数据结构:二叉查找树(C语言实现)

数据结构:二叉查找树(C语言实现)



?写在前面

  关于二叉树的基础知识,请看我的一篇博客:二叉树的链式存储

  说明:

    二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:
      1.若其左子树不空,则左子树上所有结点的值均小于它的根结点的值;
      2.若其右子树不空,则右子树上所有结点的值均大于它的根结点的值;
      3.其左、右子树也分别为二叉排序树

?二叉查找树的建立(插入):

说明:   

    二叉树的创建是二叉树反复插入节点所构造出来的!

     若二叉树为空树,则插入元素作为树根节点。

     若根结点的键值等于key,则插入失败;

     若key小于根结点的键值,则插入到根的左子树上;否则,插入到根的右子树上

     新插入的节点一定是一个叶子节点!

代码分析:

void InsertBST(BiStree &Tree,ElemType e)
{
    BiStree T =Tree;    //定义执行副本,!
    BiStree father =NULL; //定义
    while (T&&T->data.key!=e.key)
    {
        father=T;
        if(e.key>T->data.key)
            T=T->Rchild;
        else
            T=T->Lchild;
    }
    if(T) //跳出循环的只有两种情况,要么就是T不存在,要么就是找到了对应元素!T 存在说明,只能是对应元素也存在,那我我们就不用插入了
        return;
    BiSnode *s = (BiSnode*)malloc(sizeof(BiSnode));//能到这里,说明节点不存在,新建一个节点,并初始化!
    s->data=e;
    s->Rchild=s->Lchild=NULL;

    if(father==NULL)        //如果farther不存在,那说明就是没有执行While语句,也即是树是空的,因为一旦执行,就不会为NULL!
        Tree=s;
    else if(e.key>father->data.key) //到这里说明Farther存在,那么剩下的就是往farther左右节点插入元素了
        father->Rchild=s;
    else
        father->Lchild=s;
}

?删除运算

说明:
  删除运算是的基础是查找元素,首先要查找要删除的元素,如果找到就删除,找不到就不用删除了。

查找部分代码:

void DelBST(BiStree &Tree,char key)
{
    if(!Tree) //如果节点为空节点,说明要删除的元素不可能存在,所以返回就好!
        return;
    else //下面是节点存在的分情况判断:
    {
        if(Tree->data.key==key) //如果找到了要删除的节点!
        {
            deleteNode(Tree);   //删除该节点
        }
        else if(Tree->data.key<key)  //如果要删除的节点大于该节点,则往该节点的右子树方向进行查找
            DelBST(Tree->Rchild,key);
        else
            DelBST(Tree->Lchild,key);//如果要删除的节点小于该节点,则往该节点的左子树方向进行查找
    }
}

  到现在我们已经找到元素了 ,要对其删除,就是要实现deleteNode(Tree);方法!
  但是删除元素的运算是存在多种情况的,我们要分别处理:
    ★待删除的结点*p是个叶子结点

  

    ★待删除的结点*p是仅有一个非空子树

  

    ★待删除的结点*p有两个非空子树

  

    如何找出直接前驱:找到要删除节点的第一个左子树然后一直向右!   

  删除代码如下

void deleteNode(BiStree &p)
{
    if(!p->Rchild)  //对第一种及第二种情况的处理
    {
        BiSnode * q =p;
        p=p->Lchild;
        free(q);
    }
    else if(!p->Lchild) //对第一种及第二种情况的处理
    {
        BiSnode * q =p;
        p=p->Rchild;
        free(q);
    } else
    {
        BiSnode * q =p;
        BiSnode * s =p->Lchild;
        while (s->Rchild)
        {
            q=s;
            s=s->Rchild;
        }
        //s指向被删节点p的前驱
        p->data=s->data;
        if(q!=p) //详见下两图
            q->Rchild=s->Lchild;    //左图
         else
            q->Lchild=s->Lchild;    //右图
        free(s);
    }

}

    

?查找运算:

代码就不演示了,很简单哦!

查找键值为K的记录:
  若二叉排序树为空树,则查找失败,返回;
  若根结点的键值等于key,则查找成功,返回;
  若根结点的键值大于key,则到根的左子树上继续查找;否则,到根的右子树上继续查找

时间: 2024-10-12 09:23:17

数据结构:二叉查找树(C语言实现)的相关文章

数据结构算法C语言实现(十)--- 3.3栈与递归的实现

一.简介 汉诺塔问题是递归的一个典型例子,而且书上的讲解很详细,对理解C语言函数及函数传参的工作机制很有帮助,值得一看.而且,递归在我看来和分治.DP.贪心等一样是十分优美的思想,值得学习!!! 二.CPP文件 1 //3_3.cpp 2 /** 3 author:zhaoyu 4 email:[email protected] 5 date:2016-6-8 6 note:realize my textbook <<数据结构(C语言版)>> 7 */ 8 //Page 54 9

