标签:
6. 蛤蟆的数据结构进阶六之二叉树排序树
本篇名言:“有些人因为贪婪,想得更多的东西,却把现在所有的也失掉了。 -- 伊索”
关于理论知识已经在上篇中进行描述,这篇我们主要来看下如何是实现二叉排序树。
欢迎转载,转载请标明出处:
二叉排序树(BinarySort Tree)又称二叉查找(搜索)树(Binary Search Tree)。其定义为:二叉排序树或者是空树,或者是满足如下性质的二叉树:
①若它的左子树非空,则左子树上所有结点的值均小于根结点的值;
②若它的右子树非空,则右子树上所有结点的值均大于根结点的值;
③左、右子树本身又各是一棵二叉排序树。
上述性质简称二叉排序树性质(BST性质),故二叉排序树实际上是满足BST性质的二叉树。
如下结构体
typedef struct
{
KeyTypekey; //关键字域
} ElemType;
typedef struct BiTNode //定义二叉树二叉链表
{
ElemType data;
struct BiTNode*lchild, *rchild;
}BiTNode,*BiTree,*SElemType;
typedef struct
{
SElemType*base;
SElemType*top;
intstacksize;
}SqStack;
定义元素类型。
定义二叉树二叉链表。
最后定义一个堆栈。
运行过程中,输入节点数值为:{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:先序遍历也叫做先根遍历、前序遍历,可记做根左右(二叉树父结点向下先左后右)。
中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树。在遍历左、右子树时,仍然先遍历左子树,再访问根结点,最后遍历右子树。
后序遍历首先遍历左子树,然后遍历右子树,最后访问根结点,在遍历左、右子树时,仍然先遍历左子树,然后遍历右子树,最后遍历根结点。
输入参数为二叉树指针,关键值,根节点,以及另一个二叉树变量地址p用于接受返回值。
查找关键字,指针p返回。
首先判断二叉树是否为空,为空则直接返回FALSE。
不会空,判断关键值是否和二叉树的中值相等。
如果相等则返回二叉树指针,并返回OK。
否则则进行递归调用。小于根节点则从左子树开始递归,否则从右子树开始递归。
输入参数为二叉树指针是元素。
也再一次判断是会否存在相同元素,如果存在退出。
否则,则分配一个空间,这个该值为输入的元素。
然后设置左右子节点为NULL。
接着判断是否是根节点,如果是则将钙元素设置为根。
否则,判断是大于叶子节点,设置为左或者右。
判断二叉树是否为空,不会空则递归调用ShowBST,从右节点开始输出,然后是中间,最后是左节点。
输入二叉树指针和关键词。
如果二叉树为空则返回。
判断是否和当前指针的data相等,相等则调用DELETE函数进行删除。
否则判断是否小于当前指针的data,小于则递归从左子节点继续删除。
然后从右子节点继续删。
先判断右子树是否为空,如果右子树为空,那么释放中节点,保留左子树(此时并不知道左子树是否为空)。
如果右子树不为空,左子树也为空,那么释放中节点,保留右子树。
如果都不为空,从左子树的右节点开始,找到左子树的最右叶子节点。
将当前值设置为该值,因为其左子树的最右叶子节点,肯定比左子树大,而比右子树小的。
排序需要用到堆栈了。
先调用InitStack函数来初始化堆栈,得到堆栈地址。
判断堆栈是否为空或者p是否为空。(p的初始值为二叉树)
如果不为空则进行压栈,然后调用Visit函数来输出节点,然后取p的左节点。
如果p为空,调用Pop函数从堆栈弹出一个值。取右节点。
以此循环。
函数来输出节点的值。
如果空间还有空间,则直接返回栈顶指针。如果不够,怎将堆栈进行重新分配。
如果到栈底,则返回ERROR。
否则返回栈顶元素。
中序遍历,类似先序遍历。
先一直压栈左节点数,直到左节点数为空。
然后弹出一个,输出值,再去弹出值的右节点数。
后序遍历。
P初始化为二叉树指针。
相比前序和中序遍历,略微复杂一点。
使用两个堆栈S和SS。
将右节点一致压栈到两个堆栈,直到为空。
然后从S堆栈弹出一个,获取该弹出值的左节点。继续上个查找右节点的操作。直到p为空,且堆栈S为空。
然后从堆栈SS中挨个输出值。
将二叉树的根节点幅值为NULL。
分配堆栈。返回堆栈基地址。
将堆栈底和堆栈顶放在同一个地址。
#include "stdio.h"
#include "stdlib.h"
#define KeyType int
#define EQ(a,b)((a)==(b))
#define LT(a,b)((a)< (b))
#define LQ(a,b)((a)<=(b))
#define TRUE 1
#define FALSE 0
#define STACK_INIT_SIZE100
#define OVERFLOW-1
#define OK 1
#define STACKINCREMENT10
#define ERROR-1
typedef struct
{
KeyTypekey; //关键字域
} ElemType;
typedef struct BiTNode //定义二叉树二叉链表
{
ElemType data;
struct BiTNode*lchild, *rchild;
}BiTNode,*BiTree,*SElemType;
typedef struct
{
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(BiTree T,KeyType key,BiTree f,BiTree&p) //查找关键字,指针p返回
{
if(!T)
{
p=f;
return FALSE;
}
else if EQ(key,T->data.key)
{
p=T;
return TRUE;
}
else if LT(key,T->data.key)
returnSearchBST(T->lchild,key,T,p);
else
returnSearchBST(T->rchild,key,T,p);
}
int InsertBST(BiTree&T,ElemType e) //插入节点元素
{
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;
else if LT(e.key,p->data.key)
p->lchild=s;
else
p->rchild=s;
return TRUE;
}
else return FALSE;
}
int ShowBST(BiTree T,int nlayer) //显示树形二叉排序树
{
inti;
if(T==NULL)
return FALSE;
ShowBST(T->rchild,nlayer+1);
for(i=0;i<nlayer;i++)
printf(" ");
printf("%d\n",T->data);
ShowBST(T->lchild,nlayer+1);
return OK;
}
int Visit(ElemType e) //Visit函数
{
printf("%d",e.key);
return OK;
}
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;
return OK;
}//InitStack
int Push(SqStack&S, SElemType e) //插入元素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;
return OK;
}//Push
int Pop(SqStack&S,SElemType&e) //删除栈顶,应用e返回其值
{
if(S.top==S.base) return ERROR;
e=*--S.top;
return OK;
}//Pop
int StackEmpty(SqStack S) //判断是否为空栈
{
if(S.base==S.top)return TRUE;
return FALSE;
}
int PreOrderTraverse(BiTree T,int(*Visit)(ElemTypee)) //先序遍历,运用栈
{
SqStackS;
BiTreep;
InitStack(S);
p=T;
while(p||!StackEmpty(S))
{
if(p)
{
Push(S,p);
if(!Visit(p->data))return ERROR;
p=p->lchild;
}
else
{
Pop(S,p);
p=p->rchild;
}
}
return OK;
}
int InOrderTraverse(BiTree T, 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))return ERROR;
p=p->rchild;
}
}
return OK;
}
int PostOrderTraverse(BiTree T,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))return ERROR;
}
return OK;
}
int Delete(BiTree&p) // 三种删除节点的操作实现
{
BiTreeq,s;
if(!p->rchild) //右子树为空
{
q=p;
p=p->lchild;
free(q);
}
else if(!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;
}
return TRUE;
}
int DeleteBST(BiTree&T,KeyType key) //实现二叉排序树的删除操作
{
if(!T)
return FALSE;
else
{
if (EQ(key,T->data.key)) //T->data.key等于key
returnDelete(T);
else if (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);
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/notbaron/article/details/47304373