zoukankan      html  css  js  c++  java
  • 算法导论 第13章 红黑树

    为了让这片博客看起来更有营养一些,我还是在添加一些红黑树的设计原理吧?

    Q:为什么要为叶节点加入终止节点NIL?

    A:其实这个NIL的假如本省没有什么,但是当规定完NIL的颜色为Black时,他的作用就显现出来了,但他的颜色为Black时无论是Insert还是delete,都可以起到辅佐判断的作用例:

    假如向上面这种情况,插入节点为C那么我们就可以通过判断其叔节点的颜色,也就是NIL的颜色把其对应于正确的case2中去。

    不知道是我买的是盗版的原因还是本身书中就有这个问题《算法导论》中文翻译第三版的179页的关于RB-INSERT-FLXUP的操作中对于case3没有加else,这应该是错误的,应该是在case2后加上case3,然后再加上在else里写上case3。

    下面是算法导论红黑树部分的代码实现,其中大部分代码是根据算法导论的二叉树的部分改编过来的,所以会看到一些有些过于单纯的二叉树操作还请见谅!

    重点强调了红黑树的插入和删除部分的代码!!

    这个代码还是写了不少的,但是为什么会有红黑树这种数据结构,换句话说通过导论引理13.1的证明,这中操作后能保证搜索二叉树的高度小于lg(n+1),但如果仅从这个角度产生的对于搜索的代价来看的话红黑树的优势显然不如AVL,那么为什么要用红黑树呢?

    代码:

      1 #include<iostream>
      2 #include<stack>
      3 
      4 using namespace std;
      5 
      6 #define Red 1
      7 #define Black 0
      8 
      9 typedef struct node
     10 {
     11     int key;
     12     node* left;
     13     node* right;
     14     node* parent;
     15     int color;    //    红黑树的节点颜色标识,选取Red-1,Black-0;
     16 }Node;
     17 
     18 int visited;
     19 int colorFlag;
     20 Node* NIL;
     21 Node* Root;
     22 
     23 //    创建二叉树,数据来控制台。按中序遍历的方式输入。
     24 void CreatBinaryTree(Node &node)
     25 {
     26     cout << "输入" << node.key << "的左儿子" << endl;
     27     int x;
     28     cin >> x;
     29     if (x != -1)
     30     {
     31         Node *lnode = new Node();
     32         lnode->key = x;
     33         node.left = lnode;
     34         lnode->parent = &node;
     35         CreatBinaryTree(*lnode);
     36     }
     37     else
     38     {
     39         node.left = NULL;
     40     }
     41     cout << "输入" << node.key << "的右儿子" << endl;
     42     int y;
     43     cin >> y;
     44     if (y != -1)
     45     {
     46         Node *rnode = new Node();
     47         rnode->key = y;
     48         node.right = rnode;
     49         rnode->parent = &node;
     50         CreatBinaryTree(*rnode);
     51     }
     52     else
     53     {
     54         node.right = NULL;
     55     }
     56 }
     57 
     58 // 按照中序访问建立二叉树,数组要求为先序遍历返回结果,且左儿子,右儿子为空设定起等于-1;
     59 void CreateBinaryTreeByArray(Node *root, int a[])
     60 {
     61     //输入root的key
     62     root->key = a[visited];
     63     visited++;
     64     if (a[visited] == -1)
     65     {
     66         root->left = NULL;
     67         visited++;
     68     }
     69     else
     70     {
     71         root->left = new Node();
     72         root->left->parent = root;
     73         CreateBinaryTreeByArray(root->left, a);
     74     }
     75     if (a[visited] == -1)
     76     {
     77         root->right = NULL;
     78         visited++;
     79     }
     80     else
     81     {
     82         root->right = new Node();
     83         root->right->parent = root;
     84         CreateBinaryTreeByArray(root->right, a);
     85     }
     86 }
     87 
     88 //    递归法中序访问二叉树
     89 void Traverse(Node *root)
     90 {
     91     if (root != NULL)
     92     {
     93         Traverse(root->left);
     94         cout << root->key << "    " << endl;
     95         Traverse(root->right);
     96     }
     97 }
     98 
     99 
    100 //    非递归借用栈迭代中序遍历二叉树。
    101 void NonRecursionTraverse(Node *root)
    102 {
    103     stack<Node*> treeStack;
    104     Node *p = root->left;
    105     treeStack.push(root);
    106     while (!(treeStack.empty() && p == NULL))
    107     {
    108         while (p != NULL)
    109         {
    110             treeStack.push(p);
    111             p = p->left;
    112         }
    113         Node *top = treeStack.top();
    114         cout << top->key << "    ";
    115         treeStack.pop();
    116         p = top->right;
    117     }
    118 }
    119 
    120 
    121 //    递归二叉树搜索树的搜索
    122 Node* TreeSearch(Node *root, int x)
    123 {
    124     if (root == NULL || x == root->key)
    125         return root;
    126     if (x < root->key)
    127         return TreeSearch(root->left, x);
    128     else
    129         return TreeSearch(root->right, x);
    130 }
    131 
    132 
    133 //    非递归二叉搜索树的搜索
    134 Node* InteractiveTreeSearch(Node* root, int x)
    135 {
    136     while (root != NULL && root->key != x)
    137     {
    138         if (x < root->key)
    139             root = root->left;
    140         else
    141             root = root->right;
    142     }
    143     return root;
    144 }
    145 
    146 
    147 //    返回二叉搜索树中关键字最小的元素
    148 Node *TreeMinimum(Node* root)
    149 {
    150     while (root->left != NULL)
    151         root = root->left;
    152     return root;
    153 }
    154 
    155 Node* RecursionTreeMinimun(Node* root)
    156 {
    157     if (root->left == NULL)
    158         return root;
    159     return RecursionTreeMinimun(root->left);
    160 }
    161 
    162 //    返回二叉搜索树中关键字最大的元素
    163 Node *TreeMaxmum(Node* root)
    164 {
    165     while (root->right != NULL)
    166         root = root->right;
    167     return root;
    168 }
    169 
    170 
    171 //    返回指定节点的后继(后继的定义见算法导论)
    172 Node *TreeSuccessor(Node *root)
    173 {
    174     if (root->right != NULL)
    175         return TreeMinimum(root->right);
    176     Node* tempParent = root->parent;
    177     while (tempParent != NULL&&tempParent->left != root)
    178     {
    179         root = tempParent;
    180         tempParent = tempParent->parent;
    181     }
    182     return tempParent;
    183 }
    184 
    185 //    为一颗红黑树节点设置颜色值;
    186  
    187 void SetNodeColor(Node * root)
    188 {
    189     if (root != NIL)
    190     {
    191         cout << root->key << "颜色" << endl;
    192         cin >> root->color;
    193         SetNodeColor(root->left);
    194         SetNodeColor(root->right);
    195     }
    196 }
    197 
    198 // 按照中序访问建立红黑树但不涉及节点的颜色
    199 void CreateRBTreeByArray(Node *root, int a[])
    200 {
    201     //输入root的key
    202     root->key = a[visited];
    203     visited++;
    204     if (a[visited] == -1)
    205     {
    206         root->left = NIL;
    207         visited++;
    208     }
    209     else
    210     {
    211         root->left = new Node();
    212         root->left->parent = root;
    213         CreateRBTreeByArray(root->left, a);
    214     }
    215     if (a[visited] == -1)
    216     {
    217         root->right = NIL;
    218         visited++;
    219     }
    220     else
    221     {
    222         root->right = new Node();
    223         root->right->parent = root;
    224         CreateRBTreeByArray(root->right, a);
    225     }
    226 }
    227 //    遍历一颗红黑树
    228 void TraverseRBTree(Node *root)
    229 {
    230     if (root != NIL)
    231     {
    232         TraverseRBTree(root->left);
    233         cout << root->key << "颜色:";
    234         if (root->color == 1)
    235             cout << "Red" << endl;
    236         else
    237             cout << "Black" << endl;
    238         TraverseRBTree(root->right);
    239     }
    240 }
    241 
    242 void SetRBTreeColorByArray(Node *root, int a[])
    243 {
    244     if (root != NIL)
    245     {
    246         SetRBTreeColorByArray(root->left, a);
    247         root->color = a[colorFlag];
    248         colorFlag++;
    249         SetRBTreeColorByArray(root->right, a);
    250     }
    251 }
    252 
    253 //    作为普通二叉树的插入操作,但仍需要进一步调整
    254 void RBInsert(Node *root, Node *z)
    255 {
    256     Node* x = root;
    257     Node* y = x->parent;
    258     while (x != NIL)
    259     {
    260         y = x;
    261         if (z->key < x->key)
    262         {
    263             x = x->left;
    264         }
    265         else
    266         {
    267             x = x->right;
    268         }
    269     }
    270     z->parent = y;
    271     if (z->key < y->key)
    272         y->left = z;
    273     else
    274         y->right = z;
    275     z->left = NIL;
    276     z->right = NIL;
    277     z->color = Red;
    278 }
    279 
    280 void LeftRotate(Node* root, Node *x)
    281 {
    282     Node *y = x->right;
    283     x->right = y->left;
    284     if (y->left != NIL)
    285         y->left->parent = x;
    286     y->parent = x->parent;
    287     if (x->parent == NIL)
    288         Root = y;
    289     if (x == x->parent->left)
    290         x->parent->left = y;
    291     else
    292         x->parent->right = y;
    293     y->left = x;
    294     x->parent = y;
    295 }
    296 
    297 void RightRotate(Node *root, Node *y)
    298 {
    299     Node *x = y->left;
    300     y->left = x->right;
    301     if (x->right!=NIL)
    302         y->left->parent = x;
    303     x->parent = y->parent;
    304     if (x->parent == NIL)
    305         Root = x;
    306     if (y == y->parent->left)
    307         y->parent->left = x;
    308     else
    309         y->parent->right = x;
    310     x->right = y;
    311     y->parent = x;
    312 }
    313 
    314 void RBFixup(Node *root, Node *z)
    315 {
    316     while (z->parent->color == Red)
    317     {
    318         if (z->parent == z->parent->parent->left)
    319         {
    320             Node *y = z->parent->parent->right;
    321             if (y->color == Red)
    322             {
    323                 y->color = Black;
    324                 z->parent->color = Black;
    325                 y->parent->color = Red;
    326                 z = y->parent;
    327             }
    328             else if (z == z->parent->right)
    329             {
    330                 z = z->parent;
    331                 LeftRotate(Root, z);
    332 
    333                 z->parent->color = Black;
    334                 z->parent->parent->color = Red;
    335                 RightRotate(Root, z->parent->parent);
    336             }
    337             else
    338             {
    339                 z->parent->color = Black;
    340                 z->parent->color = Red;
    341                 RightRotate(root, z->parent->parent);
    342             }
    343         }
    344         else
    345         {
    346 
    347         }
    348     }
    349     Root->color = Black;
    350 }
    351 
    352 int main()
    353 {
    354     //    建立NIL
    355     NIL = new Node();
    356     NIL->key = -1;    //    规定NIL的key等于-1;
    357 
    358     int a[] = {11, 2, 1, -1, -1, 7, 5, -1, -1, 8, -1, -1, 14, -1, 15, -1, -1 };
    359     int color[] = { Black, Red, Red, Black, Red, Black, Black, Red};
    360     Node *treeroot = new Node();
    361     treeroot->key = 15;
    362     treeroot->parent = NIL;
    363     Root = treeroot;
    364     visited = 0;
    365     colorFlag = 0;
    366     CreateRBTreeByArray(treeroot, a);
    367     /*SetNodeColor(treeroot);*/
    368     SetRBTreeColorByArray(treeroot, color);
    369     TraverseRBTree(treeroot);
    370     Node* Insert = new Node();
    371     Insert->key = 6;
    372     RBInsert(treeroot, Insert);
    373     cout << TreeSearch(Root, 11)->color << endl;
    374     RBFixup(treeroot, Insert);
    375     cout << TreeSearch(Root, 11)->color << endl;
    376     TraverseRBTree(Root);
    377     cout << TreeSearch(Root, 11)->color << endl;
    378     return 0;
    379 }
  • 相关阅读:
    web知识共享网站
    Javascript模拟多线程
    让mssql查询的参数大小写区分
    asp.net导出excel文件方法之一
    对生活迷茫时,可以看的小说..
    解决SWFUpload在Chrome、Firefox浏览器下session找不到的问题
    fckeditor在ie9无法上传图片和弹出浮层内容不显示的解决方法
    一个javascript文件上传组件.
    css属性之媒体(Media)类型
    前端问题汇总
  • 原文地址:https://www.cnblogs.com/chaiwentao/p/4342983.html
Copyright © 2011-2022 走看看