zoukankan      html  css  js  c++  java
  • 二叉排序树-经典排序

    定义:一颗二叉排序树(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("申请内存出错!
    ");
     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("
    ");
    156         CreateBST(&bst,source,ARRAYLEN);
    157         printf("遍历二叉排序树 :");
    158         BST_LDR(&bst);
    159         BST_Delete(&bst,37);
    160         printf("
    删除结点后的结点 :");
    161         BST_LDR(&bst);
    162         printf("
    请输入关键字");
    163         scanf("%d",&key);
    164         pos=SearchBST(&bst,key);
    165         if(pos)
    166             printf("查找成功,改结点的地址: %x 
    ",pos);
    167         else
    168             printf("查找查找失败
    ");
    169         getchar();
    170         return 0;
    171     }

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

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

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

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

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

  • 相关阅读:
    Python:virtualenv 和 venv
    NHibernate从入门到精通系列(9)——一对多关联映射
    开源框架完美组合之Spring.NET + NHibernate + ASP.NET MVC + jQuery + easyUI 中英文双语言小型企业网站Demo
    Android与IIS身份验证——基本验证
    NHibernate从入门到精通系列(8)——一对一关联映射
    NHibernate从入门到精通系列(10)——多对多关联映射
    Android与IIS身份验证——Form验证
    以C#编写的Socket服务器的Android手机聊天室Demo
    【算法系列】使用LINQ来检测和删除重复的文件
    【算法系列】一道笔试试题——回文数算法
  • 原文地址:https://www.cnblogs.com/lujun1949/p/5507524.html
Copyright © 2011-2022 走看看