Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3892032
  • 博文数量: 146
  • 博客积分: 3918
  • 博客等级: 少校
  • 技术积分: 8585
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-17 13:52
个人简介

个人微薄: weibo.com/manuscola

文章分类

全部博文(146)

文章存档

2016年(3)

2015年(2)

2014年(5)

2013年(42)

2012年(31)

2011年(58)

2010年(5)

分类:

2011-07-10 11:53:01

前文二叉搜索树的C实现(2)中提到了,我们可以把二叉搜索树中的任意一个节点提拔成根,
方法如下:
1 调用bst_select(root,K),返回第K大的节点node
2 调用bst_bubble(root,node),把node,升为root。
注 其实bst_select(root,K) 返回的是第K+1大的节点,因为bst_select(root,0)是最小节点。
bst_node* bst_select_root(bst_node* root,int k)
{
 if(root == NULL)
 {
  printf("[bst_select_root] root is null\n");
  return root;
  }
if(k>root->counter || k < 0)
{
printf("k is not valid (%d-%d)\n",root->counter,k);
return root;
}
bst_node * node = bst_select(root,k);
if (node != NULL)
return bst_bubble(root,node);
else
return root;
}

bst_select函数在二叉搜索树C实现中已经实现了,为了方便阅读,在此再次贴出代码
bst_node* bst_select(bst_node* root,int k)
{
if(root == NULL)
return NULL;/*not find the kth node*/
int t=0;
if(root->left ==NULL)
t = 0;
else
t = root->left->counter;

if(t>k)       
return bst_select(root->left,k);
else if(t
return bst_select(root->right,k-t-1);
return root;
}

既然我们可以把任何一个节点提拔成根,这就启发了我们如何将二叉搜索树平衡,就是把key值是
中间的那个节点提拔成 根,这样左右就平衡了。如果我们递归操作,那么,我们就得到平衡二叉搜索树。

前提条件是,我们必须知道每棵树有多少个节点,树的节点个数需要维护一个专门的字段,counter。
表示以node为根的树共有多少个节点
node->counter = node->left->counter+node->right->counter +1;
当然上面的等式只是解释counter定义用的,实际需要讨论 左右孩子不存在的情况。
好在我们前文的代码中已经维护了counter这个字段。
bst_node* bst_balance(bst_node* root)
{
    if(root == NULL)
        return root ;
if(root->counter < 2 )
return root;
root = bst_select_root(root,root->counter/2);
root->left   = bst_balance(root->left);
if(root->left)
   root->left->parent = root;
root->right = bst_balance(root->right);
if(root->right)
   root->right->parent = root;

return root;
}


参考文献:
1 算法:C语言实现   Robert Sedgewick著

阅读(3181) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~