数据结构算法C语言实现(八)--- 3.2栈的应用举例:迷宫求解与表达式求值

一.简介 迷宫求解:类似图的DFS.具体的算法思路可以参考书上的50.51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意.大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚,所以很多需要自己揣摩.这也体现了算法和程序设计语言的特点,算法更侧重本质的描述,而任何编程语言都要照顾到实现的细节以及数据类型等语法方面的需求. 表达式求值: [编码中....] 二.头文件 迷宫求解: 1 //3_2_maze.h 2 /** 3 author:zhaoyu 4 email:[em

数据结构算法C语言实现(七)--- 3.1 的线性实现及应用举例

一.简述 栈,LIFO.是操作受限的线性表,和线性表一样有两种存储表示方法.下面以顺序存储为例,实现. 二.ADT 暂无. 三.头文件 1 //3_1.h 2 /** 3 author:zhaoyu 4 email:[email protected] 5 date:2016-6-7 6 note:realize my textbook <<数据结构(C语言版)>> 7 */ 8 //Page 46 9 10 #ifndef _3_1_H_ 11 #define _3_1_H_ 12

数据结构算法C语言实现(二十)--- 6.3.1遍历二叉树

一.简述 二叉树的遍历主要是先序.中序.后序及对应的递归和非递归算法,共3x2=6种,其中后序非递归在实现上稍复杂一些.二叉树的遍历是理解和学习递归及体会栈的工作原理的绝佳工具! 此外,非递归所用的栈及相关操作是第三章实现的,但数据类型做了更改. 二.头文件 1 //3_1.h 2 /** 3 author:zhaoyu 4 email:[email protected] 5 date:2016-6-7 6 note:realize my textbook <<数据结构(C语言版)>&g

二叉查找树C语言实现

1.      二叉查找树的定义: 左子树不为空的时候,左子树的结点值小于根节点,右子树不为空时,右子树的结点值大于根节点,左右子树分别为二叉查找树 2.      二叉查找树的最左边的结点即为最小值,要查找最小值,只需遍历左子树的结点直到为空为止,同理,最右边的结点结尾最大值,要查找最大值,只需遍历右子树的结点直到为空为止.二叉查找树的插入查找和删除都是通过递归的方式来实现的,删除一个结点的时候,先找到这个结点S,然后并不是真正的删除这个结点S,而是在其右子树找到后继结点,将后继结点的值付给S

数据结构算法C语言实现(十二)--- 3.4循环队列&amp;队列的顺序表示和实现

一.简述 空队列的处理方法:1.另设一个标志位以区别队列是空还是满:2.少用一个元素空间,约定以队列头指针在队尾指针下一位置上作为队列呈满的状态的标志. 二.头文件 1 //3_4_part1.h 2 /** 3 author:zhaoyu 4 email:[email protected] 5 date:2016-6-9 6 note:realize my textbook <<数据结构(C语言版)>> 7 */ 8 //Page 64 9 #include <cstdio

数据结构算法C语言实现(十一)--- 3.4队列的链式表示和实现

一.简介 FIFO. 二.头文件 1 //3_4_part1.h 2 /** 3 author:zhaoyu 4 email:[email protected] 5 date:2016-6-9 6 note:realize my textbook <<数据结构(C语言版)>> 7 */ 8 //Page 61 9 #include <cstdio> 10 #include "head.h" 11 #define QElemType int 12 //

数据结构算法C语言实现(一)---2.3线性表的顺序表示和实现

注意: 虽然是用C语言实现,但是考虑到使用了一个C++的特性----引用以简化代码,所以所有的代码均以cpp作为后缀,用g++编译(以后不做说明). g++版本: 一.简述 本节主要讲述线性表的顺序实现,主要操作包括建表,插入元素,删除元素,查找元素,合并表等操作,根据书中伪代码编写了C语言,使用int类型进行了测试,需要注意的是查找元素时使用了函数指针,C语言初学者不易理解,可查阅相关书籍学习. 二.头文件 1 //head.h 2 /** 3 My Code 4 */ 5 #include

数据结构成为小语言

面向语言的开发并不一定意味着,一定要自己开发解析器或编译器.这就是说,我们将在下一章学习创建解析器,然后,把这样的解析器和本章介绍的方法照结合起来,去构建一个简单的编译器.可以通过创建数据结构和函数或模块,就能够做很多事,数据结构描述了准备做什么,而函数或模块定义了如何解释结构. 几乎可以用任何语言创建数据结构来表示一个程序,但是 F# 更适合.F# 的文字列表和数组很容易定义,不要求庞大的类型注解:它的联合类型能够创建结构,来表达相关的概念,但却不一定要包含相同类型的数据,可以用它来创建树型结