数据结构树与二叉树的实现

目录

一、普通树的存储结构

1、双亲表示法

2.孩子表示法

二、二叉树

1.二叉树的顺序存储(必须是完全二叉树,否则很浪费空间)

1)结构体

2.二叉树的链式存储

1)结构体

2)操作

1.创建一颗二叉树

2.创建一个结点

3.二叉树的前序遍历

a.递归实现

b.非递归,使用栈

4.二叉树的中序遍历

a.递归实现

b.非递归实现

5.二叉树的后序遍历

a.递归实现

b.非递归实现

6.二叉树的层次遍历:使用队列

三、线索二叉树

1.先序线索化

2.中序线索化

3.后序线索化

4.拓展,中序线索二叉树中

1)找到以p为根,第一个为中序遍历的结点,其实就是最左边的叶节点

2)找到p的后继

3)能找到后继,就可以不使用递归来遍历了,能得到中序遍历结果

4)找到以p为根结点,最后一个被中序遍历的结点,也就是p最右边的叶子结点

5)找到p的前驱

6)逆序中序遍历

5.拓展,先序二叉树中

1)寻找后继

2)不能知道找到前驱,除非能直接找到父节点,然后再讨论

6.拓展,后续二叉树中

1)寻找前驱

2)找不到后继,除非能找到父节点,再讨论

四、二叉排序树

1.结构体

2.操作函数

1)创建一颗二叉排序树

2)创建一颗二叉排序结点

3)查找关键值所对应结点

a.递归

b.非递归

4)插入关键值

5)构造一颗二叉排序树,其实就是不断插入的过程


一、普通树的存储结构

1、双亲表示法

typedef  struct{ElemType data;int parent;
}PTNode;typedef  struct{PTNode nodes[MAXSIZE];int n;  //结点数
}PTree;

2.孩子表示法

struct CTNode{int child; //孩子在数组中的下标CTNode *next;
};typedef  struct {ElemType data;CTNode *firstChild;
}CTBox;typedef  struct{CTBox nodes[MAXSIZE];int n,r;//结点数、根的下标
}CTree;

二、二叉树

1.二叉树的顺序存储(必须是完全二叉树,否则很浪费空间)

1)结构体

struct TreeNode{ElemType value;bool isEmpty;
};TreeNode t[MAXSIZE]; //一般从下标为1开始存储,为了和下标对应起来,方便查找孩子//顺序存储初始化将所有的isEmpty变为TRUE//左孩子为2i 右孩子为2i+1  父节点为i/2//i>n/2就是叶子结点

2.二叉树的链式存储

1)结构体

//二叉树的链式存储
typedef  struct BiTNode{ElemType data;BiTNode *lchild,*rchild;
}BiTNode,*BTree;

2)操作

1.创建一颗二叉树

BTree CreatBTree(ElemType rootdata)
{BiTNode *root = (BiTNode*)malloc(sizeof(BiTNode));root->data=rootdata;root->lchild=NULL;root->rchild=NULL;return  root;
}

2.创建一个结点

BiTNode *CreatBiTNode(ElemType data)
{BiTNode* NewNode = (BiTNode*)malloc(sizeof(BiTNode));NewNode->data=data;NewNode->lchild=NULL;NewNode->rchild=NULL;return  NewNode;
}

3.二叉树的前序遍历

a.递归实现
void PreOrder(BTree T)
{if(T!=NULL){visit(T);PreOrder(T->lchild);PreOrder(T->rchild);}
}
b.非递归,使用栈
//会使用栈
void PreOrder1(BTree T)
{SqStack s;InitStack(s);BTree p =T;while (p||!StackEmpty(s)) {if(p){visit(p);push(s,p);p=p->lchild;}else {pop(s,p);p=p->rchild;}}
}

4.二叉树的中序遍历

