zoukankan      html  css  js  c++  java
  • 二叉排序树思想及C语言实现

    转自: 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(== 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((!= NULL) && (p->key != value))
        {
            pre = p;
            if(p->key < value)
            {
                p = p->right;
            }
            else
                p = p->left;
        }
        if(== 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(" %d %s ", root->key, bst_search(root, 10) ? "yes":"no");
        return 0;
    }

  • 相关阅读:
    Coding 初级教程(一)——用GitHub的GUI客户端对Coding的项目进行管理
    自己以前写的日记,现在公开(别的文章需要用)1
    7-网页,网站,微信公众号基础入门(微信配网_申请微信公众号)
    关于Keil4 转到 Keil5以后的一些错误解决
    6-网页,网站,微信公众号基础入门(PHP学习_1)
    5-网页,网站,微信公众号基础入门(配置网站--PHP配置上数据库)
    4-网页,网站,微信公众号基础入门(配置网站--下载安装PHP)
    3-网页,网站,微信公众号基础入门(学习网页_2)
    7-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案安全篇(GPRS模块SSL连接MQTT)
    6-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案安全篇(Wi-Fi模块SSL连接MQTT)
  • 原文地址:https://www.cnblogs.com/wliangde/p/3766601.html
Copyright © 2011-2022 走看看