- 引出
基于BST极端情况(链表)引出了平衡二叉树,又分为高度 和颜色上的平衡,AVL和RBT。AVL——树中任一结点的左右子树高度差不超过1。仅查询用AVL较多,对于删除和插入操作,为了维护高度上绝对平衡开销过大。RBT则是放弃了这种绝对平衡,实现大致平衡
- 特性
1.结点要么黑色要么红色
2.根节点是黑的
3.不能有两个红的构成父子关系
4.哨兵都是黑的,叶子结点有两个黑哨兵;如果一个结点只有左孩子,那它的右孩子是一个黑哨兵(NULL),反之亦然。
5.从任意一个结点到其子孙叶结点的所有路径上包含相同数目的黑结点。
由此推出结论6,7:
6.没有一条路径会比其他路径超过两倍,最短路径全黑,最长路径黑红数相同
7.时间复杂度log2n
- 红黑树的添加
定义树的数据结构,多了个父亲关系和颜色
typedef struct tree { int nValue; int Color; struct tree *pLeft; struct tree *pRight; struct tree *pFather; }RBTree;
为了保证平衡树的特性,在进行添加或者删除操作后结构可能不平衡了,所以需要引入旋转操作维持其平衡。对A左旋即A变成一个左节点
左旋操作图:
1 void RRotate(RBTree **pTree,RBTree *pNode) 2 { 3 //pNode 存待旋转点A地址,pTree则存指向这棵树的指针地址 4 RBTree *pMark = pNode->pLeft;//标记B,改变A的孩子关系后找不到B 5 6 //孩子关系 7 //A的左是C 8 pNode->pLeft = pMark->pRight; 9 //B的右是A 10 pMark->pRight = pNode; 11 12 13 if(pNode->pFather == NULL) 14 { 15 //**************换根,树改变了******** 16 *pTree = pMark; 17 //pMark->pFather = NULL; X是否存在这句话都能写,无所谓 18 19 } 20 else 21 { 22 //B是X的左或右子树 23 if(pNode->nValue < pNode->pFather->nValue) 24 { 25 pNode->pFather->pLeft = pMark; 26 } 27 else pNode->pFather->pRight = pMark; 28 } 29 //父亲关系 30 //C存在? 31 if(pNode->pLeft != NULL) 32 { 33 //C的父亲是A 34 pNode->pLeft->pFather = pNode; 35 } 36 //B的父亲是X 37 pMark->pFather = pNode->pFather; 38 //A的父亲变成B 39 pNode->pFather = pMark; 40 }
多种不平衡解决方式图示: