算法复习-红黑树-c++实现

#pragma once

#include "my_sorting.h"
#include <vector>

class RBTree
{
private:
	struct TreeNode
	{
		int val;
		char color;
		TreeNode* left;
		TreeNode* right;
		TreeNode* fa;
		TreeNode(int v): val(v), left(0), right(0), fa(0), color('b'){}
		~TreeNode(){cout<<"node val at "<<val<<" has been deleted!\n";}
	};
	TreeNode *root;
	int nodenum;

public:
	RBTree(void): root(0){}

	// 快速设置左右孩子
	void setright(TreeNode* nd, TreeNode* nd1){
		if (nd) nd->right = nd1;
		if (nd1) nd1->fa = nd;
	}
	void setleft(TreeNode* nd, TreeNode* nd1){
		if (nd) nd->left = nd1;
		if (nd1) nd1->fa = nd;		
	}

	// 中序遍历
	void printinoder(TreeNode *nd)
	{
		if(nd){
			printinoder(nd->left);
			cout<<nd->val<<" ";
			printinoder(nd->right);
		}
	}

	// 找到值为v的节点,返回其指针
	TreeNode* find(int v){
		TreeNode *nd = root;
		while(nd && nd->val!=v){
			if (v < nd->val)
				nd = nd->left;
			else
				nd = nd->right;
		}
		return nd;
	}

	// 左旋操作
	void left_rotate(TreeNode* x){
		TreeNode* y = x->right;
		if(!y) // 左旋操作中x的右节点必须非空
			return;
		setright(x, y->left);
		y->fa = x->fa;
		if (x==root)
			root = y;
		else{
			if(x==x->fa->left)
				setleft(x->fa, y);
			else
				setright(x->fa, y);
		}
		setleft(y, x);
	}
		
	// 右旋操作
	void right_rotate(TreeNode* x){
		TreeNode* y = x->left;
		if(!y) // 左旋操作中x的右节点必须非空
			return;
		setleft(x, y->right);
		y->fa = x->fa;
		if (x==root)
			root = y;
		else{
			if(x==x->fa->right)
				setright(x->fa, y);
			else
				setleft(x->fa, y);
		}
		setright(y, x);
	}

	// 红黑树插入节点
	void RB_insert(int v){
		nodenum ++;
		if(!root){
			root = new TreeNode(v);
			return;
		}
		TreeNode* pre, *nd = root;
		bool isright;
		while(nd){
			pre = nd;
			if (v < nd->val){
				nd = nd->left;
				isright = false;
			}else{
				nd = nd->right;
				isright = true;
			}
		}
		TreeNode *z = new TreeNode(v);;
		if(isright)
			setright(pre,z);
		else
			setleft(pre,z);
		z->color = 'r';
		RB_insert_fix_up(z);
	}

	// 删除操作!比较复杂,先不写了

	// 插入后调整,保持红黑属性
	void RB_insert_fix_up(TreeNode* z){
		while(z->fa && z->fa->color=='r'){ // 在z的父为红的情况下进行循环
			if(!z->fa->fa)
				break; // 如果z没有祖父节点,则退出
			if(z->fa==z->fa->fa->left){
				TreeNode* y = z->fa->fa->right; // y为z的叔节点
				if(y && y->color=='r'){ // 1、父、叔皆红,则将祖父置红,父、叔置黑
					z->fa->color ='b';
					y->color = 'b';
					z->fa->fa->color = 'r';
					z = z->fa->fa; // z向上回溯置祖父节点
				}else{		
					if (z==z->fa->right){ // 2、父红叔黑,且z为其父的右孩子(2完成后一定会到3)
						z = z->fa;
						left_rotate(z);
					}
					z->fa->color = 'b'; // 3、父红叔黑,且z为其父的左孩子
					z->fa->fa->color = 'r';
					right_rotate(z->fa->fa);
				}
			}else{ // 对称情况
				TreeNode* y = z->fa->fa->left; 
				if(y && y->color=='r'){ 
					z->fa->color ='b';
					y->color = 'b';
					z->fa->fa->color = 'r';
					z = z->fa->fa;
				}else{		
					if (z==z->fa->left){ 
						z = z->fa;
						right_rotate(z);
					}
					z->fa->color = 'b'; 
					z->fa->fa->color = 'r';
					left_rotate(z->fa->fa);
				}
			}
			root->color = 'b';
		}
	}

	TreeNode* getroot(){return root;}

	// 按层打印树
	void printlevel(){
		vector<vector<int> > res;
		vector<TreeNode*> q(1,root);
		TreeNode* nd;
		int level=0;
		while(!q.empty()){
			int sz=q.size();
			res.push_back(vector<int>());
			for(int i=0;i<sz;i++){
				nd = q.front();
				res[level].push_back(nd->val);
				q.erase(q.begin());
				if(nd->left) q.push_back(nd->left);
				if(nd->right) q.push_back(nd->right);
			}
			level++;
		}
		for (int i=0;i<level;i++){
			for(size_t j=0;j<res[i].size();j++)
				cout<<res[i][j]<<' ';
			cout<<endl;
		}
	}


};


性能测试:

		RBTree rbt;
		for (int i=0;i<n;i++)
			rbt.RB_insert(i);
		rbt.printinoder(rbt.getroot()); // n=10^5 时耗时 0.172 秒(性能非常好!)
		rbt.printlevel();

n=15时结果如下:


可见中序遍历无误,将按层打印结果还原为二叉树,可得:


其中黑色节点用圆圈标识,从图中可见,树的黑高为3,树的最长路径为6,最短为3,符合红黑性质(最长/最短<=3)最长路径不会比最短路径长出2倍


补充红黑树的几条性质如下(图片来自算法导论):



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值