• C++红黑树


     1 #ifndef _RBTREE_H_
     2 #define _RBTREE_H_
     3 
     4 const int nodeSize = 3;
     5 class RBTree
     6 {
     7 private:
     8     typedef struct Node {
     9         int key;
    10         int color;    //0为红,1为黑
    11         Node * family[nodeSize];    //family[0]左节点,family[1]右节点,family[2]父节点
    12         Node(int k, int c);
    13     }* Pnode;
    14 private:
    15     Pnode nil;
    16     Pnode root;
    17 private:
    18     //返回k节点
    19     Pnode __GetNode(int k);
    20     //中序遍历
    21     void __ShowNode(Pnode n)const;
    22     //旋转节点,direction 为 0 左旋转,1右旋转
    23     void __Rotate(Pnode n, int direction);
    24     //修正插入后的红黑树
    25     void __InsertFixup(Pnode n);
    26     //修正删除后的红黑树
    27     void __DeleteFixup(Pnode delNode);
    28     //释放内存
    29     void __Clear(Pnode n);
    30     //返回当前节点(包含当前节点)下的所有节点个数.
    31     size_t __NodeSize(Pnode n);
    32     //返回节点n的前驱(direction = 0),后继(direction = 1)
    33     Pnode __GetNeighbor(Pnode n, int direction);
    34 public:
    35     RBTree();
    36     bool IsExist(int k);
    37     size_t Size();
    38     //按从小到大打印所有节点的key值
    39     void ShowList()const;
    40     //按树的层次打印节点的key值和颜色(R,B)
    41     void ShowTree()const;
    42     //插入新节点
    43     void Insert(int k);
    44     //删除节点
    45     void Delete(int k);
    46     ~RBTree();
    47 };
    48 
    49 #endif
    RBTree.h
      1 #include "RBTree.h"
      2 #include <iostream>
      3 #include <queue>
      4 
      5 using namespace std;
      6 
      7 RBTree::Node::Node(int k = 0x80000000, int c = 0) :key(k), color(c), family{} {}
      8 
      9 RBTree::RBTree(): nil(new Node(0x80000000, 1)), root(nil){}
     10 
     11 RBTree::~RBTree() 
     12 {
     13     __Clear(root);
     14     delete nil;
     15 }
     16 
     17 void RBTree::__Clear(Pnode n)
     18 {
     19     if (n == nil)
     20         return;
     21     __Clear(n->family[0]);
     22     __Clear(n->family[1]);
     23     delete n;
     24 }
     25 
     26 bool RBTree::IsExist(int k) 
     27 {
     28     return __GetNode(k) != nil;
     29 }
     30 
     31 size_t RBTree::__NodeSize(Pnode n)
     32 {
     33     if (n == nil)
     34         return 0;
     35     return 1 + __NodeSize(n->family[0]) + __NodeSize(n->family[1]);
     36 }
     37 
     38 void RBTree::__ShowNode(Pnode n) const
     39 {
     40     if (n == nil)
     41         return;
     42     __ShowNode(n->family[0]);
     43     cout << n->key << " ";
     44     __ShowNode(n->family[1]);
     45 }
     46 
     47 void RBTree::ShowList() const
     48 {
     49     __ShowNode(root);
     50     cout << endl;
     51 }
     52 
     53 void RBTree::ShowTree() const
     54 {
     55     queue<Pnode> dn;
     56     if(root != nil)
     57         dn.push(root);
     58     int size = 0;
     59     while (!dn.empty())
     60     {
     61         size = dn.size();
     62         for (int i = 0; i < size; i++)
     63         {
     64             cout << dn.front()->key;
     65             if (dn.front()->color)
     66                 cout << "B  ";
     67             else cout << "R  ";
     68             if (dn.front()->family[0] != nil)
     69                 dn.push(dn.front()->family[0]);
     70             if (dn.front()->family[1] != nil)
     71                 dn.push(dn.front()->family[1]);
     72             dn.pop();
     73         }
     74         cout << endl;
     75     }
     76 }
     77 
     78 RBTree::Pnode RBTree::__GetNeighbor(Pnode n, int direction)
     79 {
     80     Pnode current{};
     81     if (n->family[direction] != nil)
     82     {
     83         current = n->family[direction];
     84         while (current->family[!direction] != nil)
     85             current = current->family[!direction];
     86     }
     87     else {
     88         current = n;
     89         while (current->family[2] != nil && current != current->family[2]->family[!direction])
     90             current = current->family[2];
     91         current = current->family[2];
     92     }
     93     return current;
     94 }
     95 
     96 RBTree::Pnode RBTree::__GetNode(int k)
     97 {
     98     Pnode current = root;
     99     while (current != nil)
    100     {
    101         if (current->key == k)
    102             break;
    103         else
    104             current = current->family[k > current->key];
    105     } 
    106     return current;
    107 }
    108 
    109 //direction = 0 左转,1 右转
    110 void RBTree::__Rotate(Pnode x, int direction)
    111 {
    112     Pnode y = x->family[!direction];
    113     x->family[!direction] = y->family[direction];
    114     if (y->family[direction])
    115         y->family[direction]->family[2] = x;
    116     y->family[2] = x->family[2];
    117     if (x->family[2] == nil)
    118         root = y;
    119     else
    120         x->family[2]->family[x == x->family[2]->family[1]] = y;
    121     x->family[2] = y;
    122     y->family[direction] = x;
    123 }
    124 
    125 void RBTree::__InsertFixup(Pnode n)
    126 {
    127     int plr = 0;
    128     //如果n的父节点不为空,且父节点颜色为红色
    129     while (!n->family[2]->color)
    130     {
    131         //如果n的父节点是祖父节点的左节点,则plr = 0,反之为1
    132         plr = (n->family[2] == n->family[2]->family[2]->family[0] ? 0 : 1);
    133         //如果存在叔节点,且叔节点颜色为红,则将父节点和叔结点颜色变黑,当前节点成为祖节点且颜色变红.
    134         if ((n->family[2]->family[2]->family[!plr]) &&
    135             !(n->family[2]->family[2]->family[!plr]->color))
    136         {
    137             n = n->family[2]->family[2];
    138             n->color = 0;
    139             n->family[plr]->color = 1;
    140             n->family[!plr]->color = 1;
    141         }
    142         else {
    143             //如果n是左节点,则lr为0,反之为1
    144             int lr = n == n->family[2]->family[0] ? 0 : 1;
    145             //如果n是左节点,其父为右节点;或者n是右节点,其父为左节点
    146             if (lr + plr == 1)
    147             {
    148                 n = n->family[2];
    149                 __Rotate(n, !lr);
    150                 //旋转后,n变为原来反方向的节点
    151                 lr = !lr;
    152             }
    153             n = n->family[2]->family[2];
    154             __Rotate(n, !lr);
    155             n->color = 0;
    156             n->family[2]->color = 1;
    157             break;        
    158         }
    159     }
    160     root->color = 1;
    161 }
    162 
    163 void RBTree::Insert(int k)
    164 {
    165     Pnode current = root;
    166     Pnode prev = nil;
    167     while (current != nil)
    168     {
    169         prev = current;
    170         if (k < current->key)
    171             current = current->family[0];
    172         else if (k > current->key)
    173             current = current->family[1];
    174         else {
    175             cout << k << " is already exist!!!
    ";
    176             return;
    177         }
    178     }
    179     Pnode new_node = new Node(k);
    180     new_node->family[0] = new_node->family[1] = nil;
    181     new_node->family[2] = prev;
    182     if (root == nil)
    183         root = new_node;
    184     else if (k < prev->key)
    185         prev->family[0] = new_node;
    186     else prev->family[1] = new_node;
    187     __InsertFixup(new_node);
    188 }
    189 
    190 
    191 void RBTree::__DeleteFixup(Pnode delNode)
    192 {
    193     Pnode bakNode = delNode;
    194     while (delNode != root && delNode->color)
    195     {
    196         //delNode如果是左孩子lr = 0, 反之lr = 1,为便于思考,假定lr=0,即delNode为左孩子.
    197         int lr = delNode == delNode->family[2]->family[1];
    198         Pnode brother = delNode->family[2]->family[!lr];
    199         //如果兄弟结点颜色为红色,则其父结点和兄弟孩子的颜色必为黑,以父节点为轴左旋转重新着色后,delNode新兄弟结点颜色为黑
    200         if (!brother->color) {
    201             delNode->family[2]->color = 0;
    202             brother->color = 1;
    203             __Rotate(delNode->family[2], lr);
    204             brother = delNode->family[2]->family[!lr];
    205         }
    206         //如果兄弟左右孩子都为黑色,兄弟结点着红色,将父结点成为当前节点
    207         if (brother->family[0]->color && brother->family[1]->color) {
    208             brother->color = 0;
    209             delNode = delNode->family[2];
    210         }
    211         else {
    212             //如果兄弟右孩子为黑色
    213             if (brother->family[!lr]->color) {
    214                 brother->color = 0;
    215                 brother->family[lr]->color = 1;
    216                 __Rotate(brother, !lr);
    217                 brother = brother->family[2];
    218             }
    219             brother->color = brother->family[2]->color;
    220             brother->family[!lr]->color = 1;
    221             brother->family[2]->color = 1;
    222             __Rotate(brother->family[2], lr);
    223             break;
    224         }
    225     }
    226     delNode->color = 1;
    227     //删除节点,释放内存
    228     if (bakNode == root)
    229         root = nil;
    230     else if (bakNode == bakNode->family[2]->family[0])
    231         bakNode->family[2]->family[0] = nil;
    232     else 
    233         bakNode->family[2]->family[1] = nil;
    234     delete bakNode;
    235 }
    236 
    237 void RBTree::Delete(int k)
    238 {
    239     Pnode delNode = __GetNode(k);
    240     if (delNode == nil) {
    241         cout << k << "is not exist, delete failed!
    ";
    242         return;
    243     }
    244     //如果有双子节点,找后继节点successor,则successor没有左子节点
    245     if(delNode->family[0] != nil && delNode->family[1] != nil)
    246     {
    247         Pnode successor = __GetNeighbor(delNode, 0);
    248         delNode->key = successor->key;
    249         delNode = successor;
    250     }
    251     //如果没子节点
    252     if (delNode->family[0] == nil && delNode->family[1] == nil) {
    253         __DeleteFixup(delNode);
    254     }
    255     //如果仅有单子节点,那么delNode必为黑色,且其独生子女为红色
    256     else{
    257         int lr = delNode->family[0] == nil;
    258         delNode->key = delNode->family[lr]->key;
    259         delete delNode->family[lr];
    260         delNode->family[lr] = nil;
    261     }
    262 }
    263 
    264 size_t RBTree::Size()
    265 {
    266     return __NodeSize(root);
    267 }
    RBTee.cpp
     1 #define CRTDBG_MAP_ALLOC    
     2 #include "stdafx.h"
     3 #include <crtdbg.h>    
     4 #include "RBTree.h"
     5 #include <iostream>
     6 #include <ctime>
     7 
     8 using namespace std;
     9 const int ASIZE = 10;
    10 void LoadArrayToTree(RBTree & t, int * arr, int n);
    11 void GetRandomArray(int * arr, int n);
    12 void ShowArray(int * arr, int n);
    13 void Show(RBTree & t);
    14 void DeleteTree(RBTree &t, int * arr, int n);
    15 
    16 int main()
    17 {
    18     {
    19         srand(size_t(time(0)));
    20         int arr[ASIZE]{11,26,35,14,5,26,57,8,39,10};
    21         //int arr[ASIZE]{};
    22         //GetRandomArray(arr, ASIZE);
    23         ShowArray(arr, ASIZE);
    24         RBTree t;
    25         LoadArrayToTree(t, arr, ASIZE);
    26         Show(t);
    27         DeleteTree(t, arr, ASIZE);
    28         Show(t);
    29     }
    30     //内存泄露测试
    31     _CrtDumpMemoryLeaks();
    32     return 0;
    33 }
    34 
    35 //main test method
    36 void LoadArrayToTree(RBTree & t, int * arr, int n)
    37 {
    38     for (int i = 0; i < n; i++)
    39         t.Insert(arr[i]);
    40 }
    41 
    42 void DeleteTree(RBTree & t, int * arr, int n)
    43 {
    44     for (int i = 0; i < n; i++) 
    45         t.Delete(arr[i]);        
    46 }
    47 
    48 void GetRandomArray(int * arr, int n)
    49 {
    50     for (int i = 0; i < n; i++)
    51     {
    52         arr[i] = rand()%50000+1;
    53         //不重复数组
    54         /*int num = rand() % 50000 + 1;
    55         int j = 0;
    56         for (j = 0; j < i; j++)
    57         {
    58             if (arr[j] == num)
    59                 break;
    60         }
    61         if (j == i)
    62             arr[i] = num;
    63         else --i;*/
    64     }
    65 }
    66 
    67 void ShowArray(int * arr, int n)
    68 {
    69     for (int i = 0; i < n; i++)
    70         cout << arr[i] << " ";
    71     cout << endl;
    72 }
    73 
    74 void Show(RBTree & t)
    75 {
    76     cout << "
    t.Size() = " << t.Size() << endl;
    77     cout << "********************List**********************
    ";
    78     t.ShowList();
    79     cout << "********************Tree**********************
    ";
    80     t.ShowTree();
    81     cout << "********************End***********************
    ";
    82     cout << endl;
    83 }
    84 // end of main test
    main.cpp

     

     

    红黑树添加PPT图 

    旧金山大学官网的红黑树可视化在线模拟器

    http://www.cs.usfca.edu/~galles/visualization/RedBlack.html

  • 相关阅读:
    快速制作高保真原型不得不知的小技巧
    EXC_BAD_ACCESS的本质详解以及僵尸模式调试原理
    Android开发的那些坑和小技巧
    谈Runtime机制和使用的整体化梳理
    在Mac OSX下设置前端开发环境
    uglifyjs压缩JS
    背投广告js
    鼠标到哪tl到哪
    word-wrap同word-break的区别(转)
    HTML中的转义字符
  • 原文地址:https://www.cnblogs.com/endenvor/p/7774605.html
Copyright © 2020-2023  润新知