码迷,mamicode.com
首页 > 其他好文 > 详细

二叉查找树

时间:2015-09-08 09:40:53      阅读:197      评论:0      收藏:0      [点我收藏+]

标签:二叉查找树   二叉查找树的删除   二叉查找树的查询   二叉查找树的插入   

虽然在需要优先级队列的应用程序中,堆非常合适,但它并不适用删除任意元素的应用,从具有n个元素的堆中删除任意元素的时间开销为O(n),并且查询任意元素的时间开销也是O(n),因此当进行插入,删除和查找操作,二叉查找树的性能就非常的适合。
二叉查找树,具有如下性质:

  • 每个元素都有关键字,任意两个元素的关键字都不相同,即,关键字是唯一的。
  • 非空左子树的关键字值一定小于其子树根结点的关键字值。
  • 非空右子树的关键字值一定大于其子树根结点的关键字值。
  • 左,右子树仍然是二叉查找树。
    一颗符合以上性质的叉查找树,如图:
    技术分享
    二叉查找树的查找过程:假设要查找一个关键字为key的元素,则从root开始查找,如果root是NULL,则此二叉树不包含任何元素,查找失败,否则,将key与root的关键字比较,如果key的值等于root的关键字值,则查找成功结束,如果key值小于root的关键字值,则说明右子树中不存在关键字值等于key的元素,因此只需要查找root的左子树,如果key值大于root的关键字值,则需要查找root的右子树,其时间复杂度为O(log2N),查找过程如图:
    技术分享
    递归查找实现:
//递归二叉查找树查找
tree_pointer search(tree_pointer root,int key)
{
   if(!root) return NULL;
   if(root->data==key)
      return root;
   if(root->data>key)
      return search(root->left_child,key);
   else
      return search(root->right_child,key);
}

迭代查找实现:

//迭代二叉查找树查找
tree_pointer search2(tree_pointer root,int key)
{
   while(root)
   {
      if(root->data==key)
         return root;
      if(root->data>key)
         root=root->left_child;
      else
         root=root->right_child;
   }
   return NULL;
}

二叉查找树的插入:
要插入一个关键字值为key的新元素,必须首先确认这个关键字与现有的元素的关键字值都不同,为此,对二叉查找树进行查找,如果查找不成功,则将元素插入到查询结束处,时间复杂度为O(log2N).
技术分享
代码实现:

//如果树为空,或该关键字值已存在,则返回NULL,否则返回查找过程中遇到的树中最后一个结点的指针
tree_pointer modified_search(tree_pointer root,int key)
{
   tree_pointer lastroot=NULL;
   while(root)
   {
      lastroot=root;
      if(root->data==key)
         return NULL;
      if(root->data>key)
         root=root->left_child;
      else
         root=root->right_child;
   }
   return lastroot;
}
//插入操作
void insert_node(tree_pointer *node,int num)
{
   tree_pointer ptr,temp=modified_search(*node,num);
   if(temp||!(*node))
   {
      ptr=(tree_pointer)malloc(sizeof(node));
      ptr->data=num;
      ptr->left_child=ptr->right_child=NULL;
      if(*node)
         {
            if(ptr->data<temp->data)
               temp->left_child=ptr;
            else
               temp->right_child=ptr;
         }
      else
         *node=ptr;
   }
}

二叉查找树的删除:
二叉查找树的删除也是常用的操作,其时间复杂度为O(log2N),而删除目标结点要考虑以下三种情况以及对应的处理:

  • 如果目标结点是叶子结点,那就直接删除。
  • 如果目标结点是仅有一个子结点,那么在删除后,令其唯一的子结点取代原来的位置。
  • 如果目标结点结点有两个儿子结点,在删除时,先用其左子树中的最大元素或者其右子树的最小元素替代给结点,然后,将替代结点从其子树中删除。
    代码实现:
//删除元素操作
void delete_node(tree_pointer node,int num)
{
   if(!node)
      return;
   if(num<node->data)
      delete_node(node->left_child,num);
   else if(num>node->data)
      delete_node(node->right_child,num);
    //如果目标有两个结点的情况
   else if(node->left_child!=NULL&&node->right_child!=NULL)
   {
      tree_pointer minnode=node->right_child;
      //寻找右子树的最小结点
      while(minnode->left_child)
         minnode=minnode->left_child;
      node->data=minnode->data;
      delete_node(minnode,minnode->data);
   }
   //如果目标结点有一个儿子结点或者没有儿子结点的情况
   else
   {
      tree_pointer deleteNode=node;
      node=(node->left_child!=NULL) ?node->left_child:node->right_child;
      free(deleteNode);
   }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

二叉查找树

标签:二叉查找树   二叉查找树的删除   二叉查找树的查询   二叉查找树的插入   

原文地址:http://blog.csdn.net/xuguoli_beyondboy/article/details/48276883

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!