红黑树插入算法实现

</pre><p>参考文件:  <a target=_blank href="http://www.soft568.com/info/detail/4-11258.html">http://www.soft568.com/info/detail/4-11258.html</a></p><p align="left"><span style="color:#666666;">在</span><span style="color:#666666;">VC</span><span style="color:#666666;">环境下编译。主体语言是</span><span style="color:#666666;">C</span><span style="color:#666666;">,用到了点</span><span style="color:#666666;">C++</span><span style="color:#666666;">语法。</span></p><p align="left"><span style="color:#666666;"> </span></p><p align="left"><span style="color:#666666;">由于红黑树中的元素必须各不相同,定义了一个时间复杂度仅为</span><span style="color:#666666;">O</span><span style="color:#666666;">(</span><span style="color:#666666;">n</span><span style="color:#666666;">)的随机数产生函数:</span></p><p align="left"><span style="color:#666666;">void Random(int *A, int max, int length);</span></p><p align="left"><span style="color:#666666;">该函数能返回一个长度为</span><span style="color:#666666;">length,</span><span style="color:#666666;">元素随机分布在</span><span style="color:#666666;">0~max</span><span style="color:#666666;">之间的数组</span><span style="color:#666666;">A</span><span style="color:#666666;">。</span></p><p align="left"><span style="color:#666666;">根据实验主要功能</span><span style="color:#666666;">—</span><span style="color:#666666;">插入,定义了插入函数</span></p><p align="left"><span style="color:#666666;">void rbInsert(RBT* *root, RBT* pZ); </span></p><p align="left"><span style="color:#666666;">而插入函数需要调整红黑树结构,定义红黑树调整函数:</span></p><p align="left"><span style="color:#666666;">void rbFixUp(RBT **root, RBT *pZ);//</span><span style="color:#666666;">插入后的调整</span></p><p align="left"><span style="color:#666666;">在调整函数中又需要调用左旋操作和右旋操作:</span></p><p align="left"><span style="color:#666666;">void leftRotate(RBT* *root, RBT *pX); //</span><span style="color:#666666;">左旋操作</span></p><p align="left"><span style="color:#666666;">void rightRotate(RBT** root, RBT *pX); //</span><span style="color:#666666;">右旋操作</span></p><p align="left"><span style="color:#666666;">为了显示红黑树而定义了先序遍历的红黑树打印函数:</span></p><p align="left"><span style="color:#666666;">void treePrint(RBT **root); //</span><span style="color:#666666;">打印一棵树</span><span style="color:#666666;">,</span><span style="color:#666666;">先序遍历</span></p><p align="left"><span style="color:#666666;">打印红黑树的过程中需要调用对每一个结点的打印函数:</span></p><p align="left"><span style="color:#666666;">void rbPrint(RBT* pX); //</span><span style="color:#666666;">打印一个结点</span></p><p align="left"><span style="color:#333333;"></span><span style="color:#333333;">代码如下:</span><span style="color:#333333;"></span><span style="color:#333333;"></span><pre name="code" class="cpp">#include <iostream>
#include <stdio.h>
#include <time.h>
using namespace std;


#define red 0
#define black 1
#define SIZE 10 //待插入的元素个数
#define MAX 100 //待插入元素的范围0~MAX
typedef struct RB 
{
   int key; //关键字
    int color; //颜色
    struct RB *ptParent; //指向父结点的指针
    struct RB *ptLeft; //指向左孩子的指针
    struct RB *ptRight; //指向右防子的指针
}RBT; //定义结构体RBT来表示红黑树一个结点

void leftRotate(RBT* *root, RBT *pX); //左旋操作
void rbFixUp(RBT **root, RBT *pZ);//插入后的调整
void rightRotate(RBT** root, RBT *pX); //右旋操作
void rbInsert(RBT* *root, RBT* pZ); //插入操作
void rbPrint(RBT* pX); //打印一个结点
void treePrint(RBT **root); //打印一棵树,先序遍历
void Random(int *A, int max, int length);//产生一个长度为length数组,
                                         //数组元素随机分布在0~max间,且不重复,
                                         //时间复杂度为O(max)

