数据结构与算法分析(12)特殊二叉树的应用(一)

  本节继续介绍二叉树的相关内容,包括二叉查找树和AVL树。

(1)二叉查找树:

 定义:

使二叉树成为二叉查找树的性质是,对于树中的每个结点X,它的左子树中所有的关键字值小于X的关键字的值,而它的右子树中所有关键字的值大于X的关键字值。 二叉查找树的平均深度是O(log N)。

  1 /**********二叉查找树的标准例程**********/
  2
  3 #ifndef _Tree_H
  4 typedef int ElementType;
  5 struct TreeNode;
  6 typedef struct TreeNode *Position;
  7 typedef struct TreeNode *SearchTree;
  8
  9 SearchTree MakeEmpty(SearchTree T);
 10 Position Find(ElementType X,SearchTree T);
 11 Position FindMin(SearchTree T);
 12 Position FindMax(SearchTree T);
 13 SearchTree Insert(ElementType X,SearchTree T);
 14 SearchTree Delete(ElementType X,SearchTree T);
 15 ElementType Retrieve(Position P);
 16 #endif  /* _Tree_H */
 17
 18 struct TreeNode{
 19     ElementType Element;
 20     SearchTree Left;
 21     SearchTree Right;
 22 };
 23
 24 /* MakeEmpty 这个操作主要用于初始化 */
 25 SearchTree MakeEmpty(SearchTree     T){
 26     if(T!=NULL){
 27         MakeEmpty(T->Left);
 28         MakeEmpty(T->Right);
 29         free(T);
 30     }
 31     return NULL;
 32 }//遵循树的递归定义
 33
 34 /* Find 这个操作需要返回树T中具有关键字X的节点的指针,如果这样的节点不存在则返回NULL */
 35 Position Find(ElementType X,SearchTree T){
 36     //注意测试的顺序,首先是需要对空树进行测试,否则就可能在指针上兜圈子
 37     if(T==NULL)
 38         return NULL;
 39     //其余的测试应该使得最不可能的情况安排在最后进行。
 40     if(X<T->Element)
 41         return Find(X,T->Left);
 42     else if(X>T->Element)
 43         return Find(X,T->Right);
 44     else
 45         return T;
 46 }//这里的递归调用事实都是尾递归并且可以用一次赋值和一个goto语句很容易代替
 47
 48 /*FindMin FindMax 这些例程分别返回树中的最小元和最大元的位置*/
 49 Position FindMin(SearchTree    T){
 50     if(T==NULL){
 51         return NULL;
 52     }else if(T->Left==NULL){
 53         return T;
 54     }else{
 55         return FindMin(T->Left);
 56     }
 57 }
 58 Position FindMax(SearchTree    T){
 59     if(T!=NULL){
 60         while(T->Right!=NULL){
 61             T=T->Right
 62         }
 63         return T;
 64     }
 65 }
 66
 67 typedef FatalError printf;
 68 SearchTree Insert(ElementType X,SearchTree    T){
 69     if(T==NULL){
 70         T=malloc(sizeof(struct TreeNode));
 71         if(T==NULL){
 72             FatalError("Out of Space");
 73         }else{
 74             T->Element=X;
 75             T->Left=T->Right=NULL;
 76         }
 77     }else if(X<T->Element){
 78         T->Left=Insert(X,T->Left);
 79     }else if(X>T->Element){
 80         T->Right=Insert(X,T->Right);
 81     }
 82     //Else X is in the tree alreay;we‘ll do nothing
 83     return T;
 84 }
 85 /*
 86     重复元的插入可以通过在结点记录中保留一个附加域以指示发生的频率来处理。这使整
 87     个的树增加了某些附加空间,但是却比将重复信息放到树中要好(它将使树的深度变得很
 88     大)。当然,如果关键字只是一个更大数据结构的一部分。这种方法行不通,此时我们
 89     可以将具有相同关键字的所有结构保留在一个辅助数据结构中,如表或另一颗查找树。
 90 */
 91
 92 /* Delete 删除操作通常需要考虑许多可能的情况 */
 93 SearchTree Delete(ElementType X,SearchTree    T){
 94     Position TmpCell;
 95     if(T==NULL){
 96         printf("元素没有找到!\n");
 97     }else if(X<T->Element){
 98         T->Left=Delete(T->Left);
 99     }else if(X>T->Element){
100         T->Right=Delete(T->Right);
101     }else if(T->Left&&T->Right){//两个儿子
102         TmpCell=FindMin(T->Right);
103         T->Element=TmpCell->Element;
104         T->Right=Delete(T->Element,T->Right);
105     }else{ //一个或者没有儿子
106          TmpCell=T;
107          if(T->Left=NULL){
108              T=T->Right;
109          }else if(T->Right==NULL){
110              T=T->Left;
111          }
112          free(TmpCell);
113     }
114 } 

