1、二叉排序树的定义  

二叉排序树(Binary Sort Tree)又称二叉查找(搜索)树(Binary Search Tree)。其定义为:二叉排序树或者是空树,

或者是满足例如以下性质的二叉树:

(1)若它的左子树非空。则左子树上全部结点的值均小于根结点的值;

(2)若它的右子树非空。则右子树上全部结点的值均大于根结点的值;

(3)左、右子树本身又各是一棵二叉排序树。

上述性质简称二叉排序树性质(BST性质),故二叉排序树实际上是满足BST性质的二叉树。

2.二叉排序树的性质及意义

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

意义:构造一棵二叉排序树的目的。并非为了排序。而是为了提高查找和插入删除keyword的速度。无论怎么说,

在一个有序数据集上 的查找,速度总要快于无序的数据集,二叉树这样的非线性的结构。也有利于插入和删除的实现。

3.二叉排序树的查找

假定二叉排序树的根结点指针为 root 。给定的keyword值为 K 。则查找算法可描写叙述为:

(1)置初值: q = root ;

(2)假设 K = q -> key ,则查找成功。算法结束。

(3)否则。假设 K < q -> key ,并且 q 的左子树非空。则将 q 的左子树根送 q ,转步骤(2);

否则。查找失败,结束算法;

(4)否则,假设 K > q -> key ,并且 q 的右子树非空。则将 q 的右子树根送 q ,转步骤(2);

否则。查找失败,算法结束。

4.二叉排序树的插入

在二叉排序树中插入新结点,要保证插入后的二叉树仍符合二叉排序树的定义。   

插入步骤例如以下:

(1)若二叉排序树为空,则待插入结点*S作为根结点插入到空树中;
  

(2)当非空时,将待插结点keywordS->key和树根keywordt->key进行比較,若s->key = t->key,则无须插入。

若s->key< t->key,则插入到根的左子树中,若s->key> t->key,则插入到根的右子树中。而子树中的插入过程

和在树中的插入过程同样。如此进行下去,直到把结点*s作为一个新的树叶插入到二叉排序树中,或者直到发现

树已有同样keyword的结点为止。

5.二叉排序树的删除

如果被删结点是*p,其双亲是*f。不失一般性,设*p是*f的左孩子。以下分三种情况讨论:   

(1)若结点*p是叶子结点,则仅仅需改动其双亲结点*f的指针就可以。
  

  (2)若结点*p仅仅有左子树PL或者仅仅有右子树PR,则仅仅要使PL或PR 成为其双亲结点的左子树就可以。

  

  (3)若结点*p的左、右子树均非空,先找到*p的中序前趋(或后继)结点*s(注意*s是*p的左子树中的最右下的结点,

它的右链域为空),然后有两种做法:

① 令*p的左子树直接链到*p的双亲结点*f的左链上,而*p的右子树链到*p的中序前趋结点*s的右链上。

② 以*p的中序前趋结点*s取代*p(即把*s的数据拷贝到*p中),将*s的左子树链到*s的双亲结点*q的左(或右)链上。 

6.实现代码例如以下:

bi_search_tree.h

#ifndef __BI_SEARCH_TREE_H__

#define __BI_SEARCH_TREE_H__

 

typedef int datatype;

typedef struct bi_search_tree

{

    datatype key;

    struct bi_search_tree *left,*right;

}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.cpp

#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.cpp