int main()
{
    
    RBT **root; //root指向根结点
    root = (RBT**)malloc(sizeof(RBT*));
    *root = NULL;//初始时树为空

    
    int *A; //A用来存放待入元素
    A = (int*)malloc(sizeof(int)*SIZE);
    int i;
/*    for(i=0; i<SIZE; i++)
    {
        A[i] = rand()%100;
        printf("%d ", A[i]);
    }*/
    Random(A, MAX, SIZE);
    for(i=0; i<SIZE; i++)
    {
        printf("%d ", A[i]);
    }
    puts("\n");
    for(i=0; i<SIZE; i++)
    {
        RBT *pZ = (RBT*)malloc(sizeof(RBT));//定义一个指向新结点的指针pZ
         printf("\nNow insert the element %d:\n", A[i]);
        pZ->key = A[i];
        rbInsert(root, pZ);
        treePrint(root);//打印当前红黑树结构
        system("pause");
    }
    puts("\nThe total tree is:\n ");
    
    treePrint(root);
    system("pause");
    return 0;
}





//以下的各函数的定义

//左旋
void leftRotate(RBT* *root, RBT* pX)
{
    RBT* pY;
    pY = pX->ptRight;

    if(pX->ptRight != NULL && pY != NULL)
        pX->ptRight = pY->ptLeft;
    if(pY != NULL && pY->ptLeft != NULL)
        pY->ptLeft->ptParent = pX; //将Y的左孩子变成X的右孩子
    if(pY != NULL)
    pY->ptParent = pX->ptParent;
    if(pX->ptParent == NULL)
        *root = pY; //如果pX结点是根那么让pY成为新的根
    else    
    {
        if(pX == pX->ptParent->ptLeft)
            pX->ptParent->ptLeft = pY;
        else
            pX->ptParent->ptRight = pY;
    }
    if(pY!=NULL)
    pY->ptLeft = pX;
    pX->ptParent = pY;
}





//右旋
void rightRotate(RBT** root, RBT *pX)
{
    RBT* pY;
    pY = pX->ptLeft;

    if(pX->ptLeft != NULL && pY != NULL)
        pX->ptLeft = pY->ptRight;
    if(pY->ptRight != NULL && pY->ptLeft != NULL)
        pY->ptRight->ptParent = pX; //将Y的右孩子变成X的左孩子

    pY->ptParent = pX->ptParent;
    if(pX->ptParent == NULL)
        *root = pY; //如果pX结点是根那么让pY成为新的根
    else    
    {
        if(pX == pX->ptParent->ptLeft)
            pX->ptParent->ptLeft = pY;
        else
            pX->ptParent->ptRight = pY;
    }
    
    pY->ptRight = pX;
    pX->ptParent = pY;
}




//红黑树插入
void rbInsert(RBT* *root, RBT* pZ)
{
    RBT *pY, *pX;
    pY = NULL;
    pX = *root;

    while(pX != NULL)
    {
        pY = pX;
        if(pZ->key < pX->key)
            pX = pX->ptLeft;
        else
            pX = pX->ptRight;
    }

    pZ->ptParent = pY;
    
    if(pY == NULL)
        *root = pZ;
    else
    {
        if(pZ->key < pY->key)
            pY->ptLeft = pZ;
        else
            pY->ptRight = pZ;
    }

    pZ->ptLeft = pZ->ptRight = NULL;

    pZ->color = red;

    rbFixUp(root,pZ);

}


