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. 操作系统概念学习笔记三 cpu调度算法

    一 基本概念 1 队列中的记录通常是进程的进程控制块. 2 CPU调度决策可在如下四种环境下发生 a 当一个进程从运行状态切换到等待状态 例如,I/O请求或调用wait以等待一个子进程的终止 b 党一 ...

  2. PHP接收跨域请求header 头设置

    header("Access-Control-Allow-Origin: http://a.com"); // 允许a.com发起的跨域请求 //如果需要设置允许所有域名发起的跨域 ...

  3. HUD Text 学习

    使用版本 NGUI_HUD_Text_v1.11 .英语水平差,难免有很多不足之处,忘批评指正.本文为鬼脸苹果原创 HUD Text 的其中一个用途是,涉及到非战斗场景时,你能通过在角色头顶显示文本行 ...

  4. python常用代码积累

    一.文件操作 1.判断一个目录是否存在,若不存在则创建 if not os.path.isdir(new_path): os.makedirs(new_path) 2.新建一个文件 f=open(&q ...

  5. Java网络爬虫 - 一个简单的爬虫例子

    WikiScraper.java package master.haku.scrape; import org.jsoup.Jsoup; import org.jsoup.nodes.Document ...

  6. java实现双向循环链表

    java实现循环链表:http://www.cnblogs.com/lixiaolun/p/4643911.html 在单链表中,查询下一个元素的时间是O(1).查询上一个元素的时间却是O(n). 为 ...

  7. function.length和arguments的区别

    function.length:接收到函数体外的参数计算长度 arguments:接收到函数体内的参数计算长度 /** * 函数参数长度和伪数组(arguments)长度不一样! -> 接收到函 ...

  8. Jquery重新学习之四[核心属性与文档处理属性]

    1:核心.each(callback),size(),length(),get([index]) 1.1 .each(callback)通过它可以遍历对象.数组的属性值并进行处理 <form i ...

  9. 〖QT编程〗在Qt编程中使用/显示中文编码

    在main.cpp中添加: #include "QTextCodec" QTextCodec *codec = QTextCodec::codecForName("Sys ...

  10. 数据库如何创建视图create view

    数据库如何创建视图     创建视图的理想步骤: 一般来说,视图创建可以分为五步走: 第一步:先考虑select语句的编写.我们知道,视图其实就是一个select语句的集合,所以,我们建立视图的第一步 ...