算法系列笔记4(红黑树)

       随机构建的二叉查找树的高度期望值为O(lgn),并不代表所有的二叉查找树的高度都为O(lgn)。但是对于有些二叉查找树的变形来说,动态集合各基本操作的性能却总是很好的,如红黑树、B树、平衡二叉树(AVL树)、跳跃表(确切的说不是树,或多或少有树的结构)、treaps(树堆)等。这里我们讲解红黑树。

       平衡的意思就是完成动态数据集的操作(minimum、maximum、search、predecessor(前驱)、successor(后继)、insert及delete)在O(lgn)时间内完成。

定义:

红黑树在二叉查找树的基础上增加了色域-red或者black。 一棵红黑树要满足下面4条性质:(1)结点要么是红的,要么是黑的。

(2)根和叶子节点都是黑的。

(3)一个结点是红的,那么它的父节点必须是黑的。

(4)任一结点到其叶子节点的简单路径上黑结点的个数要相同= 黑高度(不包括自身结点,但包括叶子节点)。

 

性质:

一个具有n个结点(不包括叶子节点)的红黑树的高度不超过2lg(n+1)。

因此这些动态集合的操作都在O(lgn)时间内能完成,所以红黑树是平衡的。

 

操作(插入和删除)

红黑树操作与二叉查找树的主要区别在于插入和删除,其它都是一样的。可参见上一篇blog。

插入:

并且红黑树只能通过插入操作来创建一棵红黑树以维持红黑特性。红黑树的插入操作分为三种情况.如下图

待传…..

其中case1为着色,可以一直可以向上移动,每次移动2层,由于树高≤2lg(n+1),所以最多循环lg(n+1)次。case2case3是终止情形,各旋转一次,都为O(1)时间。所以红黑树的插入操作可以在O(lgn)时间内完成.

代码如下:

RBTree.h

#ifndef RBTREE
#define RBTREE
#include <iostream>
#include <string>
using namespace std;

class BSTNode{
public:
	BSTNode *left, *right;
	BSTNode *parent;
	int val;
	string color;
};

class RBTree{
public:
	RBTree(const int &rootVal){
		root = new BSTNode();
		root->val = rootVal;
		root->parent = NULL;
		root->left = NULL;
		root->right = NULL;
		root->color = "black";
	}
	
	void insertRBTree(BSTNode *root, const int &value);   // 红黑树的插入
	void inorderRBTree(BSTNode *p);
	BSTNode *root;
private:
	BSTNode *insertBST(BSTNode *p, const int &value);       // 二叉树的插入
};

#endif

RBTree.cpp

#include "RBTree.h"
using namespace std;

BSTNode* RBTree::insertBST(BSTNode *p, const int &value){
	BSTNode *y = NULL;
	BSTNode *in = new BSTNode();
	in->left = NULL;
	in->right = NULL;
	in->val = value;
	in->parent = NULL;

	while(p != NULL){
		y = p;
		if(p->val > in->val) p = p->left;
		else p = p->right;
	}
	
	if(y == NULL)
		p = in;
	else{
		in->parent = y;
		if(y->val > in->val) y->left = in;
		else y->right = in;
	}
	return in;
}

void RBTree::insertRBTree(BSTNode *root1, const int &value){
	BSTNode * in = insertBST(root1, value);
	in->color = "red";
	while(in != root1 && in->color == "red"){            // 对红黑特性进行调整
		if(in->parent->color == "black") return;   //  也就保证了必须
		if(in->parent == in->parent->parent->left){
			BSTNode *y = in->parent->parent->right;
			if(y != NULL && y->color == "red"){   //  case 1
				y->color = "black";
				y->parent->color = "red";
				in->parent->color ="black";
				in = in->parent->parent;
			}
			else{
				if(in == in->parent->right){      // case 2   in->parent 左旋
					BSTNode *pa = in->parent;
					in->parent = pa->parent;
					pa->parent->left = in;
					pa->parent = in;
					if(in->left != NULL)
						in->left->parent = pa;
					pa->right = in->left;
					in->left = pa;
					in = pa;
				}
				// case 3    in->parent->parent 右旋
				BSTNode *pa = in->parent;
				BSTNode *gpa = in->parent->parent;
				if(gpa->parent != NULL){
					if(gpa == gpa->parent->left){
						gpa->parent->left = pa;
					}else
						gpa->parent->right = pa;
				}
				pa->parent = gpa->parent;
				if(pa->right != NULL)
					pa->right->parent = gpa;
				gpa->left = pa->right;
				pa->right = gpa;
				gpa->parent = pa;
				pa->color = "black";
				gpa->color = "red";
			}
		}
		else{
			BSTNode *y = in->parent->parent->left;
			if(y != NULL && y->color == "red"){   //  case 1
				y->color = "black";
				y->parent->color = "red";
				in->parent->color ="black";
				in = in->parent->parent;
			}else{                               // do the same as A  but left与right对换
				if(in == in->parent->left){      // case 2   in->parent 右旋
					BSTNode *pa = in->parent;
					in->parent = pa->parent;
					pa->parent->right = in;
					pa->parent = in;
					if(in->right != NULL)
						in->right->parent = pa;
					pa->left = in->right;
					in->right = pa;
					in = pa;
				}
				// case 3    in->parent->parent 左旋
				BSTNode *pa = in->parent;
				BSTNode *gpa = in->parent->parent;
				if(gpa->parent != NULL){
					if(gpa == gpa->parent->left){
						gpa->parent->left = pa;
					}else
						gpa->parent->right = pa;
				}
				pa->parent = gpa->parent;
				if(pa->left != NULL)
					pa->left->parent = gpa;
				gpa->right = pa->left;
				pa->left = gpa;
				gpa->parent = pa;
				pa->color = "black";
				gpa->color = "red";
			}
		}
	}
	root1->color = "black";
}


void RBTree::inorderRBTree(BSTNode *p){
	if(p == NULL) return;
	if(p->left != NULL) inorderRBTree(p->left);
	cout << p->val << p->color  << " ";
	if(p->right != NULL) inorderRBTree(p->right);
}

Main.cpp

int a[10] = {5,4,6, 7,2,4, 1, 8, 5, 10};
	RBTree rbt(a[0]);
	for(int i =1; i < 10; i++)
		rbt.insertRBTree(rbt.root, a[i]);

	cout << "中序遍历的结果: " << endl;
	rbt.inorderRBTree(rbt.root);
Result:

技术分享


删除:

待续

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。