//红黑树调整
void rbFixUp(RBT **root, RBT *pZ)
{
    if(*root != NULL)
    {
    RBT *pY;
    while(pZ->ptParent != NULL && pZ->ptParent->color == red)
    {
        if(pZ->ptParent->ptParent->ptLeft == pZ->ptParent)
        {
            pY = pZ->ptParent->ptParent->ptRight; //Y是Z的叔叔

            if(pY!=NULL && pY->color == red)//第一种情况 
            {
                pZ->ptParent->color = pY->color = black;
                pZ->ptParent->ptParent->color = red;
                pZ = pZ->ptParent->ptParent; //上溯到Z的爷爷,再进行调整
            }

            else //第二 三种情况
            {
                if(pZ == pZ->ptParent->ptRight) //case2->case3
                {
                    pZ = pZ->ptParent;
                    leftRotate(root, pZ);
                }
                pZ->ptParent->color = black;
                pZ->ptParent->ptParent->color = red;
                rightRotate(root, pZ->ptParent->ptParent);
            }
        }
        else
        {
            pY = pZ->ptParent->ptParent->ptLeft;

            if(pY != NULL && pY->color == red)
            {
                pZ->ptParent->color = pY->color = black;
                pZ->ptParent->ptParent->color = red;
                pZ = pZ->ptParent->ptParent;
            }
            else
            {
                if(pZ == pZ->ptParent->ptLeft)
                {
                    pZ = pZ->ptParent;
                    rightRotate(root, pZ);
                }
                pZ->ptParent->color = black;
                pZ->ptParent->ptParent->color = red;
                leftRotate(root,pZ->ptParent->ptParent);
            }
        }
    }
    (*root)->color = black;
    }
}


//打印结点
void rbPrint(RBT* pX)
{
    if(pX !=NULL)
    {
        printf("key: %d\t", pX->key);

        if(pX->color == red)
            printf("color: red\t");
        else
            printf("color: black\t");
    
        if(pX->ptLeft != NULL)
            printf("left: %d \t", pX->ptLeft->key);
        else
            printf("left: nil\t");

        if(pX->ptRight != NULL)
            printf("right: %d\t", pX->ptRight->key);
        else
            printf("right: nil\t");

        if(pX->ptParent != NULL)
            printf("parent: %d\t", pX->ptParent->key);
        else
            printf("*root\t");
    }
    else
        printf("empty");
        puts("\n");
}


//从根结点开始先序遍历,打印树
void treePrint(RBT** root)
{
    if(*root != NULL)
    {
        rbPrint(*root);
        treePrint(&((*root)->ptLeft));
        treePrint(&((*root)->ptRight));
    }
}


//产生一个长度为length,元素随机分布在0~max之间的数组A

void Random(int *A, int max, int length)
{
    srand(time(NULL));
    int i;
    int c;
    int k = max+1;
    int *B = (int*)malloc(sizeof(int)*k);
    for(i=0; i<k; i++)
        B[i] = i;
    for(i=0; i<length; i++)
    {
        c = rand()%k;
        k--;
        A[i] = B[c];
        B[c] = B[k];
    }
}


程序编译通过,正常运行.

随机产生的待插入元素为:

54 62 81 91 34 9 16 74 48 24

最后输出结果为:

The total tree is:

key: 62 color: black   left: 34        right:81       *root

key: 34 color:red      left:16        right:54       parent: 62

key: 16 color: black   left: 9         right:24       parent: 34

key: 9 color:red      left: nil      right: nil      parent: 16

key: 24 color:red      left: nil      right: nil      parent: 16

key: 54 color: black   left: 48        right:nil      parent: 34

key: 48 color:red      left: nil      right: nil      parent: 54

key: 81 color: black   left: 74       right:91       parent: 62

key: 74 color:red      left: nil      right: nil      parent: 81

key: 91 color:red      left: nil      right: nil      parent: 81

最终输出满足红黑树性质。

且中间每一步输出正确。

主函数int main()

{ …

return 0;

}

The thread 0x924 has exited with code 0(0x0).

The program 'D:\PhanYoung\课堂\Algorithm\实验\实验二红黑树的插入\Debug\rbt.exe'has exited with code 0 (0x0).

函数正常结束.获得正确结果.

 


你可能感兴趣的:(算法,算法,C语言,红黑树)