#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. 二叉排序树详解——PHP代码实现

    二叉排序树(Binary Sort Tree),又称二叉查找树(Binary Search Tree),亦称二叉搜索树. 一.定义 二叉排序树或者是一棵空树,或者是具有下列性质的二叉树: 若左子树不空 ...

  2. 算法与数据结构(十) 二叉排序树的查找、插入与删除(Swift版)

    在上一篇博客中,我们主要介绍了四种查找的方法,包括顺序查找.折半查找.插入查找以及Fibonacci查找.上面这几种查找方式都是基于线性表的查找方式,今天博客中我们来介绍一下基于二叉树结构的查找,也就 ...

  3. c语言数据结构学习心得——查找

    顺序查找(线性查找) 主要用于在线性表中的查找 int Search1(int a[],int n,int key){ ;i<=n;i++){ //注意从1开始 if(a[i]==key)ret ...

  4. 原生JS实现二叉搜索树(Binary Search Tree)

    1.简述 二叉搜索树树(Binary Search Tree),它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它的右子树不空,则右子 ...

  5. C中二叉排序树的非递归和递归插入操作以及中序遍历代码实现【可运行】

    C中二叉排序树的非递归和递归插入操作以及中序遍历代码实现[可运行] #include <stdio.h> #include <stdlib.h> typedef int Key ...

  6. 二叉排序树BST代码(JAVA)

        publicclassTest{     publicstaticvoid main(String[] args){         int[] r =newint[]{5,1,3,4,6,7 ...

  7. 二叉排序树(BST)创建,删除,查找操作

    binary search tree,中文翻译为二叉搜索树.二叉查找树或者二叉排序树.简称为BST 一:二叉搜索树的定义 他的定义与树的定义是类似的,也是一个递归的定义: 1.要么是一棵空树 2.如果 ...

  8. 数据结构图文解析之:树的简介及二叉排序树C++模板实现.

    0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组.单链表.双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 ...

  9. 二叉树建立,遍历和二叉排序树的判断【c++】

    // test.cpp : Defines the entry point for the console application. // #include "stdafx.h" ...

随机推荐

  1. iOS:删除storyBoard,纯代码实现UITabBarController的视图切换功能

    storyboard是一个很强大的编写代码的辅助工具,可以帮助布局多个视图之间的联系,既直观又能减少代码量:但是,作为一个程序员,在不使用storyboard的情况下,纯代码编写是必须的技能. 下面就 ...

  2. win7 64位的 svchost.exe 占用内存过大的问题

    svchost.exe 是用来启动系统服务的,所以某个 svchost.exe 占用内存过大,可能就是它启动的那个服务占用内存过大,所以只要停止并禁用那个服务就行了. 一般来说占用内存最大的服务是 S ...

  3. 触摸事件【MotionEvent】简介

    MotionEvent简介 当用户触摸屏幕时,将创建一个MontionEvent对象,MotionEvent包含了关于发生触摸的位置.时间信息,以及触摸事件的其他很多细节. Android 将所有的输 ...

  4. SQL OUTER JOIN

    When we want to select out all the record from two table, no matter it's present at second table or ...

  5. 搜集整理一些Cron表达式例子

    1.cronExpression配置说明 字段 允许值 允许的特殊字符 秒 0-59 , - * / 分 0-59 , - * / 小时 0-23 , - * / 日期 1-31 , - * ? / ...

  6. LDA基本介绍以及LDA源码分析(BLEI)

    基本介绍: topic model,主题模型介绍:http://www.cnblogs.com/lixiaolun/p/4455764.html  以及 (http://blog.csdn.net/h ...

  7. ASP.NET操作Oracle知识记录(采用ODP.NET)

    最近因为要把以前做的一个项目数据库从MSSQL2005转移到Oracle上,所以开始接触Oracle,通过本篇随笔简单记录一些ASP.NET结合Oralce的操作: 因为微软未来不再支持 System ...

  8. CentOS 6.5下二进制安装 MySQL 5.6

    CentOS 6.5 二进制安装MySQL 5.6 1:查看系统版本 [root@10-4-5-9 mysql]# cat /etc/redhat-release CentOS release 6.5 ...

  9. Nginx如何保留真实IP和获取前端IP

    原理: squid,varnish以及nginx等,在做反向代理的时候,因为要代替客户端去访问服务器,所以,当请求包经过反向代理后,在代理服务器这里这个IP数据包的IP包头做了修改,最终后端web服务 ...

  10. Jni中图片传递的3种方式(转)

    java层的图片如何传递到c/c+层处理,处理完之后如何传回java层,下面总结了一下用到的三种方法. 1.将Bitmap转为int[]数组对象,将数组作为参数传递到C/C++层,处理完之后再以int ...