鱼C论坛

 找回密码
 立即注册
查看: 1735|回复: 3

[技术交流] 随机化二叉树

[复制链接]
发表于 2014-4-27 15:26:53 | 显示全部楼层 |阅读模式

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

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

x
本帖最后由 andalousie 于 2014-4-27 15:33 编辑

感觉自己好久没在鱼C上发东西了,虽然总是签到。
今天发一个随机化二叉树吧,包含了中序遍历的迭代器。
和往常一样,直接上代码~
RandomizedBST.cpp
  1. #include <iostream>
  2. #include <string>
  3. #include "Random.h"
  4. #include "stack.h"

  5. template<typename Index, typename Value> class BSTIterator;

  6. template<typename Index, typename Value>
  7. class BST
  8. {
  9. protected:
  10.         struct Node
  11.         {
  12.                 Node (Index k, Value v)
  13.                 :key(k), val(v), left(0),
  14.                 right(0), N(1)
  15.                 {}
  16.                 Index key;                  // key
  17.         Value val;                  // associated data
  18.         Node *left, *right;         // left and right subtrees
  19.         int   N;                    // size of subtree rooted at this node
  20.         };
  21. public:
  22.         typedef BSTIterator<Index, Value> iterator;
  23.         friend class BSTIterator<Index, Value>;

  24.         BST(): root(0) {}
  25.         /*************************************************************************
  26.         *  BST search
  27.         *************************************************************************/
  28.         bool contains(Index& key) {
  29.                 return get(key) != 0;
  30.         }

  31.         // return value associated with the given key
  32.         // if no such value, return null
  33.         Value get(const Index& key) {
  34.                 return get(root, key);
  35.         }

  36.         /*************************************************************************
  37.         *  randomized insertion
  38.         *************************************************************************/
  39.         void put(Index key, Value val) {
  40.                 root = putRoot(root, key, val);
  41.         }

  42.         // remove and return value associated with given interval;
  43.         // if no such interval exists return null
  44.         Value remove(Index key) {
  45.                 Value value = get(key);
  46.                 root = remove(root, key);
  47.                 return value;
  48.         }

  49.         Index select(int k) { return select(root, k)->key; }

  50.         Index min()
  51.         {
  52.                 Index key = 0;
  53.                 for (Node * x = root; x; x = x->left)
  54.                         key = x->key;
  55.                 return key;
  56.         }

  57.         Index max()
  58.         {
  59.                 Index key = 0;
  60.                 for (Node * x = root; x; x = x->right)
  61.                         key = x->key;
  62.                 return key;
  63.         }

  64.         int size() { return size(root); }
  65.         int height() { return height(root); }

  66.         iterator begin() { return iterator(root); }
  67.         iterator end  () { return iterator(0); }
  68. private:
  69.         Node * root;
  70.         Random rnd;
  71.         int size(Node * x) {
  72.                 if (!x) return 0;
  73.                 else           return x->N;
  74.         }
  75.         int height(Node * x) {
  76.                 if (!x) return 0;
  77.                 return 1 + (height(x->left) > height(x->right)
  78.                                           ? height(x->left) : height(x->right));
  79.         }

  80.         //Private methods
  81.         Value get(Node *x, Index key)
  82.         {
  83.                 if (!x) return 0;
  84.                 int cmp = compare(key, x->key);
  85.                 if      (cmp < 0) return get(x->left, key);
  86.                 else if (cmp > 0) return get(x->right, key);
  87.                 else              return x->val;
  88.         }

  89.         // make new node the root with uniform probability
  90.         Node * put(Node * x, Index key, Value val) {
  91.                 if (!x) return new Node(key, val);
  92.                 int cmp = compare(key, x->key);
  93.                 if (!cmp)
  94.                 {
  95.                         x->val = val;
  96.                         return x;
  97.                 }
  98.                 if (rnd.bernoulli(1.0 / (size(x) + 1.0))) return putRoot(x, key, val);
  99.                 if (cmp < 0)  x->left  = put(x->left,  key, val);
  100.                 else          x->right = put(x->right, key, val);
  101.                 fix(x);
  102.                 return x;
  103.         }

  104.         Node * putRoot(Node * x, Index key, Value val) {
  105.                 if (!x) return new Node(key, val);
  106.                 int cmp = compare(key, x->key);
  107.                 if (!cmp)
  108.                 {
  109.                         x->val = val;
  110.                         return x;
  111.                 }
  112.                 if (cmp < 0)  { x->left  = putRoot(x->left,  key, val); x = rotR(x); }
  113.                 else          { x->right = putRoot(x->right, key, val); x = rotL(x); }
  114.                 return x;
  115.         }

  116.         Node * select(Node * x, int& k)
  117.         {   // Return Node containing key of rank k.
  118.                 if(!x) return 0;
  119.                 int t = size(x->left);
  120.                 if (t > k) return select(x->left, k);
  121.                 else if (t < k) return select(x->right, k-t-1);
  122.                 else return x;
  123.         }

  124.         /*************************************************************************
  125.         *  deletion
  126.         *************************************************************************/
  127.         Node * joinLR(Node * a, Node * b) {
  128.                 if (!a) return b;
  129.                 if (!b) return a;

  130.                 if (rnd.bernoulli((double) size(a) / (size(a) + size(b))))  {
  131.                         a->right = joinLR(a->right, b);
  132.                         fix(a);
  133.                         return a;
  134.                 }
  135.                 else {
  136.                         b->left = joinLR(a, b->left);
  137.                         fix(b);
  138.                         return b;
  139.                 }
  140.         }

  141.         Node * remove(Node * h, Index key) {
  142.                 if (!h) return 0;
  143.                 int cmp = compare(key, h->key);
  144.                 if      (cmp < 0) h->left  = remove(h->left,  key);
  145.                 else if (cmp > 0) h->right = remove(h->right, key);
  146.                 else              h = joinLR(h->left, h->right);
  147.                 fix(h);
  148.                 return h;
  149.         }

  150.         /*************************************************************************
  151.         *  helper BST functions
  152.         *************************************************************************/

  153.         // fix auxilliar information (subtree count and max fields)
  154.         void fix(Node * x) {
  155.                 if (!x) return;
  156.                 x->N = 1 + size(x->left) + size(x->right);
  157.         }

  158.         // right rotate
  159.         Node * rotR(Node * h) {
  160.                 Node * x = h->left;
  161.                 h->left = x->right;
  162.                 x->right = h;
  163.                 fix(h);
  164.                 fix(x);
  165.                 return x;
  166.         }

  167.         // left rotate
  168.         Node * rotL(Node * h) {
  169.                 Node * x = h->right;
  170.                 h->right = x->left;
  171.                 x->left = h;
  172.                 fix(h);
  173.                 fix(x);
  174.                 return x;
  175.         }

  176.         int   compare(Index& v, Index& w) const
  177.         {
  178.                 if     (v > w) return  1;
  179.                 else if(v < w) return -1;
  180.                 else           return  0;
  181.         }
  182. };

  183. /***********************************************************************
  184. *  Iterate using inorder traversal using a stack.
  185. *  Iterating through N elements takes O(N) time.
  186. ***********************************************************************/
  187. template<typename Index, typename Value>
  188. class BSTIterator
  189. {
  190.         typedef typename BST<Index, Value>::Node Node;
  191. public:
  192.         BSTIterator(Node * x)
  193.         {
  194.                 do_push(x);
  195.                 if (stack.Empty())
  196.                         _cur = 0;
  197.                 else
  198.                 {
  199.                         x = stack.Top();
  200.                         stack.Pop();
  201.                         _cur = x;
  202.                         do_push(x->right);
  203.                 }
  204.         }

  205.         void operator =  (const BSTIterator& it)
  206.         {
  207.                 stack = it.stack;
  208.                 _cur  = it._cur;
  209.         }

  210.         bool operator == (const BSTIterator& it)
  211.         {
  212.                 return _cur == it._cur;
  213.         }

  214.         bool operator != (const BSTIterator& it)
  215.         {
  216.                 return _cur != it._cur;
  217.         }

  218.         BSTIterator& operator ++ ()
  219.         {
  220.                 if (isEnd())
  221.                 {
  222.                         _cur = 0;
  223.                         return *this;
  224.                 }
  225.                 Node * x = stack.Top(); stack.Pop();
  226.                 _cur = x;
  227.                 do_push(x->right);
  228.                 return *this;
  229.         }

  230.         Index operator * () const { return _cur->key; }
  231. private:
  232.         Stack<Node *> stack;
  233.         Node *        _cur;

  234.         bool isEnd() { return stack.Empty(); }
  235.         void do_push(Node * x)
  236.         {
  237.                 while (x)
  238.                 {
  239.                         stack.Push(x);
  240.                         x = x->left;
  241.                 }
  242.         }
  243. };

  244. int main()
  245. {
  246.         BST<std::string, std::string> st;

  247.         st.put("www.cs.princeton.edu",   "128.112.136.11");
  248.         st.put("www.cs.princeton.edu",   "128.112.136.35");
  249.         st.put("www.princeton.edu",      "128.112.130.211");
  250.         st.put("www.math.princeton.edu", "128.112.18.11");
  251.         st.put("www.yale.edu",           "130.132.51.8");
  252.         st.put("www.amazon.com",         "207.171.163.90");
  253.         st.put("www.simpsons.com",       "209.123.16.34");
  254.         st.put("www.stanford.edu",       "171.67.16.120");
  255.         st.put("www.google.com",         "64.233.161.99");

  256.         std::cout << st.get("www.cs.princeton.edu") << std::endl;
  257.         std::cout << st.get("www.princeton.edu") << std::endl;

  258.         BST<std::string, std::string>::iterator it = st.begin();
  259.         while(it != st.end())
  260.         {
  261.                 std::cout << *it << " " << st.get(*it) << std::endl;
  262.                 ++it;
  263.         }
  264. }
