二叉查找树的简单操作

 近几天来研究伸展树,但一直都没有进展,想既然伸展树是一棵二叉查找树,那么先把二叉查找树的各种操作弄清楚了,再来研究伸展树也许会有突破!

    二叉查找树是一种在log复杂度内实现快速查找元素的一种数据结构。其改进的树有红黑树,AVL树,平衡二叉树,节点大小平衡树,伸展树。

    同其它数据结构一下,二叉查找树的操作有 查插删改 四种。我个人觉得,二叉查找树的删除是最难的,需要考虑的因素比较多,但毕竟还是可以实现出来的。这里呢,我主要把我自己实现删除操作的思路整理出来,供大家参考。

    首先要说明的,一般的二叉查找树是不允许元素重复的,这里我稍微改动了一下,允许元素的重复。

    删除元素步骤如下:

   第一步:找到要删除元素的结点(*cur)及其父节点(*parent)。

   第二步:删除元素,删除元素分以下几种情况;

           如果cur的值在树中有多个,则只删除一个,返回。

           如果cur是叶子节点,则直接删除,并把其parent指向cur的指针置为空。

           如果cur只有一个孩子,则把parent原来指向cur的指针指向cur的孩子。

           如果cur有两个孩子(我们称之为左子树和右子树),则把其左子树接到右子树的最左边的叶子结点上,然后把parent原来指向cur的指针指向cur的右子树。

  第三步:delete cur.

  这样的话,就实现了二叉查找树的删除操作。

 

   我们知道,如果把二叉树中序遍历,则是让它从小到大的输出,那么怎么使其从大到小的输出呢?把遍历的顺序变一下就可以了,先输出右子树,再输出当前结点,最后输出左子树。我把这个操作定义为:变异的中序遍历(variation_inorder_traversal)。

   其查找和更新操作就很简单了,这里就把代码贴出来吧!

 

 
 
  1. /* 
  2.  * BinarySearchTree.cpp 
  3.  * 
  4.  *  Created on: 2012-9-15 
  5.  *      Author: Administrator 
  6.  */ 
  7. #include<stdio.h> 
  8. #include<string.h> 
  9. struct Node{ 
  10.     int value; 
  11.     int count; 
  12.     Node *left,*right; 
  13.     Node(){ 
  14.         count=1; 
  15.         left=NULL;right=NULL; 
  16.     } 
  17. }; 
  18. bool insert(Node **cur,int value){ 
  19.     if((*cur)!=NULL){ 
  20.         if((*cur)->value>value){ 
  21.             return insert(&((*cur)->left),value); 
  22.         }else if((*cur)->value<value){ 
  23.             return insert(&((*cur)->right),value); 
  24.         }else
  25.             printf("the element %d has been in the tree\n",value); 
  26.             (*cur)->count+=1; 
  27.             return false
  28.         } 
  29.     }else
  30.         Node *p=new Node(); 
  31.         p->value=value; 
  32.         *cur=p; 
  33.         return true
  34.     } 
  35. //从树中查找某个元素 
  36. Node* search(Node *cur,const int &value){ 
  37.     if(cur->value==value){//如果找到了怎么办 
  38.         return cur; 
  39.     }else if(cur->value>value&&cur->left!=NULL){ 
  40.         return search(cur->left,value); 
  41.     }else if(cur->value<value&&cur->right!=NULL){ 
  42.         return search(cur->right,value); 
  43.     }else
  44.         printf("No Element!\n"); 
  45.         return NULL; 
  46.     } 
  47. //从树中删除指定值的元素 
  48. void deleteElement(Node **root,const int &value){ 
  49.     if(*root==NULL){ 
  50.         printf("the tree is empty!\n"); 
  51.         return
  52.     } 
  53.     //找到要删除的结点,及父结点 
  54.     Node *parent,*cur; 
  55.     parent=cur=(*root); 
  56.     bool find=false
  57.     while(cur&&!find){ 
  58.         if(cur->value==value){ 
  59.             find=true
  60.         }else if(value>cur->value){ 
  61.             parent=cur; 
  62.             cur=cur->right; 
  63.         }else
  64.             parent=cur; 
  65.             cur=cur->left; 
  66.         } 
  67.     } 
  68.     if(!find){ 
  69.         printf("can not find the element %d!\n",value); 
  70.         return ; 
  71.     } 
  72.     //如果有多个元素,只删除一个 
  73.     if(cur->count>1){ 
  74.         cur->count-=1; 
  75.         return ; 
  76.     } 
  77.     //如果是叶子结点,直接删除 
  78.     if(cur->left==NULL&&cur->right==NULL){ 
  79.         if(parent==cur){//如果是根结点 
  80.             (*root)=NULL; 
  81.         }else if(parent->left==cur){//是左孩子 
  82.             parent->left=NULL; 
  83.         }else if(parent->right==cur){//是右孩子 
  84.             parent->right=NULL; 
  85.         } 
  86.     }else if(cur->right!=NULL){//树只有右孩子 
  87.         if(parent==cur){//如果是根结点 
  88.             (*root)=cur->right; 
  89.         }else if(parent->left==cur){//是左孩子 
  90.             parent->left=cur->right; 
  91.         }else if(parent->right==cur){//是右孩子 
  92.             parent->right=cur->right; 
  93.         } 
  94.     }else if(cur->left!=NULL){//树只有左孩子 
  95.         if(parent==cur){//如果是根结点 
  96.             (*root)=cur->left; 
  97.         }else if(parent->left==cur){//是左孩子 
  98.             parent->left=cur->left; 
  99.         }else if(parent->right==cur){//是右孩子 
  100.             parent->right=cur->left; 
  101.         } 
  102.     }else{//两个孩子都在:把左子树的根结点,接到右子树最左边的叶子结点 
  103.         Node *leaf; 
  104.         leaf=cur->right; 
  105.         while(leaf->left!=NULL){ 
  106.             leaf=leaf->left; 
  107.         } 
  108.         leaf->left=cur->left; 
  109.         if(parent==cur){//如果是根结点 
  110.             (*root)=cur->right; 
  111.         }else if(parent->left==cur){//是左孩子 
  112.             parent->left=cur->right; 
  113.         }else if(parent->right==cur){//是右孩子 
  114.             parent->right=cur->right; 
  115.         } 
  116.     } 
  117.     delete cur; 
  118.     printf("delete %d success!\n",value); 
  119. //中序输出二叉查找树:这其实也相当与排序了:将二叉树按元素的大小 ,从小到大输出 
  120. void inorder_traversal(Node *cur){ 
  121.     if(cur==NULL)return ; 
  122.     inorder_traversal(cur->left); 
  123.  
  124.     for(int i=0;i<cur->count;i++) 
  125.         printf("%d ",cur->value); 
  126.  
  127.     inorder_traversal(cur->right); 
  128. //我将其定义为变异的中序输出:将二叉树按元素的大小 ,从大到小输出 
  129. void variation_inorder_traversal(Node *cur){ 
  130.     if(cur==NULL)return ; 
  131.     variation_inorder_traversal(cur->right); 
  132.  
  133.     for(int i=0;i<cur->count;i++) 
  134.             printf("%d ",cur->value); 
  135.  
  136.     variation_inorder_traversal(cur->left); 
  137. //程序运行完,回收内存 
  138. void recycle(Node **cur,Node **parent){ 
  139.     if((*cur)==NULL)return
  140.     recycle(&((*cur)->left),cur); 
  141.     recycle(&((*cur)->right),cur); 
  142.  
  143.     if(((*cur)->left)==NULL&&((*cur)->right)==NULL){ 
  144.         if((*parent)!=NULL){ 
  145.             if(((*parent)->left)==(*cur)) 
  146.                 (*parent)->left=NULL; 
  147.             else (*parent)->right=NULL; 
  148.         } 
  149.         delete (*cur); 
  150.         (*cur)=NULL; 
  151.  
  152.     } 
  153. int main(){ 
  154.     int a[8]={0,4,6,23,567,34,8566,4}; 
  155.     Node *root; 
  156.     root=NULL; 
  157.     for(int i=0;i<8;i++){ 
  158.         insert(&root,a[i]); 
  159.     } 
  160.     printf("root=%d\n",root->value); 
  161.     printf("\nascending order: "); 
  162.     inorder_traversal(root);puts(""); 
  163.     printf("descending order: "); 
  164.     variation_inorder_traversal(root);puts(""); 
  165.  
  166. //  Node *p; 
  167. //  p=search(root,9); 
  168. //  if(p)printf("%d",p->value); 
  169. //  else printf("No data"); 
  170.     deleteElement(&root,7); 
  171.     deleteElement(&root,2); 
  172. //  deleteElement(&root,1); 
  173. //  deleteElement(&root,4); 
  174. //  deleteElement(&root,3); 
  175. //  deleteElement(&root,3); 
  176.     printf("after deleted,the left elements are: "); 
  177.     inorder_traversal(root);puts(""); 
  178.  
  179.     Node *q=NULL;recycle(&root,&q); 
  180.     if(root==NULL)printf("after recycle the root points NULL");//结点正常回收后,应输出NULL 

 参考文档:

   http://www.cnblogs.com/aiyelinglong/archive/2012/03/27/2419972.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值