对于二叉查找树的删除例程,上述删除操作的效率并不高,因为它沿树进行两趟搜索以查找和删除右子树中最小的结点。如果删除的次数不多通常使用的策略是惰性删除:当一个元素要被删除时,它留在树中,而是做了一个被删除的记号。这种做法特别是在有重复关键字时很流行,因为此时记录出现频率数的域可以减一。

    (2)二叉查找树的使用范例:

1)构造简单的二叉查找树:

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<time.h>
 4 typedef struct TreeNode *SearchTree;
 5 typedef struct TreeNode *Position;
 6
 7 struct TreeNode{
 8   int Element;
 9   int flag;
10   SearchTree Left;
11   SearchTree Right;
12 };
13
14 SearchTree Insert(int x,SearchTree     T){
15     if(T==NULL){
16         //创建一个新的结点
17         T=malloc(sizeof(struct TreeNode));
18         T->Element=x;
19         T->flag=1;
20         T->Left=T->Right=NULL;
21     }else if(x<T->Element){
22         T->Left=Insert(x,T->Left);
23     }else if(x>T->Element){
24         T->Right=Insert(x,T->Right);
25     }else {
26         T->flag++;
27     }
28     return T;
29 }
30 Position FindMax(SearchTree     T){
31     if(T==NULL){
32         return NULL;
33     }else if(T->Right==NULL){
34         return T;
35     }else{
36         return FindMax(T->Right);
37     }
38 }
39 Position FindMin(SearchTree     T){
40     if(T==NULL){
41         return NULL;
42     }else if(T->Left==NULL){
43         return T;
44     }else{
45         return FindMin(T->Left);
46     }
47 }
48 //对二叉树进行遍历并输出
49 void TraverseAndPrint(SearchTree    T){
50     int i=0;
51     if(T!=NULL){
52         TraverseAndPrint(T->Left);
53         for(i=1;i<=T->flag;i++){
54           printf("%2d  ",T->Element);
55         }
56         TraverseAndPrint(T->Right);
57     }
58 }
59
60 int main(){
61     SearchTree testTree=NULL;
62     printf("下面构造一个有20个结点的二叉树并输出最大最小的结点:\n");
63     int i,x;
64     srand(time(NULL));
65     for(i=0;i<20;i++){
66         x=rand()%89+10;
67         printf("x[%2d]=%-5d",i+1,x);
68         if((i+1)%5==0){
69             printf("\n");
70         }
71         testTree=Insert(x,testTree);
72     }
73     printf("The max of the tree=%d,the min of the tree=%d\n"
74     ,FindMax(testTree)==NULL?0:FindMax(testTree)->Element
75     ,FindMin(testTree)==NULL?0:FindMin(testTree)->Element);
76     printf("按顺序输出此树中保存的结点元素:\n");
77     TraverseAndPrint(testTree);printf("\n");
78 }

      2)二叉查找树的删除实例(允许有多个重复结点)

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <time.h>
  4
  5 //系统也有TreeNode。
  6
  7 struct TreeNode{
  8   int Element;
  9   int flag;
 10   struct TreeNode * Left;
 11   struct TreeNode * Right;
 12 };
 13
 14 typedef struct TreeNode *SearchTree;
 15 typedef struct TreeNode *Position;
 16
 17 SearchTree Insert(int x,SearchTree     T){
 18     if(T==NULL){
 19         //创建一个新的结点
 20         T=malloc(sizeof(struct TreeNode));
 21         T->Element=x;
 22         T->flag=1;
 23         T->Left=T->Right=NULL;
 24     }else if(x<T->Element){
 25         T->Left=Insert(x,T->Left);
 26     }else if(x>T->Element){
 27         T->Right=Insert(x,T->Right);
 28     }else {
 29         T->flag++;
 30     }
 31     return T;
 32 }
 33 Position FindMax(SearchTree     T){
 34     if(T==NULL){
 35         return NULL;
 36     }else if(T->Right==NULL){
 37         return T;
 38     }else{
 39         return FindMax(T->Right);
 40     }
 41 }
 42 Position FindMin(SearchTree     T){
 43     if(T==NULL){
 44         return NULL;
 45     }else if(T->Left==NULL){
 46         return T;
 47     }else{
 48         return FindMin(T->Left);
 49     }
 50 }
 51 Position Find(int x,SearchTree    T){
 52     if(T==NULL){
 53       return NULL;
 54     }else if(x<T->Element)
 55       return Find(x,T->Left);
 56      else if(x>T->Element)
 57       return Find(x,T->Right);
 58      else
 59       return T;
 60 }
 61 //对二叉树进行遍历并输出
 62 void TraverseAndPrint(SearchTree    T){
 63     int i=0;
 64     if(T!=NULL){
 65         TraverseAndPrint(T->Left);
 66         for(i=1;i<=T->flag;i++){
 67           printf("%2d  ",T->Element);
 68         }
 69         TraverseAndPrint(T->Right);
 70     }
 71 }
 72 SearchTree Delete(int x,SearchTree T){
 73     Position TmpCell;
 74     if(T==NULL){
 75         printf("错误\n");
 76     }else{
 77         if(x<T->Element){
 78             T->Left=Delete(x,T->Left);
 79         }else if(x>T->Element){
 80             T->Right=Delete(x,T->Right);
 81         }else{
 82             if(T->flag>1){
 83                 T->flag--;
 84                 return T;
 85             }
 86               if(T->Left&&T->Right){
 87                 TmpCell=FindMin(T->Right);
 88                 T->Element=TmpCell->Element;
 89                 T->Right=Delete(T->Element,T->Right);
 90             }else{
 91                   TmpCell=T;
 92                 if(T->Left==NULL)
 93                     T=T->Right;
 94                 else if(T->Right==NULL)
 95                     T=T->Left;
 96                 free(TmpCell);
 97             }
 98         }
 99     }
100     return T;
101 }
102 int main(){
103     SearchTree testTree=NULL;
104     printf("下面构造一个有20个结点的二叉树并输出最大最小的结点:\n");
105     int i,x;
106     srand(time(NULL));
107     for(i=0;i<20;i++){
108         x=rand()%89+10;
109         printf("x[%2d]=%-5d",i+1,x);
110         if((i+1)%5==0){
111             printf("\n");
112         }
113         testTree=Insert(x,testTree);
114     }
115     printf("The max of the tree=%d,the min of the tree=%d\n"
116     ,FindMax(testTree)==NULL?0:FindMax(testTree)->Element
117     ,FindMin(testTree)==NULL?0:FindMin(testTree)->Element);
118     printf("按顺序输出此树中保存的结点元素:\n");
119     TraverseAndPrint(testTree);
120     printf("请输入你想要删除的结点:\n");
121     scanf("%d",&x);
122     getchar();
123     if(Find(x,testTree)!=NULL){
124         printf("在此树中有此结点,按y键删除此节点\n");
125     }
126     if(getchar()==‘y‘){
127        testTree=Delete(x,testTree);
128     }
129     TraverseAndPrint(testTree);
130 }