a.递归实现
void InOrder(BTree T)
{if(T!=NULL){InOrder(T->lchild);visit(T);InOrder(T->rchild);}
}
b.非递归实现
void InOrder1(BTree T)
{SqStack s;InitStack(s);BTree p = T;while (p||!StackEmpty(s)) {if(p){push(s,p);p=p->lchild;}else {pop(s,p);visit(p);p=p->rchild;}}
}

5.二叉树的后序遍历

a.递归实现
void PostOrder(BTree T)
{if(T!=NULL){PostOrder(T->lchild);PostOrder(T->rchild);visit(T);}
}
b.非递归实现
void PostOrder1(BTree T)
{SqStack s;InitStack(s);BTree p = T;BTree r=NULL;while (p||!StackEmpty(s)) {if(p){push(s,p);p=p->lchild;}else {GetTop(s,p);if(p->rchild!=r&&p->rchild)p=p->rchild;else {pop(s,p);visit(p);r=p;p=NULL;}}}
}

6.二叉树的层次遍历:使用队列


void LevelOrder(BTree T)
{LinkQueue Q;InitLinkQueue(Q);BTree p;EnLinkQueue(Q,T);while (!LinkQueueEmpty(Q)) {DeLinkQueue(Q,p);visit(p);if(p->lchild!=NULL)EnLinkQueue(Q,p->lchild);if(p->rchild!=NULL)EnLinkQueue(Q,p->rchild);}
}

三、线索二叉树

1.先序线索化

void PreThread(ThreadTree T, ThreadTree &pre)
{if(T!=NULL){if(T->lchild==NULL){T->lchild=pre;T->ltag=1;}if(pre!=NULL and pre->rchild==NULL){pre->rchild=T;pre->rtag=1;}pre=T;if(T->ltag==0)PreThread(T->lchild,pre);PreThread(T->rchild,pre);}
}void CreatPreThread(ThreadTree T)
{ThreadTree pre= NULL;if(T!=NULL){PreThread(T,pre);pre->rchild=NULL;pre->rtag=1;}
}

2.中序线索化

void InThread(ThreadTree T,ThreadTree &pre)
{if(T!=NULL){InThread(T->lchild,pre);if(T->lchild==NULL){T->lchild=pre;T->ltag=1;}if(pre!=NULL and pre->rchild==NULL){pre->rchild=T;pre->rtag=1;}pre=T;InThread(T->rchild,pre);}}void CreatInThread(ThreadTree T)
{ThreadTree pre= NULL;if(T!=NULL){InThread(T,pre);pre->rchild=NULL;pre->rtag=1;}
}

3.后序线索化

void PostThread(ThreadTree T, ThreadTree &pre)
{if(T!=NULL){PostThread(T->lchild,pre);PostThread(T->rchild,pre);if(T->lchild==NULL){T->lchild=pre;T->ltag=1;}if(pre!=NULL and pre->rchild==NULL){pre->rchild=T;pre->rtag=1;}pre=T;}
}void CreatPostThread(ThreadTree T)
{ThreadTree pre= NULL;if(T!=NULL){PostThread(T,pre);pre->rchild=NULL;pre->rtag=1;}
}

4.拓展,中序线索二叉树中

1)找到以p为根,第一个为中序遍历的结点,其实就是最左边的叶节点

ThreadNode *FirstNode(ThreadNode *p)
{//找到最左边叶节点while (p->ltag==0) {p=p->lchild;}return  p;
}

2)找到p的后继

ThreadNode *NextNode(ThreadNode *p)
{if(p->rtag==0)return FirstNode(p->rchild);else {return p->rchild;}
}

3)能找到后继,就可以不使用递归来遍历了,能得到中序遍历结果

void InOrder1(ThreadTree T)
{for(ThreadNode *p = FirstNode(T);p!=NULL;p=NextNode(p)){visit_Thread(p);}
}

4)找到以p为根结点,最后一个被中序遍历的结点,也就是p最右边的叶子结点

ThreadNode *LastNode(ThreadNode *p)
{while (p->rtag==0) {p=p->rchild;}return  p;
}

