learning tree

一、二叉查找树(二叉搜索树或二叉排序树)

  

  定义:  

  二叉查找(搜索或排序)树(Binary Search Tree)。其定义为:二叉查找树或者是空树,或者是满足如下性质的二叉树:

①若它的左子树非空,则左子树上所有结点的值均小于(小于等于)根结点的值;

②若它的右子树非空,则右子树上所有结点的值均大于(大于等于)根结点的值;

③左、右子树本身又各是一棵二叉查找树。

  按中序遍历该树所得到的中序序列是一个递增有序序列。

  插入:

  在二叉查找树中插入新结点,要保证插入后仍满足BST性质。其插入过程是:

  (a)若二叉查找树T为空,则为待插入的关键字value申请一个新结点,并令其为根;

  (b)若二叉查找树T不为空,则将key和根的关键字比较:

      (i)若二者相等,则说明树中已有此关键字key,无须插入。

      (ii)若value<T.key,则将key插入根的左子树中。

      (iii)若value>T.key,则将它插入根的右子树中。

  子树中的插入过程与上述的树中插入过程相同。如此进行下去,直到将value作为一个新的叶结点的关键字插入到二叉查找树中,或者直到发现树中已有此关键字为止。

  注意:输入序列决定了二叉查找树的形态。二叉查找树的中序序列是一个有序序列。所以对于一个任意的关键字序列构造一棵二叉查找树,其实质是对

此关键字序列进行排序,使其变为有序序列。因此,人们又常常将二叉查找树称为二叉排序树。通常将这种排序称为树排序(Tree Sort),可以证明这种排

序的平均执行时间亦为O(nlgn)。对相同的输入实例,树排序的执行时间约为堆排序的2至3倍。因此在一般情况下,构造二叉排序树的目的并非为了排序,

而是用它来加速查找,这是因为在一个有序的集合上查找通常比在无序集合上查找更快,“查找树"的名称也由此而来。

  删除:

  从二叉查找树中删除一个结点,不能把以该结点为根的子树都删去,并且还要保证删除后所得的二叉树仍然满足BST性质。

  一般步骤如下:

  (a) 进行查找。查找时,令p指向当前访问到的结点,parent指向其双亲(其初值为NULL)。若树中找不到被删结点则返回,否则被删结点是p。
  (b) 删去p。删去p时,应将p的子树(若有)仍连接在树上且保持BST性质不变。按p的孩子数目分三种情况进行处理。
    (i)p是叶子(即它的孩子数为0),无须连接p的子树,只需将p的双亲parent中指向p的指针域置空即可。

    (ii)p只有一个孩子child,只需将child和p的双亲直接连接后,即可删去p。注意,p既可能是parent的左孩子也可能是其右孩子,而child可能是p      的左孩子或右孩子,故共有4种状态。
    (iii)p有两个孩子,先令q=p,将被删结点的地址保存在q中;然后找q的中序后继p,并在查找过程中仍用parent记住p的双亲位置。q的中序后继p      一定是q的右子树中最左下的结点,它无左子树。因此,可以将删去q的操作转换为删去的p的操作,即在释放结点p之前将其数据复制到q中,就      相当于删去了q。

  查找:

  在BST中查找一个值。如果树中的某个值与要查找的值相等,则返回这个结点,否则报告查找不成功。
  进行查找时,先用目标值与树根的值相比较。如果相等,则找到;否则,如果目标值大于根的值,则继续在根的右子树中继续查找;如果目标值小于根的值,则继续在根的左子树中继续查找。
  相同的关键字集合可能构成多棵不同的BST树。查找目标过程中,从根到目标结点之间的路径上的结点个数就是要进行比较的次数。树越平衡,要比较的次数越少。
  如果二叉树接近平衡,则在树中查找一个结点时,需要进行的比较次数接近O(log n)。如果树退化为一个直链,则树的查找类似于顺序查找,其比较次数接近于O(n) ,这是树查找中的最坏时间复杂度。
  一般不能预测要建立的二叉树的树型。实际上,如果关键字的排列是随机的,则建立的二叉树的树型将比较平衡,查找的效率接近二分查找。

  实现:

  

