红黑数实现

之前的作业,代码中还有需要完善的地方,如内存管理等,先贴上实现代码,后续会对红黑树的具体实现进行分析。


// 红黑树.cpp : Defines the entry point for the console application.
// author: sqxu

#include "stdafx.h"
#include <iostream>
using namespace std;

const int red=0;
const int black=1;

typedef struct rbtree 
{
    int key; //关键字
    int color; //颜色
    struct rbtree * parent; //指向父结点的指针
    struct rbtree * left; //指向左孩子的指针
    struct rbtree * right; //指向右孩子的指针
}RBT; //定义结构体RBT

void leftRotate(RBT ** root, RBT * x); //左旋函数
void rightRotate(RBT ** root, RBT * x); //右旋函数
void rbInsertFixUp(RBT ** root, RBT * z); //插入后的调整
void rbInsert(RBT ** root, RBT * z); //插入操作
void print(RBT * x); //打印一个结点
void rbprint(RBT ** root); //打印一棵树

int main()
{   
    RBT ** root; //root指向根结点
    root = (RBT**)malloc(sizeof(RBT*));
    *root = NULL; //初始时树为空
    const int MAX = 100; //定义数组的最大长度
	int arrays[MAX];
	int n;
	cout<<"请输入数组的长度:"<<endl;
	cin>>n;
	cout<<"请输入数据:"<<endl;
	for(int i=0;i<n;i++) //输入数组元素
	{
		cin>>arrays[i];
	}
    for(int i=0; i<n; i++)
    {
        RBT * z = (RBT*)malloc(sizeof(RBT)); //定义一个指向新结点的指针z
        z->key = arrays[i]; //结点z的key值指向数组中的元素
        rbInsert(root, z); //将z指向的值插入到树中
    }
	cout<<"红黑树为:"<<endl;    
    rbprint(root); //打印红黑树
    return 0;
}

void leftRotate(RBT ** root, RBT * x) //左旋函数
{
    RBT* y;
    y = x -> right;//step1,确定y
    if(x -> right != NULL && y != NULL)
        x -> right = y -> left;
    if(y != NULL && y -> left != NULL)
        y -> left -> parent = x; //step2,y的左孩子与x的右孩子连接
    if(y != NULL)
		y -> parent = x -> parent;
    if(x -> parent == NULL)
        * root = y;
    else    
    {
        if(x == x -> parent -> left)
            x -> parent -> left = y;
        else
            x -> parent-> right = y;
    } //step3,x的父结点作为y的父结点
    if(y != NULL)
	{
		y -> left = x;
		x -> parent = y; //step4,x与y交换
	}
}

void rightRotate(RBT ** root, RBT * x) //右旋函数
{
    RBT* y;
    y = x -> left; //step1,确定y的位置
    if(x -> left != NULL && y != NULL)
        x -> left = y -> right;
    if(y -> right != NULL && y -> left != NULL)
        y -> right -> parent = x; //step2,将y的右孩子变成x的左孩子
    if(y != NULL)
		y -> parent = x -> parent;
    if(x -> parent == NULL)
        * root = y; 
    else    
    {
        if(x == x -> parent -> left)
            x -> parent -> left = y;
        else
            x -> parent -> right = y;
    } //step3,x的父结点作为y的父结点
	if(y != NULL)
	{
        y -> right = x;
        x -> parent = y;
	} //step4,x与y交换
}

void rbInsert(RBT ** root, RBT * z) //插入函数
{
    RBT * y, * x; //定义指针x和y,x指向根结点,y指向空结点
    y = NULL;
    x = * root;
    while(x != NULL)
    {
        y = x;
        if((z -> key) < (x -> key))
            x = x -> left;
        else
            x = x -> right;
    }
    z -> parent = y;    
    if(y == NULL)
        * root = z;
    else
    {
        if((z -> key)<(y -> key))
            y -> left = z;
        else
            y -> right = z;
    } //确定插入元素的位置
    z -> left = NULL;
	z -> right = NULL;
    z -> color = red; //对插入点进行初始化
    rbInsertFixUp(root,z); //调用调整函数
}

void rbInsertFixUp(RBT ** root, RBT * z)
{
    if(*root != NULL)
    {
        RBT * y;
        while(z -> parent != NULL && z -> parent -> color == red) //只有当z的父结点为red时才有调整的必要
        {
            if(z -> parent -> parent -> left == z -> parent) //z的父结点是祖父结点的左孩子
            {
                y = z -> parent -> parent -> right; //定义y为z的叔叔结点
                if(y != NULL && y -> color == red)//case1,叔叔结点y不为空且color为red
                {
                    z -> parent -> color = black;
					y -> color = black;
                    z -> parent -> parent -> color = red;
                    z = z -> parent -> parent; //调整颜色后定义z的祖父结点为新的z
                }
                else //case2、case3
                {
                    if(z == z -> parent -> right) //case2,z是其父结点的右孩子
                    {
                        z = z -> parent;
                        leftRotate(root,z);
                    } //case2转换成case3
                    z -> parent -> color = black;
                    z -> parent -> parent->color = red;
                    rightRotate(root,z -> parent -> parent);
               }
            }
            else //z的父结点为祖父结点的右孩子,操作同上
            {
                y = z -> parent -> parent -> left;
                if(y != NULL && y -> color == red)
                {
                    z -> parent -> color = black;
					y -> color = black;
                    z -> parent -> parent -> color = red;
                    z = z -> parent -> 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 print(RBT * x)
{
    if(x !=NULL)
    {
        cout<<"key: "<<x -> key<<'\t'; //打印关键字
	    if(x -> parent != NULL) //打印父结点
            cout<<"  parent: "<< x -> parent -> key<<'\t';
        else
            cout<<"  parent: nil"<<'\t';
        if(x -> left != NULL) //打印左孩子
			cout<<"  left: "<<x -> left -> key<<'\t';
        else
            cout<<"  left: nil"<<'\t';
        if(x -> right != NULL) //打印右孩子
			cout<<"  right: "<<x -> right -> key<<'\t';
        else
            cout<<"  right: nil"<<'\t';
		if(x -> color == red) //打印颜色
			cout<<"  color: red"<<endl;
        else
            cout<<"  color: black"<<endl;
    }
}

void rbprint(RBT ** root) //打印红黑树
{
    if(*root != NULL)
    {
        print(*root);
        rbprint(&((*root)->left));//采用引用的方式递归调用
        rbprint(&((*root)->right));
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值