5)找到p的前驱

ThreadNode *preNode(ThreadNode *p){if (p->ltag==0) {return LastNode(p->lchild);}else {return p->lchild;}
}

6)逆序中序遍历

void RevInOrder(ThreadTree T)
{for(ThreadNode *p = LastNode(T);p!=NULL;p=preNode(p)){visit_Thread(p);}
}

5.拓展,先序二叉树中

1)寻找后继

ThreadNode *NextNode_pre(ThreadNode *p)
{if(p->rtag==0){if(p->lchild!=NULL)return p->lchild;if(p->rchild!=NULL)return p->rchild;}else {return p->rchild;}
}

2)不能知道找到前驱,除非能直接找到父节点,然后再讨论

6.拓展,后续二叉树中

1)寻找前驱

ThreadNode *preNode_post(ThreadNode *p)
{if(p->ltag==1){return p->lchild;}else {if(p->rchild!=NULL)return p->rchild;else {return p->lchild;}}
}

2)找不到后继,除非能找到父节点,再讨论

四、二叉排序树

1.结构体

typedef  struct BSTNode{ElemType data;BSTNode *lchild,*rchild;
}BSTNode,*BSTree;

2.操作函数

1)创建一颗二叉排序树

BSTree CreatBSTree(ElemType rootdata)
{BSTNode *NewNode = (BSTNode*)malloc(sizeof (BSTNode));NewNode->data=rootdata;NewNode->lchild=NULL;NewNode->rchild=NULL;return  NewNode;
}

2)创建一颗二叉排序结点

BSTNode *CreatBSTNode(ElemType data)
{BSTNode *NewNode = (BSTNode*)malloc(sizeof (BSTNode));NewNode->data=data;NewNode->lchild=NULL;NewNode->rchild=NULL;return  NewNode;
}

3)查找关键值所对应结点

a.递归
BSTNode *BSTSearch(BSTree bt, ElemTpye key)
{if(bt==NULL)return  NULL;if(bt->data==key)return bt;else if (bt->data>key) {return BSTSearch(bt->lchild,key);}else {return  BSTSearch(bt->rchild,key);}
}
b.非递归
BSTNode *BSTSearch(BSTree bt, ElemType key)
{while(bt!=NULL and key!=bt->data){if(key<bt->data)bt=bt->lchild;else {bt=bt->rchild;}}return bt;
}

4)插入关键值

bool BSTInsert(BSTree &bt, ElemType key)
{if(bt==NULL){BSTNode *Newnode = CreatBSTNode(key);bt=Newnode;return true;}if(bt->data==key){return false;}else if(bt->data>key){return BSTInsert(bt->lchild,key);}else {return BSTInsert(bt->rchild,key);}}

5)构造一颗二叉排序树,其实就是不断插入的过程

