二叉树(二)

匿名 (未验证) 提交于 2019-12-02 23:05:13

二叉查找树

定义:

例如,这是一棵二叉查找树

你会发现它的任何一个结点都满足:

  • ˫С˫如果他比他的双亲小,则他是他双亲的左孩子
  • ˫С˫如果他比他的双亲小,则他是他双亲的左孩子

特点:

  • ΪֵСֵ若它的左子树不为空,则左子树上所有结点的值均小于它的根结点的值
  • Ϊֵֵ若它的右子树不为空,则右子树上所有结点的值均大于它的根结点的值
  • ҲΪ它的左、右子树也分别为二叉查找树

但是对于任意一个列表,不同的输入会构成不同的二叉查找树


建空树

结点结构定义如下:

typedef struct node* tree struct node {     int data=-1;     tree lc=NULL,rc=NULL,parent=NULL; }t[105]

二叉查找树的每个结点比普通二叉树多了指向双亲的指针

以便通过双亲找到前驱、后继


插入操作

函数:当前二叉树根结点的指针要插入的数上一个查找的节点

当向一棵二叉树插入一个结点时,要判断此结点是否比根结点大

如果比根结点大就插入左子树中,比根结点小就插入右子树中,等于根结点插入失败

若当前二叉树的根结点为空,插入成功,将该结点直接覆盖在根节点上

代码如下
bool Insert(tree T,int s,tree p)  {     int root=T->data;     if(root==-1) //插入成功     {         T->data=s;         T->parent=p;         return true;     }     else       {         if(s>root) Insert(T->lc,s,T); //递归左子树         else if(s<root) Insert(T->rc,s,T);  //递归右子树         else return false; //插入失败     } }

查找操作

普通查询:比根小往左子树走,比根大往右子树走

查找前驱与后继

任何一个节点x的前驱是小于x的最大的数

任何一个节点x的后继是大于x的最小的数

其实找前驱,就是从根节点开始,递归子树,如果当前节点大于你要找的数,就找他的左子树,反之找他的右子树,直到没有可以找的为止

但其实不用如此,x只有两种情况:有左子树和没有左子树(这还用你说)

  • 有左子树的前驱:左子树中最大的结点
  • 没有左子树的前驱:往上找,第一个具有右子树的父亲节点

以下是查找前驱的代码,后继同理

typedef struct node* tree; tree midf(Node *x) {     if(x->lc!= NULL)         return findmax(x->lc);     //如果x存在左孩子,则x的前驱为其左子树的最大结点     else     {         tree y=x->p;         while(y!=NULL&&x==y->lc)         {             x=y;             y=y->p;         }         return y;     }     //如果x没有左孩子。则查找x的最低的具有右孩子的父结点,这个节点就是x的前驱 }


删除操作

让我们想一想,在二叉树中的每一棵节点,存在哪几种状态呢?

因此,我们在删除树中的一个节点来说,也要去分情况讨论了。

1.无左子树,无右子树。

叶子结点

2.无左子树,有右子树。

3.有左子树,无右子树

4.既有左子树,也有右子树。

替代节点呢?我们发现,作为替代节点必须满足的条件是:

(因为该节点位于58节点的左子树,所以肯定比58节点的右子树所有节点都要小)。

但现在又一个问题来了:代替节点被移走后剩下的节点怎么办呢

替代节点移到了该节点上,其实就是把替代结点删除了,按照删除操作再次进行即可

因为每次的替代节点都是往下一层的,所以总有一次不需要替代节点,用前三种情况就可以搞定

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!