复制代码
Random.h
  1. #ifndef RANDOM_H
  2. #define RANDOM_H

  3. // Random class
  4. // This code assumes 32-bit ints,
  5. // which are standard on modern compilers.
  6. //
  7. // CONSTRUCTION: with (a) no initializer or (b) an integer
  8. //     that specifies the initial state of the generator
  9. //
  10. // ******************PUBLIC OPERATIONS*********************
  11. //     Return a random number according to some distribution:
  12. // int randomInt( )                     --> Uniform, 1 to 2^31-1
  13. // int random0_1( )                     --> Uniform, 0 to 1
  14. // int randomInt( int low, int high )   --> Uniform low..high

  15. class Random
  16. {
  17.         public:
  18.                 explicit Random( int initialValue = 1 );

  19.                 int      randomInt( );
  20.                 double   random0_1( );
  21.                 int      randomInt( int low, int high );
  22.                 bool     bernoulli( double p );

  23.         private:
  24.                 int state;
  25. };

  26. //Implementations

  27. static const int A = 48271;
  28. static const int M = 2147483647;
  29. static const int Q = M / A;
  30. static const int R = M % A;

  31. /**
  32. * Construct with initialValue for the state.
  33. */
  34. Random::Random( int initialValue )
  35. {
  36.     if( initialValue < 0 )
  37.         initialValue += M;

  38.     state = initialValue;
  39.     if( state == 0 )
  40.         state = 1;
  41. }

  42. /**
  43. * Return a pseudorandom int, and change the
  44. * internal state.
  45. */
  46. inline int Random::randomInt( )
  47. {
  48.     int tmpState = A * ( state % Q ) - R * ( state / Q );

  49.     if( tmpState >= 0 )
  50.         state = tmpState;
  51.     else
  52.         state = tmpState + M;

  53.     return state;
  54. }

  55. /**
  56. * Return a pseudorandom double in the open range 0..1
  57. * and change the internal state.
  58. */
  59. inline double Random::random0_1( )
  60. {
  61.     return static_cast<double>( randomInt() ) / M;
  62. }

  63. /**
  64. * Return an int in the closed range [low,high], and
  65. * change the internal state. This is a poor implementation and
  66. * will be biased toward some numbers, especially if the range is large.
  67. */
  68. inline int Random::randomInt( int low, int high )
  69. {
  70.     double partitionSize = static_cast<double>( M ) / ( high - low + 1 );

  71.     return static_cast<int>( randomInt() / partitionSize ) + low;
  72. }

  73. /**
  74. * Returns a bool, which is true with probability p, and false otherwise.
  75. */
  76. inline bool Random::bernoulli(double p)
  77. {
  78.         if (!(p >= 0.0 && p <= 1.0))
  79.                 throw "Probability must be between 0.0 and 1.0";
  80.         return random0_1() < p;
  81. }

  82. #endif
