6. 数据结构进阶六之二叉树排序树
来源:互联网 发布:尚学堂javascript视频 编辑:程序博客网 时间:2024/05/20 23:58
6. 数据结构进阶六之二叉树排序树
:“有些人因为贪婪,想得更多的东西,却把现在所有的也失掉了。 --伊索”
关于理论知识已经在上篇中进行描述,这篇我们主要来看下如何是实现二叉排序树。
1. 二叉排序树的定义
二叉排序树(BinarySort Tree)又称二叉查找(搜索)树(Binary Search Tree)。其定义为:二叉排序树或者是空树,或者是满足如下性质的二叉树:
①若它的左子树非空,则左子树上所有结点的值均小于根结点的值;
②若它的右子树非空,则右子树上所有结点的值均大于根结点的值;
③左、右子树本身又各是一棵二叉排序树。
上述性质简称二叉排序树性质(BST性质),故二叉排序树实际上是满足BST性质的二叉树。
2. 代码实现
2.1 定义结构体
如下结构体
typedefstruct
{
KeyTypekey; //关键字域
} ElemType;
typedefstructBiTNode //定义二叉树二叉链表
{
ElemType data;
structBiTNode*lchild, *rchild;
}BiTNode,*BiTree,*SElemType;
typedefstruct
{
SElemType*base;
SElemType*top;
intstacksize;
}SqStack;
定义元素类型。
定义二叉树二叉链表。
最后定义一个堆栈。
2.2 main
运行过程中,输入节点数值为:{45 30 59 24 10 55 40 53 28 49 12 5037 62 90 88 93},
每次输入调用SearchBST函数来判断是否存在概述,如果存在则提示而不进行插入。如果不存在则调用InsertBST函数实现将数值插入到二叉树中。
然后调用ShowBST 函数来输出二叉树。
然后输入一个关键词进行删除,然后显示删除后的二叉树。
然后调用函数PreOrderTraverse来进行先序遍历,调用函数InOrderTraverse来进行中序遍历,调用函数PostOrderTraverse来进行后续遍历。调用函数ClearBiTree来清空二叉树,调用函数ClearBiTree来销毁二叉树。
PS:先序遍历也叫做先根遍历、前序遍历,可记做根左右(二叉树父结点向下先左后右)。
中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。在遍历左、右子树时,仍然先遍历左子树,再访问根结点,最后遍历右子树。
后序遍历首先遍历左子树,然后遍历右子树,最后访问根结点,在遍历左、右子树时,仍然先遍历左子树,然后遍历右子树,最后遍历根结点。
2.3 SearchBST
输入参数为二叉树指针,关键值,根节点,以及另一个二叉树变量地址p用于接受返回值。
查找关键字,指针p返回。
首先判断二叉树是否为空,为空则直接返回FALSE。
不会空,判断关键值是否和二叉树的中值相等。
如果相等则返回二叉树指针,并返回OK。
否则则进行递归调用。小于根节点则从左子树开始递归,否则从右子树开始递归。
2.4 InsertBST
输入参数为二叉树指针是元素。
也再一次判断是会否存在相同元素,如果存在退出。
否则,则分配一个空间,这个该值为输入的元素。
然后设置左右子节点为NULL。
接着判断是否是根节点,如果是则将钙元素设置为根。
否则,判断是大于叶子节点,设置为左或者右。
2.5 ShowBST
判断二叉树是否为空,不会空则递归调用ShowBST,从右节点开始输出,然后是中间,最后是左节点。
2.6 DeleteBST
输入二叉树指针和关键词。
如果二叉树为空则返回。
判断是否和当前指针的data相等,相等则调用DELETE函数进行删除。
否则判断是否小于当前指针的data,小于则递归从左子节点继续删除。
然后从右子节点继续删。
2.7 Delete
先判断右子树是否为空,如果右子树为空,那么释放中节点,保留左子树(此时并不知道左子树是否为空)。
如果右子树不为空,左子树也为空,那么释放中节点,保留右子树。
如果都不为空,从左子树的右节点开始,找到左子树的最右叶子节点。
将当前值设置为该值,因为其左子树的最右叶子节点,肯定比左子树大,而比右子树小的。
2.8 PreOrderTraverse
排序需要用到堆栈了。
先调用InitStack函数来初始化堆栈,得到堆栈地址。
判断堆栈是否为空或者p是否为空。(p的初始值为二叉树)
如果不为空则进行压栈,然后调用Visit函数来输出节点,然后取p的左节点。
如果p为空,调用Pop函数从堆栈弹出一个值。取右节点。
以此循环。
2.9 Visit
函数来输出节点的值。
2.10 Push
如果空间还有空间,则直接返回栈顶指针。如果不够,怎将堆栈进行重新分配。
2.11 Pop
如果到栈底,则返回ERROR。
否则返回栈顶元素。
2.12 InOrderTraverse
中序遍历,类似先序遍历。
先一直压栈左节点数,直到左节点数为空。
然后弹出一个,输出值,再去弹出值的右节点数。
2.13 PostOrderTraverse
后序遍历。
P初始化为二叉树指针。
相比前序和中序遍历,略微复杂一点。
使用两个堆栈S和SS。
将右节点一致压栈到两个堆栈,直到为空。
然后从S堆栈弹出一个,获取该弹出值的左节点。继续上个查找右节点的操作。直到p为空,且堆栈S为空。
然后从堆栈SS中挨个输出值。
2.14 ClearBiTree
将二叉树的根节点幅值为NULL。
2.15 ClearBiTree
2.16 InitStack
分配堆栈。返回堆栈基地址。
将堆栈底和堆栈顶放在同一个地址。
3. 源码
#include"stdio.h"
#include"stdlib.h"
#defineKeyTypeint
#defineEQ(a,b)((a)==(b))
#defineLT(a,b)((a)< (b))
#defineLQ(a,b)((a)<=(b))
#defineTRUE 1
#defineFALSE 0
#defineSTACK_INIT_SIZE100
#defineOVERFLOW-1
#defineOK 1
#defineSTACKINCREMENT10
#defineERROR-1
typedefstruct
{
KeyTypekey; //关键字域
} ElemType;
typedefstructBiTNode //定义二叉树二叉链表
{
ElemType data;
structBiTNode*lchild, *rchild;
}BiTNode,*BiTree,*SElemType;
typedefstruct
{
SElemType*base;
SElemType*top;
intstacksize;
}SqStack;
int DestroyBiTree(BiTree&T)//销毁树
{
if(T!=NULL)
free(T);
return0;
}
int ClearBiTree(BiTree&T)//清空树
{
if(T!=NULL)
{
T->lchild=NULL;
T->rchild=NULL;
T=NULL;
}
return0;
}
int SearchBST(BiTreeT,KeyTypekey,BiTreef,BiTree&p) //查找关键字,指针p返回
{
if(!T)
{
p=f;
returnFALSE;
}
elseifEQ(key,T->data.key)
{
p=T;
returnTRUE;
}
elseifLT(key,T->data.key)
returnSearchBST(T->lchild,key,T,p);
else
returnSearchBST(T->rchild,key,T,p);
}
int InsertBST(BiTree&T,ElemTypee) //插入节点元素
{
BiTrees,p;
if(!SearchBST(T,e.key,NULL,p))
{
s=(BiTree)malloc(sizeof(BiTNode));
s->data=e;
s->lchild=s->rchild=NULL;
if(!p)
T=s;
elseifLT(e.key,p->data.key)
p->lchild=s;
else
p->rchild=s;
returnTRUE;
}
elsereturnFALSE;
}
int ShowBST(BiTreeT,intnlayer) //显示树形二叉排序树
{
inti;
if(T==NULL)
returnFALSE;
ShowBST(T->rchild,nlayer+1);
for(i=0;i<nlayer;i++)
printf(" ");
printf("%d\n",T->data);
ShowBST(T->lchild,nlayer+1);
returnOK;
}
int Visit(ElemTypee) //Visit函数
{
printf("%d",e.key);
returnOK;
}
int InitStack(SqStack&S) //构造空栈
{
S.base=(SElemType*)malloc(STACK_INIT_SIZE *sizeof(SElemType));
if(!S.base)exit(OVERFLOW);
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
returnOK;
}//InitStack
int Push(SqStack&S,SElemTypee) //插入元素e为新栈顶
{
if(S.top-S.base>=S.stacksize)
{
S.base=(SElemType*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));
if(!S.base)exit(OVERFLOW);
S.top=S.base+S.stacksize;
S.stacksize+=STACKINCREMENT;
}
*S.top++=e;
returnOK;
}//Push
int Pop(SqStack&S,SElemType&e) //删除栈顶,应用e返回其值
{
if(S.top==S.base) returnERROR;
e=*--S.top;
returnOK;
}//Pop
int StackEmpty(SqStackS) //判断是否为空栈
{
if(S.base==S.top)returnTRUE;
returnFALSE;
}
int PreOrderTraverse(BiTreeT,int(*Visit)(ElemTypee)) //先序遍历,运用栈
{
SqStackS;
BiTreep;
InitStack(S);
p=T;
while(p||!StackEmpty(S))
{
if(p)
{
Push(S,p);
if(!Visit(p->data))returnERROR;
p=p->lchild;
}
else
{
Pop(S,p);
p=p->rchild;
}
}
returnOK;
}
int InOrderTraverse(BiTreeT,int(*Visit)(ElemTypee)) //中序遍历,运用栈
{
SqStackS;
BiTreep;
InitStack(S);
p=T;
while(p||!StackEmpty(S))
{
if(p)
{
Push(S,p);
p=p->lchild;
}
else
{
Pop(S,p);
if(!Visit(p->data))returnERROR;
p=p->rchild;
}
}
returnOK;
}
int PostOrderTraverse(BiTreeT,int(*Visit)(ElemTypee))//后序遍历,运用栈
{
SqStackS,SS;
BiTree p;
InitStack(S);
InitStack(SS);
p=T;
while(p||!StackEmpty(S))
{
if(p)
{
Push(S,p);
Push(SS,p);
p=p->rchild;
}
else
{
if(!StackEmpty(S))
{
Pop(S,p);
p=p->lchild;
}
}
}
while(!StackEmpty(SS))
{
Pop(SS,p);
if(!Visit(p->data))returnERROR;
}
returnOK;
}
int Delete(BiTree&p)// 三种删除节点的操作实现
{
BiTreeq,s;
if(!p->rchild) //右子树为空
{
q=p;
p=p->lchild;
free(q);
}
elseif(!p->lchild) //左子树为空
{
q=p;
p=p->rchild;
free(q);
}
else
{
q=p;
s=p->lchild;
while(s->rchild)
{
q=s;
s=s->rchild;
}
p->data=s->data;
if(q!=p)
q->rchild=s->lchild;
else
q->lchild=s->lchild;
deletes;
}
returnTRUE;
}
int DeleteBST(BiTree&T,KeyTypekey)//实现二叉排序树的删除操作
{
if(!T)
returnFALSE;
else
{
if (EQ(key,T->data.key)) //T->data.key等于key
returnDelete(T);
elseif (LT(key,T->data.key)) //T->data.key是否小于key
returnDeleteBST(T->lchild,key);
else
returnDeleteBST(T->rchild,key);
}
return0;
}
void main ()
{
inti,nlayer;
ElemTypek,d;
BiTree BT,p;
BT=NULL;
p=NULL;
nlayer=1;
printf("请输入插入的二叉树节点的数值(输入数字0结束节点赋值):\n");
scanf("%d",&k.key);
for(i=0;k.key!=NULL;i++)
{
if(!SearchBST(BT,k.key,NULL,p)) //查找关键字
{
InsertBST(BT,k); //二叉树节点数值插入
scanf("%d",&k.key);
}
else
{
printf("输入数据重复!\n");
return ;
}
}
printf("二叉排序树树形输出为:\n");
ShowBST(BT,nlayer); //树形显示二叉排序树
printf("请输入删除的数据:");
scanf("%d",&d.key);
DeleteBST(BT,d.key); //删除关键字
ShowBST(BT,nlayer);
printf("先序遍历为:"); //先序遍历、中序遍历、后序遍历
PreOrderTraverse(BT,Visit);
printf("\n中序遍历为:");
InOrderTraverse(BT,Visit);
printf("\n后序遍历为:");
PostOrderTraverse(BT,Visit);
printf("\n清空该二叉排序树.\n"); //清空二叉树
ClearBiTree(BT);
ShowBST(BT,nlayer);
printf("\n销毁该二叉排序树.\n"); //销毁二叉树
ClearBiTree(BT);
}
- 6. 数据结构进阶六之二叉树排序树
- TreeMap数据结构之排序二叉树
- 数据结构之排序二叉树操作
- 数据结构之 排序二叉树总结
- 数据结构-排序二叉树
- 数据结构之二叉查找树(BST)-(六)
- 数据结构实验之二叉树六:哈夫曼编码
- 数据结构实验之二叉树六:哈夫曼编码
- sdutoj 3345 数据结构实验之二叉树六:哈夫曼编码
- SDUT3345数据结构实验之二叉树六:哈夫曼编码
- 数据结构实验之二叉树六:哈夫曼编码
- SDUT 3345 数据结构实验之二叉树六:哈夫曼编码
- 数据结构实验之二叉树六:哈夫曼编码
- 数据结构实验之二叉树六:哈夫曼编码
- 数据结构实验之二叉树六:哈夫曼编码
- SDUTACM 数据结构实验之二叉树六:哈夫曼编码
- 数据结构实验之二叉树六:哈夫曼编码
- 数据结构实验之二叉树六:哈夫曼编码
- [USACO08NOV]玩具Toys [洛谷2917] [bzoj1229]
- 5. 数据结构进阶五动态查询
- effective java(5) 之避免创建不必要的对象
- BZOJ 1040: [ZJOI2008]骑士 环套树dp
- 实验一 、Linux操作系统的安装
- 6. 数据结构进阶六之二叉树排序树
- 归并排序
- PAT 甲级 1024. Palindromic Number (25)
- leetcode Reverse Words in a String III 反转字符串中的单词
- 实验一线性表的基本操作实现及其应用
- 7. 数据结构进阶七平衡二叉树
- springboot+jpa+jqueryeasyui重新封装
- python学习笔记——多线程(MT)
- 面试题总结