Chinaunix首页 | 论坛 | 博客
  • 博客访问: 492132
  • 博文数量: 72
  • 博客积分: 1851
  • 博客等级: 上尉
  • 技术积分: 1464
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-16 17:50
文章分类

全部博文(72)

文章存档

2013年(1)

2012年(17)

2011年(51)

2010年(3)

分类: C/C++

2011-09-17 11:14:25

在普通的二叉树中,由于没有进行处理,导致整个树出现不平衡,然而,可将堆的思想放入二叉树中,这样在一定程度上会出现二叉搜索树的平衡,这样就得到了一个新的数据结构treap.treap中不仅有插入的键值,还附带一个堆的值段:priority,键值按照二叉树来进行处理,priority则通过大顶堆或小顶堆的性质进行处理,如大顶堆则有一下特征:

1.如果vu的左孩子,key[u] > key[v];

2.如果vu的右孩子,key[u] < key[v];

3.如果vu的孩子,priority[u] > priority[v].

可以证明treap的高位lgn,搜索时间为lgn,不过为了达到这样的性质,一般priority采用随机获取.

下面是插入算法:

与普通的二叉树方法类似,先查找到合适的节点,插入之后,进行堆的属性调整.

  1. int treap_insert(struct treap_root *root,struct treap_node *node)
  2. {
  3.     int res = 0;
  4.     struct treap_node *p;
  5.     
  6.     p = _treap_find(root,node->value);


  7.     if(!p)
  8.     {
  9.         root->root = node;
  10.     }
  11.     else
  12.     {
  13.         if(p->value > node->value)     
  14.         {
  15.             p->left = node;
  16.             node->parent = p;
  17.         }
  18.         else
  19.         {
  20.             p->right = node;
  21.             node->parent = p;
  22.         }

  23.         //max heap or min heap
  24.         if((root->flag && node->priority>p->priority) || \
  25.             (!root->flag && node->priority < p->priority) )    
  26.         _treap_adjust(root,node);
  27.     }
  28.     root->length ++;
  29.     return res;    
  30. }

调整与普通的堆不同,这里需要采用旋转来保证堆中的二叉树性质.

  1. void _treap_adjust(struct treap_root *root,struct treap_node *node)
  2. {
  3.     long lvalue,lpriority;
  4.     struct treap_node *p,*q;
  5.     long rvalue,rpriority;    

  6.     p = node;
  7.     q = p->parent;

  8.     while(p&&q)
  9.     {
  10.         if(root->flag && q->priority >= p->priority) break;
  11.         
  12.         if(!root->flag && q->priority <= p->priority) break;
  13.             
  14.         //max heap
  15.         if(root->flag && q->priority < p->priority)
  16.         {
  17.             if(q->left == p) right_rotate(root,q);
  18.             else         left_rotate(root,q);    
  19.         }
  20.         //min heap
  21.         if(!root->flag && q->priority > p->priority)
  22.         {
  23.             if(q->left == p)
  24.                     right_rotate(root,q);
  25.             else        left_rotate(root,q);
  26.         }
  27.         q = p->parent;
  28.     }
  29.     
  30. }

二叉树的删除:

先查找到后继,进行替换之后,进行堆的性质调整.

  1. int treap_delete(struct treap_root *root,struct treap_node *node)
  2. {
  3.     struct treap_node *p,*q;
  4.     
  5.     q = NULL;
  6.     
  7.     if(!root->length) return 0;
  8.     
  9.     p = treap_successor(node);
  10.     
  11.     //no right child
  12.     if(!p) {
  13.         q = node->left;
  14.         if(root->root == node) root->root = q;
  15.         else
  16.         if(node->parent->left == node) {
  17.             node->parent->left = q;
  18.         } else {
  19.             node->parent->right = q;
  20.         }

  21.         if(q) q->parent = node->parent;
  22.         root->length --;
  23.         return 0;
  24.     }
  25.     
  26.     if(root->root == node) root->root = p;
  27.     else
  28.     if(node->parent->left == node) node->parent->left = p;
  29.     else             node->parent->right = p;
  30.     
  31.     q = p->right;
  32.     
  33.     if(p->parent!=node)
  34.     {
  35.     if(p->parent->left == p) p->parent->left = q;
  36.     else            p->parent->right = q;
  37.     }

  38.     if(q&&p->parent != node)
  39.     q->parent = p->parent;
  40.     
  41.     p->left = node->left;
  42.     
  43.     if(node->left)
  44.     node->left->parent = p;

  45.     if(node->right != p)
  46.     {
  47.     p->right = node->right;

  48.     if(node->right)
  49.     node->right->parent = p;
  50.     
  51.     }

  52.     p->parent = node->parent;    
  53.     
  54.     __adjust_child(root,p);    
  55.     root->length --;
  56.     return 0;    
  57. }

这里进行堆的调整,也需要进行旋转控制,来代替普通的交换数值

  1. void __adjust_child(struct treap_root *root,struct treap_node *node)
  2. {
  3.     struct treap_node *left = node->left;
  4.     struct treap_node *right = node->right;
  5.     struct treap_node *temp = node;
  6.     
  7.     //max heap    
  8.     if(root->flag) {
  9.     if(left && left->priority > temp->priority)     temp = left;
  10.     if(right && right->priority > temp->priority) temp = right;
  11.     //min heap        
  12.     } else {
  13.     if(left && left->priority < temp->priority) temp = left;
  14.     if(right && right->priority < temp->priority) temp = right;
  15.     }

  16.     if(temp != node)
  17.     {
  18.         if(node->left == temp) right_rotate(root,node);
  19.         else            left_rotate(root,node);
  20.         __adjust_child(root,node);
  21.     }
  22. }

 treaps.rar   

参考资料:

1.算法导论

2.堆的数据结构

3.treap的作者主页:


阅读(2054) | 评论(0) | 转发(0) |
0

上一篇:Linux调度器

下一篇:进程的运行过程

给主人留下些什么吧!~~