复制代码
stack.h
  1. #pragma once
  2. #include <cassert>

  3. const int maxStack=16;

  4. template<class T>
  5. class Stack
  6. {
  7. public:
  8.         Stack():_top(0){}
  9.         void Push(T i);
  10.         void Pop();
  11.         T    Top() const;
  12.         bool Empty() const;
  13. private:
  14.         T    _arr [maxStack];
  15.         int  _top;
  16. };

  17. template<class T>
  18. void Stack<T>::Push(T i)
  19. {
  20.         assert (_top<maxStack);
  21.         _arr [_top]=i;
  22.         ++_top;
  23. }

  24. template<class T>
  25. void Stack<T>::Pop()
  26. {
  27.         assert (_top>0);
  28.         --_top;
  29. }

  30. template<class T>
  31. T Stack<T>::Top()const
  32. {
  33.         assert (_top>0);
  34.         return _arr [_top-1];
  35. }

  36. template<class T>
  37. bool Stack<T>::Empty() const
  38. {
  39.         return !_top;
  40. }
复制代码
这三个文件就是一个完整的随机化二叉树
还有一个随机化二叉树的应用,区间树。
  1. #include <iostream>
  2. #include <cassert>
  3. #include "Random.h"

  4. class Interval1D
  5. {
  6. public:
  7.         const int low;  // left endpoint
  8.         const int high; // right endpoint
  9.         Interval1D(int left, int right)
  10.                 :low(left), high(right)
  11.         {}
  12.         bool intersects(Interval1D& that) {
  13.         if (that.high < low) return false;
  14.         if (high < that.low) return false;
  15.         return true;
  16.     }
  17.         bool contains(int x) {
  18.         return (low <= x) && (x <= high);
  19.     }
  20.         int compareTo(Interval1D& that) {
  21.         if      (low  < that.low)  return -1;
  22.         else if (low  > that.low)  return +1;
  23.         else if (high < that.high) return -1;
  24.         else if (high < that.high) return +1;
  25.         else                            return  0;
  26.     }
  27. };

  28. class IntervalST
  29. {
  30.         typedef int Value;
  31.         struct Node
  32.         {
  33.                 Node(Interval1D i, Value v)
  34.                 :inv(i), val(v), left(0),
  35.                 right(0), N(1), max(i.high)
  36.                 {}
  37.                 Interval1D inv;        // key
  38.         Value val;                  // associated data
  39.         Node *left, *right;         // left and right subtrees
  40.         int N;                      // size of subtree rooted at this node
  41.         int max;                    // max endpoint in subtree rooted at this node
  42.         };
  43. public:
  44.         IntervalST(): root(0) {}
  45.         /*************************************************************************
  46.     *  BST search
  47.     *************************************************************************/
  48.         bool contains(Interval1D& inv) {
  49.         return get(inv) != 0;
  50.     }

  51.         // return value associated with the given key
  52.     // if no such value, return null
  53.     Value get(Interval1D& inv) {
  54.         return get(root, inv);
  55.     }

  56.         /*************************************************************************
  57.     *  randomized insertion
  58.     *************************************************************************/
  59.     void put(Interval1D inv, Value val) {
  60.         if (contains(inv))
  61.                 { std::cout << "duplicate" << std::endl; remove(inv);  }
  62.         root = randomizedInsert(root, inv, val);
  63.     }

  64.         // remove and return value associated with given interval;
  65.     // if no such interval exists return null
  66.     Value remove(Interval1D inv) {
  67.         Value value = get(inv);
  68.         root = remove(root, inv);
  69.         return value;
  70.     }

  71.         // return an interval in data structure that intersects the given inteval;
  72.     // return null if no such interval exists
  73.     // running time is proportional to log N
  74.         Interval1D search(Interval1D& inv) {
  75.         return search(root, inv);
  76.     }

  77.         // look in subtree rooted at x
  78.     Interval1D search(Node * x, Interval1D inv) {
  79.         while (!x) {
  80.             if (inv.intersects(x->inv))  return x->inv;
  81.             else if (!x->left)             x = x->right;
  82.             else if (x->left->max < inv.low)  x = x->right;
  83.             else                                 x = x->left;
  84.         }
  85.         return Interval1D(0, 0);
  86.     }

  87.         // return *all* intervals in data structure that intersect the given interval
  88.     // running time is proportional to R log N, where R is the number of intersections
  89.     void searchAll(Interval1D& inv) { searchAll(root, inv); }

  90.         // look in subtree rooted at x
  91.     bool searchAll(Node * x, Interval1D inv) {
  92.          bool found1 = false;
  93.          bool found2 = false;
  94.          bool found3 = false;
  95.          if (!x)
  96.             return false;
  97.         if (inv.intersects(x->inv)) {
  98.                         std::cout << '[' << x->inv.low
  99.                                 << ',' << x->inv.high << "]\n";
  100.             found1 = true;
  101.         }
  102.         if (x->left && x->left->max >= inv.low)
  103.             found2 = searchAll(x->left, inv);
  104.         if (found2 || !x->left || x->left->max < inv.low)
  105.             found3 = searchAll(x->right, inv);
  106.         return found1 || found2 || found3;
  107.     }

  108.         int size() { return size(root); }
  109.         int height() { return height(root); }
  110. private:
  111.         Node * root;
  112.         Random rnd;
  113.         int size(Node * x) {
  114.         if (!x) return 0;
  115.         else           return x->N;
  116.     }
  117.         int height(Node * x) {
  118.         if (!x) return 0;
  119.         return 1 + (height(x->left) > height(x->right)
  120.                                   ? height(x->left) : height(x->right));
  121.     }

  122.         //Private methods
  123.         Value get(Node *x, Interval1D& inv)
  124.         {
  125.                 if (!x) return 0;
  126.                 int cmp = inv.compareTo(x->inv);
  127.                 if      (cmp < 0) return get(x->left, inv);
  128.                 else if (cmp > 0) return get(x->right, inv);
  129.                 else              return x->val;
  130.         }

  131.         // make new node the root with uniform probability
  132.     Node * randomizedInsert(Node * x, Interval1D inv, Value val) {
  133.         if (!x) return new Node(inv, val);
  134.         if (rnd.random0_1() * size(x) < 1.0) return rootInsert(x, inv, val);
  135.         int cmp = inv.compareTo(x->inv);
  136.         if (cmp < 0)  x->left  = randomizedInsert(x->left,  inv, val);
  137.         else          x->right = randomizedInsert(x->right, inv, val);
  138.         fix(x);
  139.         return x;
  140.     }

  141.         Node * rootInsert(Node * x, Interval1D inv, Value val) {
  142.         if (!x) return new Node(inv, val);
  143.         int cmp = inv.compareTo(x->inv);
  144.         if (cmp < 0)  { x->left  = rootInsert(x->left,  inv, val); x = rotR(x); }
  145.         else          { x->right = rootInsert(x->right, inv, val); x = rotL(x); }
  146.         return x;
  147.     }

  148.         /*************************************************************************
  149.     *  deletion
  150.     *************************************************************************/
  151.     Node * joinLR(Node * a, Node * b) {
  152.         if (!a) return b;
  153.         if (!b) return a;

  154.         if (rnd.random0_1() * (size(a) + size(b)) < size(a))  {
  155.             a->right = joinLR(a->right, b);
  156.             fix(a);
  157.             return a;
  158.         }
  159.         else {
  160.             b->left = joinLR(a, b->left);
  161.             fix(b);
  162.             return b;
  163.         }
  164.     }

  165.         Node * remove(Node * h, Interval1D inv) {
  166.         if (!h) return 0;
  167.         int cmp = inv.compareTo(h->inv);
  168.         if      (cmp < 0) h->left  = remove(h->left,  inv);
  169.         else if (cmp > 0) h->right = remove(h->right, inv);
  170.         else              h = joinLR(h->left, h->right);
  171.         fix(h);
  172.         return h;
  173.     }

  174.         /*************************************************************************
  175.     *  helper BST functions
  176.     *************************************************************************/

  177.     // fix auxilliar information (subtree count and max fields)
  178.     void fix(Node * x) {
  179.         if (!x) return;
  180.         x->N = 1 + size(x->left) + size(x->right);
  181.         x->max = max3(x->inv.high, max(x->left), max(x->right));
  182.     }

  183.     int max(Node * x) {
  184.         if (!x) return -1;
  185.         return x->max;
  186.     }

  187.     // precondition: a is not null
  188.     int max3(int a, int b, int c) {
  189.                 int max = ( a < b ) ? b : a;
  190.         return ( ( max < c ) ? c : max );
  191.     }

  192.     // right rotate
  193.     Node * rotR(Node * h) {
  194.         Node * x = h->left;
  195.         h->left = x->right;
  196.         x->right = h;
  197.         fix(h);
  198.         fix(x);
  199.         return x;
  200.     }

  201.     // left rotate
  202.     Node * rotL(Node * h) {
  203.         Node * x = h->right;
  204.         h->right = x->left;
  205.         x->left = h;
  206.         fix(h);
  207.         fix(x);
  208.         return x;
  209.     }
  210. };

  211. int main()
  212. {
  213.         IntervalST st;
  214.         Random rand_inv;
  215.         for (int i = 0; i < 50; i++) {
  216.                 int low  = rand_inv.randomInt(0, 1000);
  217.                 int high = rand_inv.randomInt(0, 50) + low;
  218.                 Interval1D interval(low, high);
  219.                 st.put(interval, i);
  220.         }
  221.         Interval1D ready(400, 700);
  222.         st.searchAll(ready);
  223. }
复制代码
大家学习参考一下。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-4-27 15:39:14 | 显示全部楼层
VS2008测试通过
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-4-27 16:58:12 | 显示全部楼层
感谢楼主分享!《,,,,,,
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-8-12 08:58:56 | 显示全部楼层
谢谢楼主分享!!!!!!!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-11 14:38

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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