zoukankan      html  css  js  c++  java
  • 第13章 红黑树

    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<queue>
    #define RED 1
    #define BLACK 0
    using namespace std;
    struct node{
    	int color;
    	int key;
    	node* left;
    	node* right;
    	node* parent;
    };
    
    //左旋
    void leftRotate(node* &root, node* x)
    {
    	node* y = x->right;
    	if (x->right = y->left) y->left->parent = x;
    	if (y->parent = x->parent){
    		if (x == x->parent->left) x->parent->left = y;
    		else x->parent->right = y;
    	}
    	else root = y;
    	x->parent = y;
    	y->left = x;
    }
    //右旋(x-y,left-right)
    void rightRotate(node* &root, node* y)
    {
    	node* x = y->left;
    	if (y->left = x->right) x->right->parent = y;
    	if (x->parent = y->parent){
    		if (y = y->parent->right) y->parent->right = x;
    		else y->parent->left = x;
    	}
    	else root = x;
    	y->parent = x;
    	x->right = y;
    }
    void RBinsertFixup(node* &root, node* z)
    {
    	while (z->parent && z->parent->color == RED){
    		if (z->parent == z->parent->parent->left){	//父节点为左支
    			node* y = z->parent->parent->right;
    			if (y&&y->color == RED){					//case 1:父节点及其兄弟节点为RED。处理如下:
    				z->parent->color = BLACK;						//父节点及其兄弟节点变为BLACK
    				y->color = BLACK;
    				y->parent->color = RED;							//祖父节点变为RED
    				z = y->parent;									//将祖父节点变为当前节点 z
    			}
    			else{										
    				if (z == z->parent->right){				//case 2:父节点为RED,叔叔节点为BLACK,且 z 为父节点的右子节点。处理如下:
    					z = z->parent;								//对父节点进行左旋操作,使之成为 case 3
    					leftRotate(root, z);
    				}										
    														//case 3:父节点为RED,叔叔节点为BLACK,且 z 为父节点的左子节点。处理如下:
    				z->parent->color = BLACK;						//父节点变为 BLACK
    				z->parent->parent->color = RED;					//祖父节点变为 RED
    				rightRotate(root, z->parent->parent);			//对祖父节点进行右旋
    			}
    		}
    		else{										//父节点为右支
    			node *y = z->parent->parent->left;
    			if (y&&y->color == RED){
    				z->parent->color = BLACK;
    				y->color = BLACK;
    				y->parent->color = RED;
    				z = y->parent;
    			}
    			else{
    				if (z == z->parent->left){
    					z = z->parent;
    					rightRotate(root, z);
    				}
    
    				z->parent->color = BLACK;
    				z->parent->parent->color = RED;
    				leftRotate(root, z->parent->parent);
    			}
    		}
    	}
    	root->color = BLACK;
    }
    void RBinsert(node* &root, int val)
    {
    	node* z = (node*)malloc(sizeof(node));
    	node *y = NULL, *x = root;
    	while (x){
    		y = x;
    		if (x->key > val) x = x->left;
    		else if (x->key < val) x = x->right;
    		else return;
    	}
    	z->parent = y;
    	if (y == NULL) root = z;
    	else if (y->key > val) y->left = z;
    	else y->right = z;
    	z->left = z->right = NULL;
    	z->key = val;
    	z->color = RED;
    	RBinsertFixup(root, z);
    }
    void RBtransplant(node* &root, node* u, node* v)
    {
    	if (u->parent == NULL) root = v;
    	else if (u == u->parent->left) u->parent->left = v;
    	else u->parent->right = v;
    	if (v) v->parent = u->parent;
    }
    void RBdeleteFixup(node* &root, node* x,node* p_x)
    {
    	node *w;								// x 的父节点的兄弟节点
    	while ((!x || x->color == BLACK) && x != root){
    		if (x == p_x->left){				// x 的父节点为祖父节点的左支
    			w = p_x->right;
    			if (w->color == RED){				//case 1: w 是 RED,通过左旋,使之成为 case 2,3,4:
    				w->color = BLACK;
    				p_x->color = RED;
    				leftRotate(root, p_x);
    				w = p_x->right;
    			}									
    			if ((w->left == NULL || w->left->color == BLACK) && (w->right == NULL || w->right->color == BLACK)){
    				w->color = RED;					//case 2: w 是 BLACK, 左 BLACK 右 BLACK
    				x = p_x;
    				p_x = p_x->parent;
    			}
    			else{								
    				if (w->right == NULL || w->right->color == BLACK){
    					if (w->left) w->left->color = BLACK;		//case 3: w 是 BLACK, 左 RED 右 BLACK
    					w->color = RED;
    					rightRotate(root, w);
    					w = p_x->right;
    				}
    				w->color = p_x->color;							//case 4: w 是 BLACK, 右 RED
    				p_x->color = BLACK;
    				if (w->right) w->right->color = BLACK;
    				leftRotate(root, p_x);
    				break;
    			}
    		}
    		else{								// x 的父节点为祖父节点的右支
    			w = p_x->left;
    			if (w->color == RED){
    				w->color = BLACK;
    				p_x->color = RED;
    				rightRotate(root, p_x);
    				w = p_x->left;
    			}
    			if ((w->left == NULL || w->left->color == BLACK) && (w->right == NULL || w->right->color == BLACK)){
    				w->color = RED;
    				x = p_x;
    			}
    			else{
    				if (w->left == NULL || w->left->color == BLACK){
    					if (w->right) w->right->color = BLACK;
    					w->color = RED;
    					leftRotate(root, w);
    					w = p_x->left;
    				}
    				w->color = p_x->color;
    				p_x->color = BLACK;
    				if (w->left) w->left->color = BLACK;
    				rightRotate(root, p_x);
    				break;
    			}
    		}
    	}
    	if (x) x->color = BLACK;
    }
    node* RBdelete(node* &root, int val)
    {
    	node* z = root;
    	while (z){
    		if (z->key > val) z = z->left;
    		else if (z->key < val) z = z->right;
    		else break;
    	}
    	if (z == NULL) return NULL;
    	node* y = z, *x, *p_x;
    	int colory = y->color;
    	if (z->left == NULL){
    		x = z->right;
    		p_x = z->parent;
    		RBtransplant(root, z, z->right);
    	}
    	else if (z->right == NULL){
    		x = z->left;
    		p_x = z->parent;
    		RBtransplant(root, z, z->left);
    	}
    	else{
    		y = z->right;
    		while (y->left) y = y->left;
    		colory = y->color;
    		x = y->right;
    		p_x = y->parent;
    		z->key = y->key;
    		RBtransplant(root, y, y->right);
    	}
    	free(y);
    	if (colory == BLACK){
    		RBdeleteFixup(root, x, p_x);
    	}
    	return x;
    }
    void printRB(node* root)
    {
    	node *p;
    	queue<node*> q;
    	q.push(root);
    	while (!q.empty()){
    		p = q.front(); q.pop();
    		if (p){
    			printf("%d", p->key);
    			if (p->color == RED) printf("r ");
    			else printf("b ");
    			q.push(p->left);
    			q.push(p->right);
    		}
    		else printf("- ");
    	}
    	printf("
    ");
    }
    int main()
    {
    	int a[] = { 11, 3, 14, 1, 7, 15, 5, 8, 4 };
    	for (int j = 1; j < 10; ++j){
    		node* root = NULL;
    		for (int i = 0; i < j; ++i)
    			RBinsert(root, a[i]);
    		printRB(root);
    	}
    	printf("
    
    ");
    	for (int k = 0; k < 9; ++k){
    		node* root = NULL;
    		for (int i = 0; i < 9; ++i)
    			RBinsert(root, a[i]);
    		node* x=RBdelete(root, a[k]);
    		printRB(root);
    	}
    
    }
    

      

  • 相关阅读:
    LINUX-----管道流及重定向
    转:vim----复制粘贴
    linux ----虚拟机无法与本地机通信
    C语言---注释
    C语言---翻译过程
    DROP--删除表
    ALTER---删除字段
    Oracle中用一条Sql实现任意的行转列拼接 多行拼接
    Oracle列操作(增加列,修改列,删除列)
    Java 把long 转换成 日期 再转换成String类型
  • 原文地址:https://www.cnblogs.com/jokoz/p/4739146.html
Copyright © 2011-2022 走看看