3)二叉查找树结点的高度:

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<time.h>
  4 typedef struct TreeNode *SearchTree;
  5 typedef struct TreeNode *Position;
  6
  7 struct TreeNode{
  8   int Element;
  9   int flag;
 10   SearchTree Left;
 11   SearchTree Right;
 12 };
 13
 14 SearchTree Insert(int x,SearchTree     T){
 15     if(T==NULL){
 16         //创建一个新的结点
 17         T=malloc(sizeof(struct TreeNode));
 18         T->Element=x;
 19         T->flag=1;
 20         T->Left=T->Right=NULL;
 21     }else if(x<T->Element){
 22         T->Left=Insert(x,T->Left);
 23     }else if(x>T->Element){
 24         T->Right=Insert(x,T->Right);
 25     }else {
 26         T->flag++;
 27     }
 28     return T;
 29 }
 30 Position FindMax(SearchTree     T){
 31     if(T==NULL){
 32         return NULL;
 33     }else if(T->Right==NULL){
 34         return T;
 35     }else{
 36         return FindMax(T->Right);
 37     }
 38 }
 39 Position FindMin(SearchTree     T){
 40     if(T==NULL){
 41         return NULL;
 42     }else if(T->Left==NULL){
 43         return T;
 44     }else{
 45         return FindMin(T->Left);
 46     }
 47 }
 48 //对二叉树进行遍历并输出
 49 void TraverseAndPrint(SearchTree    T){
 50     int i=0;
 51     if(T!=NULL){
 52         TraverseAndPrint(T->Left);
 53         for(i=1;i<=T->flag;i++){
 54           printf("%6d",T->Element);
 55         }
 56         TraverseAndPrint(T->Right);
 57     }
 58 }
 59
 60 int max(int a,int b){
 61     return a>=b?a:b;
 62 }
 63 //求二叉树单个结点的高度
 64 int height(SearchTree T){
 65     if(T==NULL){
 66         return -1;
 67     }else if(T->Left==NULL&&T->Right==NULL){
 68         return 0;
 69     }
 70     else{
 71         return (max(height(T->Right),height(T->Left))+1);
 72     }
 73 }
 74 int calAver(SearchTree    T){
 75    if(T==NULL){
 76       return 0;
 77     }else if((T->Left==NULL)&&(T->Right==NULL)){
 78          return 0;
 79     }else{
 80          return height(T)+calAver(T->Left)+calAver(T->Right);
 81     }
 82 }
 83 int main(){
 84     SearchTree testTree=NULL;
 85     printf("下面构造一个有500个结点的二叉树并输出最大最小的结点:\n");
 86     int i,x;
 87     srand(time(NULL));
 88     for(i=0;i<500;i++){
 89         x=rand()%20000+10;
 90         //printf("x[%3d]=%6d",i+1,x);
 91         if((i+1)%10==0){
 92         //printf("\n");
 93         }
 94         testTree=Insert(x,testTree);
 95     }
 96     printf("The max of the tree=%d,the min of the tree=%d\n"
 97     ,FindMax(testTree)==NULL?0:FindMax(testTree)->Element
 98     ,FindMin(testTree)==NULL?0:FindMin(testTree)->Element);
 99     printf("按顺序输出此树中保存的结点元素:\n");
100     TraverseAndPrint(testTree);
101     int h=height(testTree);
102     printf("这棵500个结点的二叉查找树的高度是:%d\n",h);
103     int depth=calAver(testTree);
104     printf("这棵500个结点的二叉查找树的高度和是:%d\n",depth);
105     return 0;
106 }