View Code
  1 tree.h
  2 #ifndef _TREE_H
  3 #define _TREE_H
  4 
  5 typedef int ElemType;
  6 
  7 typedef struct treenode
  8 {
  9     ElemType data;
 10     struct treenode * left;
 11     struct treenode * right;
 12 }TREE;
 13 
 14 
 15 
 16 TREE *MakeEmptyTree();
 17 
 18 TREE *InsertTreeNode(ElemType e,TREE *t);
 19 
 20 TREE *FindTreeNode(ElemType e,TREE *t);
 21 
 22 TREE *FindMax(TREE *t);
 23 
 24 TREE *FindMin(TREE *t);
 25 
 26 TREE *DeleteTreeNode(ElemType e,TREE *t);
 27 
 28 void DeleteTree(TREE **t);
 29 
 30 #endif
 31 
 32 tree.cpp
 33 #include<stdio.h>
 34 #include<stdlib.h>
 35 #include"tree.h"
 36 
 37 
 38 TREE *MakeEmptyTree()
 39 {
 40     return NULL;
 41 }
 42 
 43 TREE *InsertTreeNode(ElemType e,TREE *t)
 44 {
 45     if(t == NULL)
 46     {
 47         t = (TREE *)malloc(sizeof(TREE));
 48         if(t == NULL) return NULL;
 49         t->data = e;
 50         t->left = t->right = NULL;
 51     }else if(e < t->data)
 52         t->left = InsertTreeNode(e,t->left);
 53     else
 54         t->right = InsertTreeNode(e,t->right);
 55     return t;
 56 }
 57 
 58 TREE *FindTreeNode(ElemType e,TREE *t)
 59 {
 60     if(t == NULL) return NULL;
 61     if(t->data == e)
 62         return t;
 63     else if(t->data < e)
 64         return FindTreeNode(e,t->right);
 65     else 
 66         return FindTreeNode(e,t->left);
 67 }
 68 
 69 TREE *FindMax(TREE *t)
 70 {
 71     if(t == NULL)
 72         return NULL;
 73     if(t->right == NULL)
 74         return t;
 75     return FindMax(t->right);
 76 }
 77 
 78 TREE *FindMin(TREE *t)
 79 {
 80     if(t == NULL)return NULL;
 81     if(t->left == NULL)
 82         return t;
 83     return FindMin(t->left);
 84 }
 85 
 86 TREE *DeleteTreeNode(ElemType e,TREE *t)
 87 {
 88     TREE *p = NULL;
 89     if(t == NULL)return NULL;
 90     if(t->data > e)//数据比根小
 91         t->left = DeleteTreeNode(e,t->left);//去左子树删
 92     else if(t->data < e)
 93         t->right = DeleteTreeNode(e,t->right);//去右子树删
 94     //这个节点就是要删的
 95     else if(t->left && t->right)//有两个子节点的节点
 96     {
 97         //找出右子树里最小的
 98         p = FindMin(t->right);
 99         t->data = p->data;
100         t->right = DeleteTreeNode(t->data,t->right);
101     }else//要删除的节点有一个子节点或就是叶子节点
102     {
103         p = t;
104         if(t->left == NULL)//右数有
105             t = t->right;
106         else if(t->right == NULL)
107             t = t->left;
108         free(p);
109         return t;
110     }
111     return t;
112 
113 }
114 
115 void DeleteTree(TREE **t)
116 {
117     if(*t == NULL)
118         return;
119     DeleteTree(&((*t)->left));
120     DeleteTree(&((*t)->right));
121     free(*t);
122     *t = NULL;
123 }

 

View Code
 1 //非递归查找操作
 2  TREE *FindTreeNode(ElemType e,TREE *t)
 3  {
 4      while( t!=NULL )
 5      {
 6         if(t->data == e)
 7             return t;
 8         else if(t->data <e)
 9             t=t->right;
10         else
11             t=t->left;
12      }
13      return t;
14  }

 

 

 

 

 

 

 

posted @ 2012-08-14 20:33  王耀it  阅读(245)  评论(0编辑  收藏  举报