Advertisement
pipian

markov_map.cpp

Dec 11th, 2011
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.96 KB | None | 0 0
  1. #include <cassert>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <string>
  5. #include <ext/hash_map>
  6.  
  7. #include "markov_map.h"
  8.  
  9. markov_tree::node::node(markov_tree::node *parent,
  10.             const std::string& value) :
  11.     left_count(0), node_count(0), right_count(0),
  12.     left(NULL), node_parent(parent), right(NULL), balance(0) {
  13.     this->node_value = new char[value.size() + 1];
  14.     strcpy(const_cast<char*>(this->node_value), value.c_str());
  15. }  /* markov_tree::node::node() */
  16.  
  17. markov_tree::node::node(const markov_tree::node& node) {
  18.     if (node.node_value == NULL) {
  19.     this->node_value = NULL;
  20.     } else {
  21.     this->node_value = new char[strlen(node.node_value) + 1];
  22.     strcpy(const_cast<char*>(this->node_value), node.node_value);
  23.     }
  24.    
  25.     this->left_count = node.left_count;
  26.     this->node_count = node.node_count;
  27.     this->right_count = node.right_count;
  28.    
  29.     if (node.left == NULL) {
  30.     this->left = NULL;
  31.     } else {
  32.     this->left = new markov_tree::node(*node.left);
  33.     this->left->node_parent = this;
  34.     }
  35.     this->node_parent = node.node_parent;
  36.     if (node.right == NULL) {
  37.     this->right = NULL;
  38.     } else {
  39.     this->right = new markov_tree::node(*node.right);
  40.     this->right->node_parent = this;
  41.     }
  42.    
  43.     this->balance = node.balance;
  44. }  /* markov_tree::node::node(const markov_tree::node&) */
  45.  
  46. markov_tree::node::~node() {
  47.     if (this->node_value != NULL) {
  48.     delete this->node_value;
  49.     }
  50.     if (this->left != NULL) {
  51.     delete this->left;
  52.     }
  53.     if (this->right != NULL) {
  54.     delete this->right;
  55.     }
  56. }  /* markov_tree::node::~node() */
  57.  
  58. markov_tree::node& markov_tree::node::operator=(const markov_tree::node& node) {
  59.     if (this != &node) {
  60.     if (this->node_value != NULL) {
  61.         delete this->node_value;
  62.         this->node_value = NULL;
  63.     }
  64.     if (node.node_value != NULL) {
  65.         size_t len = strlen(node.node_value) + 1;
  66.        
  67.         this->node_value = new char[len];
  68.         strcpy(const_cast<char*>(this->node_value), node.node_value);
  69.     }
  70.    
  71.     this->left_count = node.left_count;
  72.     this->node_count = node.node_count;
  73.     this->right_count = node.right_count;
  74.    
  75.     if (this->left != NULL) {
  76.         delete this->left;
  77.         this->left = NULL;
  78.     }
  79.     if (node.left != NULL) {
  80.         this->left = new markov_tree::node(*node.left);
  81.         this->left->node_parent = this;
  82.     }
  83.     this->node_parent = node.node_parent;
  84.     if (this->right != NULL) {
  85.         delete this->right;
  86.         this->right = NULL;
  87.     }
  88.     if (node.right != NULL) {
  89.         this->right = new markov_tree::node(*node.right);
  90.         this->right->node_parent = this;
  91.     }
  92.    
  93.     this->balance = node.balance;
  94.     }
  95.     return *this;
  96. }  /* markov_tree::node::operator=(const markov_tree::node&) */
  97.  
  98. void markov_tree::node::rebalance(int balance_increment) {
  99.     this->balance += balance_increment;
  100.     if (this->balance == -2) {
  101.     /* Right subtree outweighs left subtree. */
  102.     markov_tree::node *tmp;
  103.     if (this->right->balance == 1) {
  104.         /* Right rotation with R as root (right-left) */
  105.         tmp = this->right->left;
  106.        
  107.         tmp->right->node_parent = this->right;
  108.         this->right->left = tmp->right;
  109.         this->right->left_count = tmp->right_count;
  110.        
  111.         this->right->node_parent = tmp;
  112.         tmp->right = this->right;
  113.         tmp->right_count +=
  114.         this->right->node_count + this->right->right_count;
  115.        
  116.         tmp->node_parent = this;
  117.         this->right = tmp;
  118.        
  119.         if (this->right->balance == -1) {
  120.         this->right->balance = -2;
  121.         this->right->right->balance = 0;
  122.         } else if (this->right->balance == 0) {
  123.         this->right->balance = -1;
  124.         this->right->right->balance = 0;
  125.         } else {
  126.         this->right->balance = -1;
  127.         this->right->right->balance = -1;
  128.         }
  129.     }
  130.     /* Left rotation with P as root */
  131.     tmp = this->right;
  132.    
  133.     tmp->left->node_parent = this;
  134.     this->right = tmp->left;
  135.     this->right_count = tmp->left_count;
  136.    
  137.     tmp->node_parent = this->node_parent;
  138.     if (this->node_parent != NULL) {
  139.         if (this->node_parent->right == this) {
  140.         this->node_parent->right = tmp;
  141.         balance_increment = -1;
  142.         } else {
  143.         this->node_parent->left = tmp;
  144.         balance_increment = 1;
  145.         }
  146.     }
  147.    
  148.     this->node_parent = tmp;
  149.     tmp->left = this;
  150.     tmp->left_count += this->left_count + this->node_count;
  151.    
  152.     if (tmp->balance == -2) {
  153.         tmp->balance = 0;
  154.         this->balance = 1;
  155.     } else if (tmp->balance == -1) {
  156.         tmp->balance = 0;
  157.         this->balance = 0;
  158.     }
  159.     } else if (this->balance == 2) {
  160.     /* Left subtree outweighs right subtree. */
  161.     markov_tree::node *tmp;
  162.     if (this->left->balance == -1) {
  163.         /* Left rotation with R as root (right-left) */
  164.         tmp = this->left->right;
  165.        
  166.         tmp->left->node_parent = this->left;
  167.         this->left->right = tmp->left;
  168.         this->left->right_count = tmp->left_count;
  169.        
  170.         this->left->node_parent = tmp;
  171.         tmp->left = this->left;
  172.         tmp->left_count +=
  173.         this->left->left_count + this->left->node_count;
  174.        
  175.         tmp->node_parent = this;
  176.         this->left = tmp;
  177.        
  178.         if (this->left->balance == 1) {
  179.         this->left->balance = 2;
  180.         this->left->left->balance = 0;
  181.         } else if (this->left->balance == 0) {
  182.         this->left->balance = 1;
  183.         this->left->left->balance = 0;
  184.         } else {
  185.         this->left->balance = 1;
  186.         this->left->left->balance = 1;
  187.         }
  188.     }
  189.     /* Right rotation with P as root */
  190.     tmp = this->left;
  191.    
  192.     tmp->right->node_parent = this;
  193.     this->left = tmp->right;
  194.     this->left_count = tmp->right_count;
  195.    
  196.     tmp->node_parent = this->node_parent;
  197.     if (this->node_parent != NULL) {
  198.         if (this->node_parent->right == this) {
  199.         this->node_parent->right = tmp;
  200.         } else {
  201.         this->node_parent->left = tmp;
  202.         }
  203.     }
  204.    
  205.     this->node_parent = tmp;
  206.     tmp->right = this;
  207.     tmp->right_count += this->node_count + this->right_count;
  208.    
  209.     tmp->balance = 0;
  210.     tmp->left->balance = 0;
  211.     tmp->right->balance = 0;
  212.    
  213.     if (tmp->balance == 2) {
  214.         tmp->balance = 0;
  215.         this->balance = -1;
  216.     } else if (tmp->balance == 1) {
  217.         tmp->balance = 0;
  218.         this->balance = 0;
  219.     }
  220.     } else if (this->node_parent != NULL) {
  221.     if (this->node_parent->left == this) {
  222.         this->node_parent->rebalance(1);
  223.     } else if (this->node_parent->right == this) {
  224.         this->node_parent->rebalance(-1);
  225.     }
  226.     }
  227. }  /* markov_tree::node::rebalance() */
  228.  
  229. void markov_tree::node::fix_count(const markov_tree::node* child) {
  230.     if (child == this->left) {
  231.     this->left_count++;
  232.     } else {
  233.     this->right_count++;
  234.     }
  235.     if (this->node_parent != NULL) {
  236.     this->node_parent->fix_count(this);
  237.     }
  238. }  /* markov_tree::node::fix_count(const markov_tree::node*) */
  239.  
  240. inline double markov_tree::node::scaled_left_count() const {
  241.     return (double)this->left_count /
  242.     (this->left_count + this->node_count + this->right_count);
  243. }  /* markov_tree::node::scaled_left_count() */
  244.  
  245. inline double markov_tree::node::scaled_right_count() const {
  246.     return (double)this->right_count /
  247.     (this->left_count + this->node_count + this->right_count);
  248. }  /* markov_tree::node::scaled_right_count() */
  249.  
  250. inline const std::string markov_tree::node::value() const {
  251.     return std::string(this->node_value);
  252. }  /* markov_tree::node::value() */
  253.  
  254. inline unsigned long markov_tree::node::count() const {
  255.     return this->node_count;
  256. }  /* markov_tree::node::count() */
  257.  
  258. const markov_count& markov_tree::node::add(const std::string& x) {
  259.     assert(this->node_value != NULL);
  260.     int order = strcmp(x.c_str(), this->node_value);
  261.     if (order == 0) {
  262.     /* We have a match. */
  263.     this->node_count++;
  264.     this->node_parent->fix_count(this);
  265.     return *this;
  266.     } else if (order < 0) {
  267.     if (this->left == NULL) {
  268.         this->left = new markov_tree::node(this, x);
  269.         this->rebalance(1);  /* Left subtree is now one level deeper. */
  270.     }
  271.     return this->left->add(x);
  272.     } else if (order > 0) {
  273.     if (this->right == NULL) {
  274.         this->right = new markov_tree::node(this, x);
  275.         this->rebalance(-1);  /* Right subtree is now one level deeper. */
  276.     }
  277.     return this->right->add(x);
  278.     } else {
  279.     /* This should never happen. */
  280.     assert(false);
  281.     }
  282. }  /* markov_tree::node::add(const char*) */
  283.  
  284. const char* markov_tree::node::random(int seed) const {
  285.     if (seed < 0 || seed > RAND_MAX) {
  286.     seed = RAND_MAX;
  287.     }
  288.     double scaled_seed = ((double)seed / ((unsigned int)RAND_MAX + 1));
  289.     if (scaled_seed < this->scaled_left_count()) {
  290.     /* Left of the left bound, so pick from that. */
  291.     return this->left->random((double)seed / this->scaled_left_count());
  292.     } else if ((1.0 - scaled_seed) <= this->scaled_right_count()) {
  293.     /* Right of the right bound, so pick from that. */
  294.     return this->right->random(
  295.         RAND_MAX - (double)(RAND_MAX - seed) / this->scaled_right_count());
  296.     } else {
  297.     /* In the bounds of this node, so pick it. */
  298.     return this->node_value;
  299.     }
  300. }  /* markov_tree::node::random(int) */
  301.  
  302. inline markov_tree::markov_tree() : root(NULL) {
  303.    
  304. }  /* markov_tree::markov_tree() */
  305.  
  306. inline markov_tree::markov_tree(const markov_tree& tree) : root(NULL) {
  307.     if (tree.root != NULL) {
  308.     this->root = new markov_tree::node(*tree.root);
  309.     }
  310. }  /* markov_tree::markov_tree(const markov_tree&) */
  311.  
  312. inline markov_tree::~markov_tree() {
  313.     if (this->root != NULL) {
  314.     delete this->root;
  315.     }
  316. }  /* markov_tree::~markov_tree() */
  317.  
  318. inline markov_tree& markov_tree::operator=(const markov_tree& tree) {
  319.     if (this != &tree) {
  320.     if (this->root != NULL) {
  321.         delete this->root;
  322.         this->root = NULL;
  323.     }
  324.     if (tree.root != NULL) {
  325.         this->root = new markov_tree::node(*tree.root);
  326.     }
  327.     }
  328.     return *this;
  329. }  /* markov_tree::operator=(const markov_tree&) */
  330.  
  331. inline const markov_count& markov_tree::add(const std::string& x) {
  332.     if (this->root == NULL) {
  333.     /* This is the first entry ever inserted into the tree. */
  334.     this->root = new markov_tree::node(NULL, x);
  335.     }
  336.     return this->root->add(x);
  337. }  /* markov_tree::add(const std::string&) */
  338.  
  339. inline const char* markov_tree::random() const {
  340.     if (this->root == NULL) {
  341.     return "";
  342.     } else {
  343.     return this->root->random(rand());
  344.     }
  345. }  /* markov_tree::random() */
  346.  
  347. inline markov_map::markov_map() : trees() {
  348.    
  349. }  /* markov_map::markov_map() */
  350.  
  351. inline markov_map::markov_map(const markov_map& map) : trees(map.trees) {
  352.    
  353. }  /* markov_map::markov_map(const markov_map&) */
  354.  
  355. inline markov_map& markov_map::operator=(const markov_map& map) {
  356.     this->trees = map.trees;
  357.     return *this;
  358. }  /* markov_map::operator=(const markov_map&) */
  359.  
  360. inline const markov_count& markov_map::add(const std::string& x, const std::string& y) {
  361.     /* Use x as the key to get the probability tree. */
  362.     return this->trees[x.c_str()].add(y);
  363. }  /* markov_map::add(const std::string&, const std::string&) */
  364.  
  365. inline const std::string markov_map::random(const std::string& x) const {
  366.     stdext::hash_map<const char*, markov_tree, stdext::hash<const char*>, eqstr>::const_iterator iter = this->trees.find(x.c_str());
  367.     if (iter == this->trees.end()) {
  368.     return std::string();
  369.     } else {
  370.     return std::string(iter->second.random());
  371.     }
  372. }  /* markov_map::random(const std::string& x) */
  373.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement