转自: http://blog.chinaunix.net/uid-22663647-id-1771796.html

1.二叉排序树的定义
  二叉排序树(Binary Sort Tree)又称二叉查找(搜索)树(Binary Search Tree)。其定义为:二叉排序树或者是空树,或者是满足如下性质的二叉树:
①若它的左子树非空,则左子树上所有结点的值均小于根结点的值;
②若它的右子树非空,则右子树上所有结点的值均大于根结点的值;
③左、右子树本身又各是一棵二叉排序树。
  上述性质简称二叉排序树性质(BST性质),故二叉排序树实际上是满足BST性质的二叉树。

2.二叉排序树的性质
   按中序遍历二叉排序树,所得到的中序遍历序列是一个递增有序序列。

3.二叉排序树的插入
   在二叉排序树中插入新结点,要保证插入后的二叉树仍符合二叉排序树的定义。   
   插入过程:
   若二叉排序树为空,则待插入结点*S作为根结点插入到空树中;   
   当非空时,将待插结点关键字S->key和树根关键字t->key进行比较,若s->key = t->key,则无须插入,若s->key< t->key,则插入到根的左子树中,若s->key> t->key,则插入到根的右子树中。而子树中的插入过程和在树中的插入过程相同,如此进行下去,直到把结点*s作为一个新的树叶插入到二叉排序树中,或者直到发现树已有相同关键字的结点为止。

4.二叉排序树的查找
   假定二叉排序树的根结点指针为 root ,给定的关键字值为 K ,则查找算法可描述为:
  ① 置初值: q = root ;
  ② 如果 K = q -> key ,则查找成功,算法结束;
  ③ 否则,如果 K < q -> key ,而且 q 的左子树非空,则将 q 的左子树根送 q ,转步骤②;否则,查找失败,结束算法;
  ④ 否则,如果 K > q -> key ,而且 q 的右子树非空,则将 q 的右子树根送 q ,转步骤②;否则,查找失败,算法结束。

5.二叉排序树的删除
   假设被删结点是*p,其双亲是*f,不失一般性,设*p是*f的左孩子,下面分三种情况讨论:   
   ⑴ 若结点*p是叶子结点,则只需修改其双亲结点*f的指针即可。   
   ⑵ 若结点*p只有左子树PL或者只有右子树PR,则只要使PL或PR 成为其双亲结点的左子树即可。   
   ⑶ 若结点*p的左、右子树均非空,先找到*p的中序前趋(或后继)结点*s(注意*s是*p的左子树中的最右下的结点,它的右链域为空),然后有两种做法:① 令*p的左子树直接链到*p的双亲结点*f的左链上,而*p的右子树链到*p的中序前趋结点*s的右链上。② 以*p的中序前趋结点*s代替*p(即把*s的数据复制到*p中),将*s的左子树链到*s的双亲结点*q的左(或右)链上。

代码实现:
bi_search_tree.h

#ifndef __BI_SEARCH_TREE_H__
#define __BI_SEARCH_TREE_H__
/*
 *说明:定义了二叉查找树的相关数据结构和几个基本操作
 *作者:leaf
 *时间:2010-09-08 15:55:37 
 */
 
typedef int datatype;

struct bi_search_tree
{
    datatype key;
    struct bi_search_tree *left,*right;
};

typedef struct bi_search_tree bst_tree;

/*插入操作,value是待插入的值*/
bst_tree *bst_insert(bst_tree *root, datatype value);

/*查找,找到返回1,否则,返回0*/
int bst_search(bst_tree *root, datatype value);

/*删除节点值为value的节点,成功返回1,否则,返回0*/
int bst_delete(bst_tree *root, datatype value);

/*中序输出bst树*/
void bst_print(bst_tree *root);

#endif

bi_search_tree.c

#include <stdio.h>
#include <stdlib.h>
#include "bi_search_tree.h"

/*插入操作,value是待插入的值*/
bst_tree *bst_insert(bst_tree *root, datatype value)
{
    bst_tree *parent, *node, *child;
    /*树为空,创建根节点*/
    if(root == NULL)
    {
        root = (bst_tree *)malloc(sizeof(bst_tree));
        root->key = value;
        root->left = NULL;
        root->right = NULL;
        return root;
    }
    
    parent = root;    /*记录下根节点的位置*/
    node = root;
    while(node != NULL)
    {
        /*待插入数据已经存在,则返回*/
        if(node->key == value)
            return root;
        else
        {
            parent = node;
            /*若小于节点的值,则查看节点的左孩子,否则,查看右孩子*/
            if(node->key < value)
                node = node->right;
            else
                node = node->left;
        }
    }

child = (bst_tree *)malloc(sizeof(bst_tree));
    child->key = value;
    child->left = NULL;
    child->right = NULL;
    
    if(value > parent->key)
        parent->right = child; 
    else
        parent->left = child;
    return root;
}

/*查找,找到返回1,否则,返回0*/
int bst_search(bst_tree *root, datatype value)
{
    bst_tree *p;
    p = root;
    if(p == NULL)
        return 0;
    if(p->key == value)
        return 1;
    else if(p->key > value)
        return bst_search(p->left, value);
    else
        return bst_search(p->right, value);
}

/*删除节点值为value的节点*/
int bst_delete(bst_tree *root, datatype value)
{
    bst_tree *p, *pre=NULL, *mid;
    
    p = root;
    if(root == NULL)
        return 0;
        
    /*找到该节点*/
    while((p != NULL) && (p->key != value))
    {
        pre = p;
        if(p->key < value)
        {
            p = p->right;
        }
        else
            p = p->left;
    }
    if(p == NULL)
        return 0;
    /*至少有一个子节点为空*/
    if( (p->left == NULL) || (p->right == NULL) )
    {
        if( pre->left == p )
        {
            pre->left = ( (p->left == NULL) ? p->right : p->left );
        }
        else
            pre->right = ( (p->left == NULL) ? p->right : p->left );
        
        free(p);    /*释放节点*/
    }
    else
    {
        /*删除的节点有2个子女*/
        mid = p->right;
        pre = p;
        /*寻找中序的第一个节点*/
        while(mid->left != NULL)
        {    
            pre = mid;
            mid = mid->left;
        }
        /*移花接木,直接赋值,避免交换节点*/
        p->key = mid->key;
        
        /*将mid节点的子节点作为pre的子节点,并将mid所指向的节点删除*/
        if(pre->right == mid)
            pre->right = mid->right;
        else
            pre->left = mid->right;
        free(mid);
    }
    return 1;
}

/*中序输出bst树*/
void bst_print(bst_tree *root)
{
    if(root == NULL)
        return;
    bst_print(root->left);
    printf(" %d ", root->key);
    bst_print(root->right);
}

测试代码:
main.c

#include <stdio.h>
#include "bi_search_tree.h"
int main()
{
    int a[10] = {5,4,2,8,7,1,9,3,6,10};
    int i=0;
    bst_tree *root=NULL;
    for(i=0; i<10; i++)
        root = bst_insert(root, a[i]);
    bst_delete(root, 5);
    bst_print(root);
    printf("\n%d %s\n", root->key, bst_search(root, 10) ? "yes":"no");
    return 0;
}

二叉排序树思想及C语言实现的更多相关文章

  1. 基本算法思想之递推算法思想(C++语言描述)

    递推算法是非常常用的算法思想,在数学计算等场合有着广泛的应用.递推算法适合有明显公式规律的场合. 递推算法基本思想 递推算法是一种理性思维莫斯的代表,根据已有的数据和关系,逐步推到而得到结果.递推算法 ...

  2. C语言的抽象与函数指针--思想(转)

    一.何为抽象? 从小到大,我们接触到的抽象,最熟悉的莫过于数学了.为什么这样说呢? 比如说,在小学的时候,老师总是拿了几个苹果来引诱我们:同学们,这里有几个苹果啊?于是我们流着口水一个个地数,一个苹果 ...

  3. 深入理解C语言

    语言只是一种工具,任何语言之间都是相通的,一通则百通,关键是要理解语言背后的思想,理解其思想,任何语言,拿来用就行了.语言没有好坏之分,任何语言既然存在自然有它存在的价值. 在一个到处是OOP的年代, ...

  4. 20155226田皓宇关于优秀技能经验以及c语言学习感悟和对JAVA的展望

    读老师文章后关于一项优秀技能的经验有感 1.首先我自我剖析认为,我是没有哪一个方面能做到强于身边90%的人的,我只能说有些方面略强于身边的人.比如唱歌.办公软件的应用(word.excel)等.但我不 ...

  5. 苹果新的编程语言 Swift 语言进阶(一)--综述

    Swift 是苹果开发和提供的供开发IOS 和OS X应用的一门新的语言.Swift语言基于C 和Objective-C语言,除了提供C 和Objective-C语言具有的所有语法功能外,为了编程方便 ...

  6. BT雷人的程序语言

    原文:http://cocre.com/?p=1142  酷壳 这个世界从来都不会缺少另类的东西,人类自然世界如此,计算机世界也一样.编程语言方面,看过本站<6个变态的C语言Hello Worl ...

  7. 为什么C语言会有头文件

    前段时间一个刚转到C语言的同事问我,为什么C会多一个头文件,而不是像Java和Python那样所有的代码都在源文件中.我当时回答的是C是静态语言很多东西都是需要事先定义的,所以按照惯例我们是将所有的定 ...

  8. 影响Scala语言设计的因素列表

    Scala语言设计概述 Scala的设计受许多编程语言和研究思想的影响.事实上,仅很少的Scala的特点是全新的:大多数都已经被以另外的形式用在其他语言中了.Scala的革新主要来源于它是如何构造并放 ...

  9. Java学习——面对对象的思想入门

          本文是看过<head first Java>之后的一点感悟,写点东西帮忙以后回忆,Java目前在我的工作中用到还不多,而我又对面对对象的编程非常的感兴趣.曾经在MFC平台上写过 ...

随机推荐

  1. No module named 'numpy.core._multiarray_umath'

    问题:基于anaconda prompt 安装好TensorFlow框架以后,引入的时候(import tensorflow as tf)报如下图片的错误: 回答:网上好多人说是需要升级numpy,我 ...

  2. SP839 Optimal marks(最小割)

    SP839 Optimal marks(最小割) 给你一个无向图G(V,E). 每个顶点都有一个int范围内的整数的标记. 不同的顶点可能有相同的标记.对于边(u,v),我们定义Cost(u,v)= ...

  3. flink学习笔记-快速生成Flink项目

    说明:本文为<Flink大数据项目实战>学习笔记,想通过视频系统学习Flink这个最火爆的大数据计算框架的同学,推荐学习课程: Flink大数据项目实战:http://t.cn/EJtKh ...

  4. 背包DP【洛谷P2113】 看球泡妹子

    P2113 看球泡妹子 题目背景 2014年巴西世界杯开幕了,现在满城皆是世界杯,商家们利用它大赚一笔,小明和小红也借此机会增进感情. 题目描述 本届世界杯共有N支球队,M场比赛.男球迷小明喜欢看比赛 ...

  5. PAT天梯赛L1-054 福到了

    题目链接:点击打开链接 "福"字倒着贴,寓意"福到".不论到底算不算民俗,本题且请你编写程序,把各种汉字倒过来输出.这里要处理的每个汉字是由一个 N x N 的 ...

  6. crm web ui

    1:View中的field对应于model中的attribute. 2:custom controller具有更长的生存时间,能够在view中共享一些数据. 3:window是component的一个 ...

  7. C语言中的副作用、序列点、完整表达式

    C语言中有个术语叫:副作用 副作用其实是对数据对象或文件的修改.(数据对象的定义是:用于存储值的数据存储区域) 例如语句 states = 50; 从C语言的角度来讲:这个赋值表达式的副作用是将变量的 ...

  8. Python的主要应用领域及应用场景

    参考链接:https://www.cnblogs.com/kaid/p/9016673.html 正文: Python简介 Python(英国发音:/ˈpaɪθən/美国发音:/ˈpaɪθɑːn/), ...

  9. 2015苏州大学ACM-ICPC集训队选拔赛(1) 1001 1002 1010

    签到题 Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other) Total Submissio ...

  10. day19 MRO C3算法 super()

    1. MRO(Method Resolution Order):方法解析顺序,主要用于在多继承时判断调的属性的路径(来自于哪个类). 1.Python语言包含了很多优秀的特性,其中多重继承就是其中之一 ...