引言:搜索二叉树,平衡二叉树,堆三者插入删除操作在选择题中经常出现,很容易混淆
所以在这里就简单总结一下:
一.搜索二叉树
定义:二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
a插入:
他的插入和他的查找操作类似
大体思路就是
向一个二叉排序树b中插入一个结点s的算法,过程为:
若b是空树,则将s所指结点作为根结点插入,否则:
若s->data等于b的根结点的数据域之值,则返回,否则:
若s->data小于b的根结点的数据域之值,则把s所指结点插入到左子树中,否则:
把s所指结点插入到右子树中。
此外,他的插入永远是一直插到最后面(也就是叶子结点哦)
b删除:
删除的话要分三种情况
(1)若*p结点为叶子结点,即PL(左子树)和PR(右子树)均为空树。由于删去叶子结点不破坏整棵树的结构,则只需修改其双亲结点的指针即可。
(2)若*p结点只有左子树PL或右子树PR,此时只要令PL或PR直接成为其双亲结点*f的左子树或右子树即可,作此修改也不破坏二叉排序树的特性。
(3)若*p结点的左子树和右子树均不空。在删去*p之后,为保持其它元素之间的相对位置不变,可按中序遍历保持有序进行调整,可以有两种做法:其一是令*p的左子树为*f的左子树,*s为*f左子树的最右下的结点,而*p的右子树为*s的右子树;其二是令*p的直接前驱(或直接后继)替代*p,然后再从二叉排序树中删去它的直接前驱(或直接后继)。
二.二叉平衡树
定义:平衡二叉搜索树(Self-balancing binary search tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。平衡二叉树的常用实现方法有红黑树、AVL、替罪羊树、Treap、伸展树等。 最小二叉平衡树的节点总数的公式如下 F(n)=F(n-1)+F(n-2)+1 这个类似于一个递归的数列,可以参考Fibonacci(斐波那契)数列,1是根节点,F(n-1)是左子树的节点数量,F(n-2)是右子树的节点数量。
他的本质还是二叉搜索树,不过他提出了一种叫做平衡因子的概念
他的插入删除与二叉搜索树本质上无差别,不过最大的难点在于你插入某个结点时可能会破坏其他结点的平衡因子,所以再次把树调平衡就成为了一个问题。这个问题通常有四种解决办法
4种方式
(1)右单转
(2)左单旋
(3)左右双旋
(4)右左双旋
其中LR(ABC->CBA)旋转和RL(ABC->CAB)旋,旋转要注意有个就近原则,就是只针对发现者和麻烦结点之间的三个结点调整,再上面的就不要调整了(即使最上面结点的平衡因子也被破坏了)。
三.堆
堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。首先堆是完全二叉树(只有最下面的两层结点度能够小于2,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树),其次任意节点的左右孩子(若有)值都不小于其父亲,这是小根堆,即最小的永远在上面。相反的是大根堆,即大的在上面。
因为完全二叉树有很好的规律,因此可以只用数据来存储数据而不需要链表。
不知道你看没看懂,简单总结一下,就是堆必须满足一下两个特性
(1)堆的插入(最大)
你一个很自然的想法就是插入到数组的最后,所以
此时没有破坏堆的有序性
此时有序性被破坏,所以交换35与31即可
这个也一个道理,只不过要调整两次
堆的删除操作:
这个ppt说的不太明白可能,大体的意思就是把堆顶删除,把最后一个元素补上去,然后把这个新的完全二叉树(暂时还不是堆)调整成一个堆
四.练一练就会啦
不知道你们看懂没?
其实这仨都有一个特点
二叉搜索树就是按照规则一直插入
二叉平衡树和堆则是在插入删除的同时是都要调整使其本身满足自己的特性
举几个例题:
二叉搜索树
1.
难点在于画图,画对了就做对了
二叉平衡树
2.
要注意平衡因子为左子树树高减去右子树树高
堆
3.说个复杂点的hh
其实只要了解堆的删除过程就还好啦
如果还不会的话有啥问题都可以问,想要更多例题我之后也可以补充