二叉树的链式查询

原地址:https://blog.csdn.net/xgf415/article/details/51190649

二叉树是非线性结构,即每个数据结点至多只有一个前驱,但可以有多个后继。它可采用顺序存储结构和链式存储结构。

二叉树的顺序存储,就是用一组连续的存储单元存放二叉树中的结点。因此,必须把二叉树的所有结点安排成为一个恰当的序列,结点在这个序列中的相互位置能反映出结点之间的逻辑关系,用编号的方法从树根起,自上层至下层,每层自左至右地给所有结点编号,缺点是有可能对存储空间造成极大的浪费。依据二叉树的性质,完全二叉树和满二叉树采用顺序存储比较合适。

二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。
通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址。其结点结
构为:


其中,data域存放某结点的数据信息;lchild与rchild分别存放指向左孩子和右孩子的指针,当左孩子或右孩子不存在时,相应指针域值为空。利用这样的结点结构表示的二叉树的链式存储结构被称为二叉链表,如下图所示:


二叉树链式存储结构定义为:

[cpp]  view plain  copy
  1. typedef struct bnode  
  2. {  
  3.     char data;  
  4.     struct bnode *lchild,*rchild;  
  5. }B,*BTree;  

二叉树的遍历

1.先序遍历:根节点、左子树、右子树

先序遍历算法(递归):

扫描二维码关注公众号,回复: 2411117 查看本文章
[cpp]  view plain  copy
  1. void preorder(BTree t)      //先序遍历  
  2. {  
  3.     if(t)  
  4.     {  
  5.         visit(t->data );        //访问节点数据,自定义访问函数visit  
  6.         preorder (t->lchild );      //递归遍历左子树  
  7.         preorder (t->rchild );      //递归遍历右子树  
  8.     }  
  9. }  
先序遍历结果:A、B、D、C、E、F

2.中序遍历:左子树、根节点、右子树

中序遍历算法(递归):

[cpp]  view plain  copy
  1. void inorder(BTree t)       //中序遍历  
  2. {  
  3.     if(t)  
  4.     {  
  5.         inorder (t->lchild );  
  6.         visit(t->data );        //访问节点数据  
  7.         inorder (t->rchild );  
  8.     }  
  9. }  

中序遍历结果:D、B、A、E、C、F

3.后序遍历:左子树、右子树、根节点

后序遍历算法(递归):

[cpp]  view plain  copy
  1. void postorder(BTree t)     //后序遍历  
  2. {  
  3.     if(t)  
  4.     {  
  5.         postorder (t->lchild );  
  6.         postorder (t->rchild );  
  7.         visit(t->data );        //访问节点数据  
  8.     }  
  9. }  

后序遍历结果:D、B、E、F、C、A

节点数、高度、每层节点数

[cpp]  view plain  copy
  1. int count(BTree t)      //计算二叉树节点数  
  2. {  
  3.     int lcount,rcount;  
  4.     if(t==NULL) return 0;  
  5.     lcount=count(t->lchild );       //左子树节点数  
  6.     rcount =count(t->rchild );      //右子树节点数  
  7.     return(lcount +rcount +1);  
  8. }  
  9. int height(BTree t)     //计算二叉树的高度  
  10. {  
  11.     int h1,h2;  
  12.     if(t==NULL) return 0;  
  13.     h1=height (t->lchild );     //左子树高度  
  14.     h2=height (t->rchild );     //右子树高度  
  15.     if(h1>h2) return h1+1;  
  16.     return h2+1;  
  17. }  
  18. void Levcount(BTree t,int L,int num[])      //计算二叉树每层节点数  
  19. {  
  20.     if(t)  
  21.     {  
  22.         num[L]++;  
  23.         Levcount (t->lchild ,L+1,num);  
  24.         Levcount (t->rchild ,L+1,num);  
  25.     }  
  26. }  

二叉排序树

任一节点左子树中的所有节点值都不大于根节点值;右子树中所有节点的值都不小于根节点值;左右子树也均为二叉排序树。

根据二叉树的中序遍历算法可以推断,二叉排序树的中序遍历结果是严格递增的。

