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);

}

 

 

 

 

 

 

 

 

 

 

原创粉丝点击