鱼C论坛

 找回密码
 立即注册
查看: 2610|回复: 1

[技术交流] C++版本的二叉搜索树(LLRB平衡)

[复制链接]
发表于 2014-3-1 17:16:54 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 andalousie 于 2014-3-1 17:19 编辑

不久前我曾发布过一个未平衡的二叉搜索树,时至今日,我觉得是时候发布一个基本平衡的左偏红黑树(LLRB)来取代原来的二叉树了。仍将沿用原来的queue.h和main.cpp,只是基于原来的BST做了修改。不多说了,下面分享代码。
BST.h
  1. #if !defined (BST_H)
  2. #defind BST_H
  3. #include "queue.h"

  4. template<typename Index, typename Value>
  5. class BST
  6. {
  7. private:
  8.         const bool RED;
  9.         const bool BLACK;
  10.         struct Node
  11.         {
  12.                 Node(Index k, Value v, int n, bool cl)
  13.                 :key(k), val(v), N(n),
  14.                  left(0), right(0), color(cl)
  15.                 {}
  16.                 Index key;
  17.                 Value val;
  18.                 Node *left, *right;
  19.                 bool  color; // color of parent link
  20.                 int   N;
  21.         };
  22.         Node *root;
  23.         bool isRed(Node* x)
  24.         {
  25.                 if(!x) return false;
  26.                 return x->color = RED;
  27.         }

  28.         Node* rotateLeft(Node* h)
  29.         {
  30.                 assert (isRed(h->right));
  31.                 Node *x = h->right;
  32.                 h->right = x->left;
  33.                 x->left = h;
  34.                 x->color = h->color;
  35.                 h->color = RED;
  36.                 x->N = h->N;
  37.                 h->N = 1 + size(h->left)
  38.                         + size(h->right);
  39.                 return x;
  40.         }

  41.         Node* rotateRight(Node* h)
  42.         {
  43.                 assert (isRed(h->left));
  44.                 Node *x = h->left;
  45.                 h->left = x->right;
  46.                 x->right = h;
  47.                 x->color = h->color;
  48.                 h->color = RED;
  49.                 x->N = h->N;
  50.                 h->N = 1 + size(h->left)
  51.                         + size(h->right);
  52.                 return x;
  53.         }

  54.         Node* moveRedLeft(Node* h)
  55.         { // Assuming that h is red and both h->left and h->left->left
  56.           // are black, make h->left or one of its children red.
  57.                 flipColors(h);
  58.                 if (isRed(h->right->left))
  59.                 {
  60.                         h->right = rotateRight(h->right);
  61.                         h = rotateLeft(h);
  62.                 }
  63.                 return h;
  64.         }

  65.         void flipColors(Node* h)
  66.         {
  67.                 h->color = !h->color;
  68.                 h->left->color = !h->left->color;
  69.                 h->right->color = !h->right->color;
  70.         }

  71.         Node* balance(Node* h)
  72.         {
  73.                 assert(h);
  74.                 if (isRed(h->right) && !isRed(h->left)) h = rotateLeft(h);
  75.                 if (isRed(h->left) && isRed(h->left->left)) h = rotateRight(h);
  76.                 if (isRed(h->left) && isRed(h->right)) flipColors(h);

  77.                 h->N = size(h->left) + size(h->right) + 1;
  78.                 return h;
  79.         }
  80. public:
  81.         BST(): RED(true), BLACK(false), root(0){}
  82.         int    size() {        return size(root);        }
  83.         bool isEmpty() { return !root; }
  84.         Index min()        { return min(root)->key; }

  85.         Index floor(Index key)
  86.         {
  87.                 Node *x = floor(root, key);
  88.                 if(!x) return 0;
  89.                 return x->key;
  90.         }

  91.         Value get(Index key) { return get(root, key); }

  92.         void put(Index key, Value val)
  93.         { // Search for key. Update value if found; grow table if new.
  94.                 root = put(root, key, val);
  95.                 root->color = BLACK;
  96.         }

  97.         Value select(int k) { return select(root, k)->key; }

  98.         int rank(Index key) { return rank(key, root); }

  99.         void delMin()
  100.         {   // if both children of root are black, set root to red
  101.                 if (!isRed(root->left) && !isRed(root->right))
  102.                         root->color = RED;
  103.                 root = delMin(root);
  104.                 if (!isEmpty()) root->color = BLACK;
  105.         }

  106.         // delete the key-value pair with the given key
  107.         void del(Index key)
  108.         {   // if both children of root are black, set root to red
  109.                 if (!isRed(root->left) && !isRed(root->right))
  110.                         root->color = RED;
  111.                 root = del(root, key);
  112.                 if (!isEmpty()) root->color = BLACK;
  113.         }

  114.         void iterate()
  115.         {
  116.                 Queue<Index> q;
  117.                 inorder(root, q);
  118.                 while(!q.empty())
  119.                 {
  120.                         Index key =  q.pop();
  121.                         std::cout << get(key);
  122.                 }
  123.         }
  124. private:
  125.         int   size(Node *x)
  126.         {
  127.                 if(!x) return 0;
  128.                 else   return x->N;
  129.         }

  130.         Node* min(Node* x)
  131.         {
  132.                 if(!(x->left)) return x;
  133.                 return min(x->left);
  134.         }

  135.         Node* floor(Node* x, Index& key)
  136.         {
  137.                 if(!x) return 0;
  138.                 int cmp = compare(key, x->key);

  139.                 if (cmp == 0) return x;

  140.                 if (cmp < 0) return floor(x->left, key);

  141.                 Node* t = floor(x->right, key);
  142.                 if(t) return t;
  143.                 else return x;
  144.         }
  145.         
  146.         Value get(Node *x, Index& key)
  147.         { // Return value associated with key in the subtree rooted at x;
  148.           // return null if key not present in subtree rooted at x.
  149.                 if (!x) return 0;
  150.                 int cmp = compare(key, x->key);
  151.                 if (cmp < 0) return get(x->left, key);
  152.                 else if (cmp > 0) return get(x->right, key);
  153.                 else return x->val;
  154.         }
  155.         
  156.         Node* put(Node* h, Index key, Value val)
  157.         {
  158.                 if(!h)
  159.                 {
  160.                         h = new Node(key, val, 1, RED);
  161.                         return h;
  162.                 }
  163.                 int cmp = compare(key, h->key);
  164.                 if(cmp < 0)
  165.                         h->left  = put(h->left, key, val);
  166.                 else if(cmp > 0)
  167.                         h->right = put(h->right, key, val);
  168.                 else
  169.                         h->val = val;

  170.                 return balance(h);
  171.         }

  172.         Node* select(Node* x, int& k)
  173.         {   // Return Node containing key of rank k.
  174.                 if(!x) return 0;
  175.                 int t = size(x->left);
  176.                 if (t > k) return select(x->left, k);
  177.                 else if (t < k) return select(x->right, k-t-1);
  178.                 else return x;
  179.         }

  180.         int   rank(Index& key, Node* x)
  181.         {
  182.                 if(!x) return 0;
  183.                 int cmp = compare(key, x->key);
  184.                 if (cmp < 0) return rank(key, x->left);
  185.                 else if (cmp > 0) return 1 + size(x->left) + rank(key, x->right);
  186.                 else return size(x->left);
  187.         }

  188.         Node* delMin(Node* h)
  189.         {
  190.                 if (!(h->left)) return 0;
  191.                 if (!isRed(h->left) && !isRed(h->left->left))
  192.                         h = moveRedLeft(h);
  193.                 h->left = delMin(h->left);
  194.                 return balance(h);
  195.         }

  196.         Node* del(Node* h, Index& key)
  197.         {
  198.                 if(!h) return 0;
  199.                 int cmp = compare(key, h->key);
  200.                 /* search for key */
  201.                 if (cmp < 0)
  202.                 {
  203.                         if (!isRed(h->left) && !isRed(h->left->left))
  204.                                 h = moveRedLeft(h);
  205.                         h->left = del(h->left, key);
  206.                 }
  207.                 else
  208.                 {
  209.                         if (isRed(h->left))
  210.                                 h = rotateRight(h);
  211.                         if (!cmp && (!h->right))
  212.                                 return 0;
  213.                         if (!isRed(h->right) && !isRed(h->right->left))
  214.                                 h = moveRedLeft(h);
  215.                         if (!cmp)
  216.                         {
  217.                                 /* replace with successor */
  218.                                 Node* x = min(h->right);
  219.                                 h->key = x->key;
  220.                                 h->val = x->val;
  221.                                 h->right = delMin(h->right);
  222.                         }
  223.                         else h->right = del(h->right, key);
  224.                 }
  225.                 return balance(h);
  226.         }
  227.         
  228.         int   compare(Index& v, Index& w) const
  229.         {
  230.                 if(v > w)      return  1;
  231.                 else if(v < w) return -1;
  232.                 return 0;
  233.         }

  234.         void inorder(Node* x, Queue<Index>& q)
  235.         {
  236.                 if(!x) return;
  237.                 inorder(x->left, q);
  238.                 q.push(x->key);
  239.                 inorder(x->right, q);
  240.         }
  241. };

  242. #endif
复制代码
仍然采用中序遍历。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-3-23 13:51:51 | 显示全部楼层
总感觉在BST的initializer_list上才声明RED和BLACK的值有点晚。而且不能体现C和C++的特点。于是试着改了改代码,应用类内的enum类型。于是去掉后面的声明,并将
  1.         const bool RED;
  2.         const bool BLACK;
复制代码
这两行改成了简单明了的
  1.         enum { RED = true, BLACK = false };
复制代码
编译通过,大家可以试一试。注意这个枚举类型是没有枚举名称的~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-27 04:34

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表