二叉排序树建立

[cpp]  view plain  copy
  1. void insertBTree(BTree &t,char x)  
  2. {  
  3.     BTree r;  
  4.     if(t==NULL)     //二叉树为空时  
  5.     {  
  6.         r=(BTree )malloc(sizeof(B ));  
  7.         r->data =x;  
  8.         r->lchild =r->rchild =NULL;  
  9.         t=r;  
  10.         return;  
  11.     }  
  12.     else  
  13.     {  
  14.         if(x<t->data)       //新节点数据小于根节点  
  15.             insertBTree (t->lchild ,x);     //递归调用插入左子树  
  16.         else   
  17.             insertBTree (t->rchild ,x);     //递归调用插入右子树  
  18.     }  
  19. }  

二叉排序树搜索

[cpp]  view plain  copy
  1. BTree searchBTree(BTree t,char s)//在二叉排序树中查找值为s的节点  
  2. {  
  3.     if(t==NULL) return NULL;  
  4.     if(t->data ==s) return t;  
  5.     if(t->data >s)  
  6.         return searchBTree (t->lchild ,s);      //在左子树中查找  
  7.     else  
  8.         return searchBTree (t->rchild ,s);      //在右子树中查找  
  9. }  

查找双亲节点

[cpp]  view plain  copy
  1. BTree searchBTree2(BTree t,char s)      //查找双亲节点  
  2. {  
  3.     if(t==NULL || t->data ==s)  return NULL;   //s节点对应根节点  
  4.     if(t->lchild ->data ==s || t->rchild ->data ==s)  return t;     //节点的左或右孩子节点值为s,即为双亲节点  
  5.     if(t->data >s)  
  6.         return searchBTree (t->lchild ,s);      //在左子树中查找  
  7.     else  
  8.         return searchBTree (t->rchild ,s);      //在右子树中查找  
  9. }  

二叉排序树删除节点

p为被删节点,f为双亲节点,需要分下面三中情况:

1. p节点为叶子节点(即左右子树均为空),直接删除,不影响树的结构;

2. p节点没有左子树,把f节点指向p节点的指针指向p的右子树;

3. p节点有左子树,从p节点的左子树中选择节点值最大的节点s,将s的值复制给p,再将指向s的指针指向s的左子树。

[cpp]  view plain  copy
  1. int deleteBTree(BTree &t,char x)  
  2. {  
  3.     BTree f,p,q,s;  
  4.     p=searchBTree (t,x);        //找到x所在节点  
  5.     f=searchBTree2 (t,x);       //找到p节点的双亲节点  
  6.     if(p==NULL) return 0;  
  7.     if(p->lchild ==NULL)  
  8.     {  
  9.         if(f==NULL)     //被删节点为跟节点  
  10.             t=p->rchild ;  
  11.         else if(f->lchild ==p)      //p为双亲节点的左节点  
  12.             f->lchild =p->rchild ;  
  13.         else  
  14.             f->rchild =p->rchild ;  
  15.         free(p);  
  16.         free(f);  
  17.     }  
  18.     else if(p->lchild !=NULL)       //p节点有左子树  
  19.     {  
  20.         q=p;  
  21.         s=p->lchild ;  
  22.         while(s->rchild )       //找到p节点左子树中值最大的节点  
  23.         {  
  24.             q=s;  
  25.             s=s->rchild ;  
  26.         }  
  27.         if(q==p)        //p节点没有右子树  
  28.             q->lchild =s->lchild ;  
  29.         else  
  30.             q->rchild =s->lchild ;  
  31.         p->data =s->data ;      //将s节点值复制给p  
  32.         free(s);  
  33.         return 1;  
  34.     }  
  35.     else        //p为叶子节点  
  36.     {  
  37.         if(f->lchild ==p)       //p为双亲节点的左孩子  
  38.             f->lchild =NULL;  
  39.         else        //p为双亲节点的右孩子  
  40.             f->rchild =NULL;  
  41.         free(p);  
  42.         return 1;  
  43.     }  
  44. }  

猜你喜欢

转载自blog.csdn.net/hh1258414454/article/details/79928624