二叉排序树-经典排序

Posted Cultivate

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉排序树-经典排序相关的知识,希望对你有一定的参考价值。

定义:一颗二叉排序树(BST)是一棵二叉树,其中的每个节点都包含一个Comparable的键(以及相关联的值),并且每个键都大于其左子树中的任意键而小于右子数的任意结点的键。

复杂度:一个由N个随机键构造的二叉排序树,查找的平均所需比较次数为~2lgN(约1.39lgN)。

         接下来是完整的代码,包括二叉树的创建,插入,遍历,删除

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #ifdef _DEBUG
  4 #define new DEBUG_NEW
  5 #undef THIS_FILE
  6 static char THIS_FILE[] = __FILE__;
  7 #endif
  8 #define ARRAYLEN 10
  9 int source[]={54,90,6,69,12,37,92,28,65,83};
 10     typedef struct bst
 11     {
 12         int data;
 13         struct bst *left;
 14         struct bst *right;
 15     }BSTree;
 16 void InsertBST(BSTree *t,int key)//在二叉树中插入查找关键字key;
 17 {
 18     BSTree *p,*parent,*head;
 19     if(!(p=(BSTree*)malloc(sizeof(BSTree *))))//判断分配内存空间是否成功;
 20     {
 21         printf("申请内存出错!\n");
 22         exit(0);
 23     }
 24     p->data=key;//保存节点数据
 25     p->left=p->right=NULL;//左右子树置空
 26     head=t;
 27     while(head)//查找需要添加的父节点
 28     { 
 29         parent=head;
 30         if(key<head->data)//若关键字小于节点数据
 31           head=head->left;
 32         else
 33             head=head->right;
 34     }
 35         //判断添加到左子树还是右子树
 36         if(key<parent->data)//小于父节点
 37             parent->left=p;//添加到左子树;
 38         else
 39             parent->right=p;
 40 }
 41 BSTree *SearchBST(BSTree *t,int key)
 42 {
 43     if(!t||t->data==key)//节点为空或者关键字相等
 44        return t;//返回结点指针
 45     else if (key>t->data)//关键字大于结点数据
 46         return (SearchBST(t->right,key));
 47     else
 48         return (SearchBST(t->left,key));
 49 }
 50 void CreateBST(BSTree *t,int data[],int n)//n个数据在数组中,tree为二叉树根
 51 {
 52     int i;
 53     t->data=data[0];
 54     t->left=NULL;
 55     t->right=NULL;
 56     for(i=1;i<n;i++)
 57     {
 58         InsertBST(t,data[i]);
 59     }
 60 }
 61 void BST_LDR(BSTree *t)//中序遍历
 62 {
 63     if(t)//树不为空,执行如下操作
 64     {
 65         BST_LDR(t->left);//中序遍历左子树
 66         printf("%d  ",t->data);//输出结点数据
 67         BST_LDR(t->right);//中序遍历右子树
 68     }
 69     return;
 70 }
 71 void BST_Delete(BSTree *t,int key)
 72 {
 73     BSTree *p,*parent,*l,*l1;
 74     int child=0;//0表示左子树,1表示又子树
 75     if(!t) return ;//二叉排序树为空,则退出
 76     p=t;
 77     parent=p;
 78     while(p)//二叉排序树有效
 79     {
 80         if(p->data==key)
 81         {
 82             if(!p->left && !p->right)//叶节点(左右子树都为空)
 83             {
 84                 if(p==t)//被删除的是根结点
 85                 {
 86                     free(p);
 87                 }
 88                 else if (child==0)//父节点为左子树
 89                 {
 90                     parent->left=NULL;//设置父结点左子树为空;
 91                     free(p);
 92                 }
 93                 else//父节点为右子树
 94                 {
 95                     parent->right=NULL;//设置父结点右子树为空;
 96                     free(p);
 97                 }
 98             }
 99                  if (!p->left)//左子树为空,右子数不为空
100                 {
101                     if(child==0)//是父结点的左子树
102                         parent->left=p->right;
103 
104                    else  //是父结点的右子树
105                         parent->left=p->left;
106                    free(p);
107                 }
108                else if (!p->right)//右子树为空,左子数不为空
109                 {
110                     if(child==0)//是父结点的左子树
111                         parent->right=p->right;
112 
113                    else  //是父结点的右子树
114                         parent->right=p->left;
115                    free(p);
116                 }
117                 else//左右子树都不为空
118                 {
119                     l1=p;//保存左子树的父节点
120                     l=p->right;//当前节点的右子数开始查找
121                    while(l->left)//左子树不为空
122                    {
123                        l1=l;
124                        l=l->left;//查找左子树;
125                    }
126                    p->data=l->data;//将左子树的数据保存到被删除的节点
127                    l1->left=NULL;//设置父结点的左子树指针为空
128                    free(l1);//释放左子树占的内存空间
129                 }
130                 p=NULL;
131             }
132             else if(key<p->data)//需删除记录的关键字小于节点的数据
133             {
134                 child=0;//标记在当前结点左子树查找
135                 parent=p;//保存当前结点为父节点
136                 p=p->left;
137             }
138              else //需删除记录的关键字大于节点的数据
139             {
140                 child=1;//标记在当前结点右子树查找
141                 parent=p;//保存当前结点为父节点
142                 p=p->right;
143             }
144         }
145     }
146 
147 
148     int main()
149     {
150         int i,key;
151         BSTree bst,*pos;//保存二叉树的根结点
152         printf("原始数据");
153         for(i=0;i<ARRAYLEN;i++)
154             printf("%d ",source[i]);
155         printf("\n");
156         CreateBST(&bst,source,ARRAYLEN);
157         printf("遍历二叉排序树 :");
158         BST_LDR(&bst);
159         BST_Delete(&bst,37);
160         printf("\n删除结点后的结点 :");
161         BST_LDR(&bst);
162         printf("\n请输入关键字");
163         scanf("%d",&key);
164         pos=SearchBST(&bst,key);
165         if(pos)
166             printf("查找成功,改结点的地址: %x \n",pos);
167         else
168             printf("查找查找失败\n");
169         getchar();
170         return 0;
171     }

注意点:在二叉排序树中,删除操作对应着多种不同情况(这几种情况在代码中均有体现):

  (1) 删除元素是叶节点;

  (2) 删除元素有左子树,无右子数

  (3) 删除元素有右子树,无左子数

  (4) 删除元素有左子树,右子数

 

以上是关于二叉排序树-经典排序的主要内容,如果未能解决你的问题,请参考以下文章

转白话经典算法系列之七 堆与堆排序

白话经典算法系列之七 堆与堆排序

LeetCode810. 黑板异或游戏/455. 分发饼干/剑指Offer 53 - I. 在排序数组中查找数字 I/53 - II. 0~n-1中缺失的数字/54. 二叉搜索树的第k大节点(代码片段

[平衡树] aw3786. 二叉排序树(BST)

数据结构 动态查找与二叉排序树

二叉排序树的实现(c语言)