时间: 2024-08-08 08:24:47

数据结构与算法分析(12)特殊二叉树的应用(一)的相关文章

数据结构与算法分析-树、二叉树、二叉查找树

作者:xiabodan 出处:http://blog.csdn.net/xiabodan 二叉树 二叉树的申明: struct node { int data; struct node *left; struct node *right; }; 新建一个节点 /* newNode() allocates a new node with the given data and NULL left and right pointers. */ struct node* newNode(int data

研磨数据结构与算法-12遍历二叉树

节点: /* * 二叉树节点 */ public class Node { //数据项 public long data; //数据项 public String sData; //左子节点 public Node leftChild; //右子节点 public Node rightChild; /** * 构造方法 * @param data */ public Node(long data,String sData) { this.data = data; this.sData = sDa

[数据结构与算法分析(Mark Allen Weiss)]二叉树的插入与删除 @ Python

二叉树的插入与删除,来自Mark Allen Weiss的<数据结构与算法分析>. # Definition for a binary tree node class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None class BinarySearchTree: # @param root, a tree node # @return a list of integers def

《数据结构与算法分析:C语言描述》复习——第四章“树”——AVL树

2014.06.15 16:22 简介: AVL树是一种高度平衡的二叉搜索树,其命名源自于联合发明算法的三位科学家的名字的首字母.此处“平衡”的定义是:任意节点的左右子树的高度相差不超过1.有了这个平衡的性质,使得AVL树的高度H总是接近log(N),因此各种增删改查的操作的复杂度能够保证在对数级别.没有bad case是AVL树与普通的二叉搜索树的最大区别.为了实现平衡性质,我们需要记录每个节点的高度(或者平衡因子)来检测不平衡的情况.为了修正高度不平衡,需要用到“旋转”的方法,分为单旋转和双

《数据结构与算法分析—C语言描述》pdf

下载地址:网盘下载 内容简介 编辑 <数据结构与算法分析:C语言描述(原书第2版)>内容简介:书中详细介绍了当前流行的论题和新的变化,讨论了算法设计技巧,并在研究算法的性能.效率以及对运行时间分析的基础上考查了一些高级数据结构,从历史的角度和近年的进展对数据结构的活跃领域进行了简要的概括.由于<数据结构与算法分析:C语言描述(原书第2版)>选材新颖,方法实用,题例丰富,取舍得当.<数据结构与算法分析:C语言描述(原书第2版)>的目的是培养学生良好的程序设计技巧和熟练的算

数据结构1:数据结构和算法分析

问题引出 假设有一道题目:有一组N个数而要确定其中第k个最大者,我们称之为选择问题,那么这个程序如何编写?最直观地,至少有两种思路: 1.将N个数读入一个数组中,再通过某种简单的算法,比如冒泡排序法,以递减顺序将数组排序,则第k个位置上的元素就是我们需要的元素 2.稍微好一些的做法,将k个元素读入数组并以递减顺序排序,接着将接下来的元素再逐个读入,当新元素被读到时,如果它小于数组中的第k个元素则忽略之,否则将其放到数组中正确的位置上,同时将数组中的一个元素挤出数组,当算法终止时,位于第k个位置上

《数据结构与算法分析:C语言描述》复习——第十章“算法设计技巧”——Alpha-Beta剪枝

2014.07.08 22:43 简介: “搜索”与“剪枝”几乎是如影随形的.此处的“搜索”指的是带有回溯算法的深度优先搜索. 在之前的“Minimax策略”中我们给出了一个三连棋的程序,运行后你就知道计算一步棋要花多少时间. 为了计算最优的一步棋,我们可能需要递归9万多次.如果毫无疑问这种阶乘式的穷举过程必须通过剪枝来加速. 本篇介绍一种用于Minimax策略的剪枝思路——α-β剪枝. 剪枝的英语是pruning,所以不要想当然说成trimming. 图示: 在上一篇讲解Minimax策略的博

《数据结构与算法分析:C语言描述》复习——第六章“排序”——冒泡排序

2014.06.17 01:04 简介: 冒泡排序是O(n^2)级别的交换排序算法,原理简单,属于必知必会的基础算法之一. 思路: 排序要进行N轮,每一轮从尾部逐个向前扫描,遇到逆序对就进行交换.确保每一轮把最小的元素交换到前面去.这个过程好比水中的气泡向上飘,所以叫冒泡排序.代码非常简单,所以语言描述反而显得麻烦了. 实现: 1 // My implementation for bubble sort. 2 #include <iostream> 3 #include <vector&

数据结构与算法分析-索引

作者:xiabodan 出处:http://blog.csdn.net/xiabodan 算法和数据结构是计算机科学的核心内容.作为程序猿,编程是我们的实战项目.然而,写出程序还不够.一个程序在应对一些大型而复杂的情况时.会耗费大量的时间.我们能够非常easy写出一个从文件里找到一个词的程序.比方逐词扫描.看是否相符.但假设我们的文件有几十TB,并且要从文件里找到上百个词,逐个扫描的办法就差点儿不可行.我们须要优化程序,以便我们的程序能够应对复杂问题. 算法研究解决这个问题的方法,而数据结构则是

数据结构和算法分析

转自[五月的仓颉] http://www.cnblogs.com/xrq730/p/5122436.html 数据结构 数据结构是计算机存储.组织数据的方式,是指数据相互之间存在一种或多种特定关系的数据元素的集合.通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率(这就是为什么我们要研究数据结构的原因),数据结构往往同高效的检索算法和索引技术相关. 常见的数据结构有数组.栈.队列.链表.树.散列等,这些数据结构将是本数据结构的分类中重点研究的对象. 算法分析 算法是为求解一个问题需要遵