void CreatBST(BSTree &bt, int key[], int n)//key[] 关键字数组,n 关键字数组长度
{bt = NULL;for (int i=0;i<n;i++) {BSTInsert(bt,key[i]);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/188620.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

侧面多级菜单(一个大类、一个小类、小类下多个物体)

效果&#xff1a; 说明&#xff1a; 左右侧面板使用Animator组件控制滑入滑出。左侧面板中&#xff0c;左的左里面是大类&#xff0c;左的右有绿色的小类&#xff0c;绿色的小类下有多个真正的UI图片按钮。 要点&#xff1a; 结合了一点EasyGridBuilderPro插件的UI元素&…

数字艺术藏品软件的独特创新与未来趋势

随着科技的飞速发展&#xff0c;数字艺术藏品软件逐渐崭露头角&#xff0c;为艺术爱好者们提供了一个全新的收藏方式。这类软件不仅为艺术家提供了展示作品的平台&#xff0c;也为收藏家们提供了收藏和分享艺术品的渠道。本文将从开发思路、技术实现、市场前景等方面探讨数字艺…

业务流程图用什么软件画?这10款流程图软件,好用到飞起!

业务流程图是什么&#xff1f; 业务流程图是一种用于表示业务过程中活动流向的图形表示方法&#xff0c;它使用标准化的图形元素&#xff08;如箭头、椭圆、方框等&#xff09;来表达一个过程中各个环节之间的关系。在这个图形表示中&#xff0c;每个元素都有特定的含义和功能…

(论文阅读)TiDB:一款基于Raft的HTAP数据库

引言 混合事务分析处理&#xff08;HTAP&#xff09;数据库要求隔离处理事务查询和分析查询&#xff0c;以消除它们之间的干扰。要实现这一点&#xff0c;有必要维护为这两种查询类型指定的数据的不同副本。然而&#xff0c;为存储系统中的分布式副本提供一致的视图是一项挑战…

OSPF开放最短路径优先(Open Shortest Path First)协议

OSPF开放最短路径优先(Open Shortest Path First)协议 为克服RIP的缺点(限制网络规模&#xff0c;坏消息传得慢)在1989年开发出来的原理很简单&#xff0c;但实现很复杂使用了Dijkstra提出的最短路径算法SPF(Shortest Path First)采用分布式的链路状态协议(link state protoco…

Postman实现接口的文件上传

近期在复习Postman的基础知识&#xff0c;在小破站上跟着百里老师系统复习了一遍&#xff0c;也做了一些笔记&#xff0c;希望可以给大家一点点启发。 接口的文件上传&#xff0c;与其他接口的传参差不多&#xff0c;只要点击form-data&#xff0c;选择要上传的文件即可。 实际…

2024年山东省职业院校技能大赛中职组“网络安全”赛项竞赛试题-A

2024年山东省职业院校技能大赛中职组 “网络安全”赛项竞赛试题-A 一、竞赛时间 总计&#xff1a;360分钟 二、竞赛阶段 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 A、B模块 A-1 登录安全加固 180分钟 200分 A-2 本地安全策略设置 A-3 流量完整性保护 A-4 …

怎么为pdf加水印?

怎么为pdf加水印&#xff1f;最近很多小伙伴都有这样的疑问。你可以在浏览器上搜索一下&#xff0c;关于这方面的很多还是有很多人不是很清楚的。虽然我们自己在很多PDF文件上都看到了水印&#xff0c;那么真的到了自己这边需要进行操作的时候&#xff0c;确实还是有些这样或是…

Python最强自动化神器..

1、Playwright介绍 Playwright是一个由Microsoft开发的开源自动化测试工具&#xff0c;它可以用于测试Web应用程序。Playwright支持多种浏览器&#xff0c;包括Chrome、Firefox和WebKit&#xff0c;同时也支持多种编程语言&#xff0c;如JavaScript、TypeScript、Python和C#。…

如何确保消息不会丢失

本篇文章大家还可以通过浏览我的博客阅读。如何确保消息不会丢失 - 胤凯 (oyto.github.io)很多人刚开始接触消息队列的时候&#xff0c;最经常遇到的一个问题就是丢消息了。<!--more-->对于大部分业务来说&#xff0c;丢消息意味着丢数据&#xff0c;是完全无法接受的。 …

软件测试之接口自动化测试实战

接口自动化测试是指通过编写程序来模拟用户的行为&#xff0c;对接口进行自动化测试。Python是一种流行的编程语言&#xff0c;它在接口自动化测试中得到了广泛应用。下面详细介绍Python接口自动化测试实战。 1、接口自动化测试框架 在Python接口自动化测试中&#xff0c;我们…

DS二叉树的存储

前言 我们上一期已经介绍了树相关的基础知识&#xff0c;了解了树相关的概念和结构、二叉树的概念和结构以及性质、也介绍了他的存储方式&#xff01;本期我们来根据上期介绍的对二叉树的顺序存储和链式存储分别进行实现&#xff01; 本期内容介绍 二叉树的顺序结构 堆的概念…