1、二叉搜索树基本概念

二叉搜索树又称二叉排序树,它或者是一棵空树,或者是一棵具有如下特性的非空二叉树:

(1)若它的左子树非空,则左子树上所有结点的关键字均小于根结点的关键字;

(2)若它的右子树非空,则右子树上所有结点的关键字均大于(允许的话,也可大于等于)根结点的关键字;

(3)左右子树本身又各是一个二叉搜索树。

根据二叉搜索树的特点知:对二叉搜索树进行中序遍历得到的结点序列必然是一个有序序列。

#include<stdio.h>
#include<stdlib.h>
#define QueueMaxSize 20 //定义队列数组长度
#define StackMaxSize 10 //定义栈数组长度
typedef int ElemType;
struct BTreeNode
{
ElemType data;
struct BTreeNode* left;
struct BTreeNode* right;
}; //1、查找等于给定值x的元素,成功返回该结点值域的地址,否则返回NULL
//a、递归方式:(消耗大量时间和空间)
ElemType* Find(struct BTreeNode* BST, ElemType x)
{
if (BST == NULL)
return NULL;
else
{
if (x == BST->data) //若结点值等于x则返回结点值域的地址
return &(BST->data);
else if (x < BST->data)
return Find(BST->left, x); //向左子树继续查找并直接返回
else
return Find(BST->right, x);//向右子树继续查找并直接返回
}
}
//b、非递归方式
ElemType* Find1(struct BTreeNode* BST, ElemType x)
{
while (BST != NULL)
{
if (x == BST->data) //若结点值等于x则返回结点值域的地址
return &(BST->data);
else if (x < BST->data)
BST = BST->left;
else
BST = BST->right;
}
return NULL;
} //2、更新:与查找算法相同,只需在返回之前先将找到的值替换再返回就行了,在此省略。
//3、向二叉搜索树中插入元素x
//a、递归方式:
void Insert(struct BTreeNode** BST, ElemType x)
{
if (*BST == NULL) //在为空指针的位置链接新结点
{
struct BTreeNode* p = malloc(sizeof(struct BTreeNode));
p->data = x;
p->left = p->right = NULL;
*BST = p;
}
else if (x < (*BST)->data) //向左子树中完成插入运算
Insert(&((*BST)->left), x);
else
Insert(&((*BST)->right), x); //向右子树中完成插入运算
}
//b、非递归方式
void Insert1(struct BTreeNode** BST, ElemType x)
{
struct BTreeNode* p;
struct BTreeNode* t = *BST, *parent = NULL;
while (t != NULL) //为插入新元素寻找插入位置
{
parent = t;
if (x < t->data)
t = t->left;
else
t = t->right;
}//循环之后parent存储的是待插入位置的双亲结点
p = malloc(sizeof(struct BTreeNode));
p->data = x;
p->left = p->right = NULL;
if (parent == NULL) //若树为空,作为根结点插入
*BST = p;
else if (x < parent->data) //链接到左指针域
parent->left = p;
else
parent->right = p; //链接到右指针域
} //4、删除
//a:删除叶子结点,只要将其双亲结点链接到它的指针置空即可。
//b:删除单支结点,只要将其后继指针链接到它所在的链接位置即可
//c:删除双支结点,一般采用的方法是首先把它的中序前驱结点的值赋给该结点的值域,
//然后再删除它的中序前驱结点,若它的中序前驱结点还是双支结点,继续对其做同样的操作,
//若是叶子结点或单支结点则做对应的操作,若是根结点则结束。
int Delete(struct BTreeNode** BST, ElemType x)
{
struct BTreeNode* temp;
temp = *BST;
if (*BST == NULL)
return ;
if (x < (*BST)->data) //带删除元素小于树根结点值,继续在左子树中删除
return Delete(&((*BST)->left), x);
if (x > (*BST)->data) //带删除元素大于树根结点值,继续在右子树中删除
return Delete(&((*BST)->right), x);
if ((*BST)->left == NULL)//待删除元素等于树根结点值且左子树为空,将右子树作为整个树并返回1
{
*BST = (*BST)->right;
free(temp);
return ;
}
else if ((*BST)->right == NULL)//待删除元素等于树根结点值且右子树为空,将左子树作为整个树并返回1
{
*BST = (*BST)->left;
free(temp);
return ;
}
else//待删除元素等于树根结点值且左右子树均不为空时处理情况
{
if ((*BST)->left->right == NULL)//中序前驱结点就是左孩子结点时,把左孩子结点赋值给树根结点
//然后从左子树中删除跟结点
{
(*BST)->data = (*BST)->left->data;
return Delete(&((*BST)->left), (*BST)->data);
}
else//查找出中序前驱结点,把该结点值赋给树根结点,然后从中序前驱结点为根结点的树上删除根结点
{
struct BTreeNode *p1 = *BST, *p2 = p1->left;
while (p2->right != NULL)
{
p1 = p2;
p2 = p2->right;
}
(*BST)->data = p2->data;
return Delete(&(p1->right), p2->data);
}
}
} //5、创建二叉搜索树,根据二叉搜索树的插入算法可以很容易实现
void CreateBSTree(struct BTreeNode** BST, ElemType a[], int n)
{
int i;
*BST = NULL;
for (i = ; i < n; i++)
Insert1(BST, a[i]);
} //6、二叉搜索树中可以直接用到二叉树中部分的操作,这里可以用到二叉树的输出、中序遍历和清除函数
//这里只在需要的地方将其元素类型换为int,函数名后加上_int后缀,用来区分
//输出二叉树,可在前序遍历的基础上修改。采用广义表格式,元素类型为int
void PrintBTree_int(struct BTreeNode* BT)
{
if (BT != NULL)
{
printf("%d", BT->data); //输出根结点的值
if (BT->left != NULL || BT->right != NULL)
{
printf("(");
PrintBTree_int(BT->left); //输出左子树
if (BT->right != NULL)
printf(",");
PrintBTree_int(BT->right); //输出右子树
printf(")");
}
}
}
void Inorder_int(struct BTreeNode* BT)//中序遍历,元素类型为int
{
if (BT != NULL)
{
Inorder_int(BT->left);
printf("%d,", BT->data);
Inorder_int(BT->right);
}
}
void ClearBTree(struct BTreeNode** BT)//清除二叉树,使之变为一棵空树
{
if (*BT != NULL)
{
ClearBTree(&((*BT)->left));//删除左子树
ClearBTree(&((*BT)->right));//删除右子树
free(*BT); //释放根结点
*BT = NULL; //置根指针为空
}
} //主函数
void main()//其中用到二叉树操作的函数都基本没变,只是元素类型换为int
{
int x, *px;
ElemType a[] = {,,,,,,,,,};
struct BTreeNode* bst = NULL;
CreateBSTree(&bst, a, ); //利用数组a建立一棵树根指针为bst的二叉搜索树
printf("建立的二叉搜索树的广义表形式为:\n");
PrintBTree_int(bst);
printf("\n"); printf("中序遍历:\n");
Inorder_int(bst);
printf("\n"); printf("输入待查找元素值:");
scanf(" %d", &x);//格式串中的空格可以跳过任何空白符
if (px = Find(bst, x))
printf("查找成功!得到的x为:%d\n", *px);
else
printf("查找失败!\n"); printf("输入待插入元素值:");
scanf(" %d", &x);
Insert(&bst, x); printf("输入待插入元素值:");
scanf(" %d", &x);
Insert(&bst, x); printf("输入待插入元素值:");
scanf(" %d", &x);
Insert(&bst, x); printf("进行相应操作后的中序遍历为:\n");
Inorder_int(bst);
printf("\n"); printf("输入待删除元素值:");
scanf(" %d", &x);
if (Delete(&bst, x))
printf("1\n");
else
printf("0\n"); printf("进行相应操作后的中序遍历为:\n");
Inorder_int(bst);
printf("\n"); printf("操作后的二叉搜索树的广义表形式为:\n");
PrintBTree_int(bst);
printf("\n"); ClearBTree(&bst);
}

运行结果:

分析:此程序的初始二叉搜索树如下:

然后依次插入:35,45,41 三个元素,插入后的二叉搜索树如下:

最后删除元素为50的结点,删除结点后的二叉搜索树如下:

删除结点前的中序遍历为:20,23,25,30,35,40,41,45,50,54,70,80,92

删除过程:

需要删除的结点是:元素为50的结点,此结点为双支结点,我们知道其中序前驱结点(中序序列中处于它前面的一个结点)为45,所以将45替换到50的位置,

而45结点有一个左孩子,45结点为单支结点,则直接将其后续结点(此处为左孩子41)替换原45结点的位置。删除完成。

二叉搜索树 C语言实现的更多相关文章

  1. 小白专场-是否同一颗二叉搜索树-python语言实现

    目录 一.二叉搜索树的相同判断 二.问题引入 三.举例分析 四.方法探讨 4.1 中序遍历 4.2 层序遍历 4.3 先序遍历 4.4 后序遍历 五.总结 六.代码实现 一.二叉搜索树的相同判断 二叉 ...

  2. 小白专场-是否同一颗二叉搜索树-c语言实现

    目录 一.题意理解 二.求解思路 三.搜索树表示 程序框架搭建 3.1 如何建搜索树 3.2 如何判别 3.3 清空树 更新.更全的<数据结构与算法>的更新网站,更有python.go.人 ...

  3. 二叉搜索树(Binary Search Tree)--C语言描述(转)

    图解二叉搜索树概念 二叉树呢,其实就是链表的一个二维形式,而二叉搜索树,就是一种特殊的二叉树,这种二叉树有个特点:对任意节点而言,左孩子(当然了,存在的话)的值总是小于本身,而右孩子(存在的话)的值总 ...

  4. Go语言实现:【剑指offer】二叉搜索树的第k个的结点

    该题目来源于牛客网<剑指offer>专题. 给定一棵二叉搜索树,请找出其中的第k小的结点.例如,(5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4. Go语言实现: ...

  5. Go语言实现:【剑指offer】二叉搜索树与双向链表

    该题目来源于牛客网<剑指offer>专题. 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. Go语言实现: type T ...

  6. Go语言实现:【剑指offer】二叉搜索树的后序遍历序列

    该题目来源于牛客网<剑指offer>专题. 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个数字都互不相同. Go ...

  7. 二叉搜索树BST(C语言实现可用)

    1:概述 搜索树是一种可以进行插入,搜索,删除等操作的数据结构,可以用作字典或优先级队列.二叉搜索树是最简单的搜索树.其左子树的键值<=根节点的键值,右子树的键值>=根节点的键值. 如果共 ...

  8. 《数据结构与算法分析——C语言描述》ADT实现(NO.03) : 二叉搜索树/二叉查找树(Binary Search Tree)

    二叉搜索树(Binary Search Tree),又名二叉查找树.二叉排序树,是一种简单的二叉树.它的特点是每一个结点的左(右)子树各结点的元素一定小于(大于)该结点的元素.将该树用于查找时,由于二 ...

  9. 98. 验证二叉搜索树 前序遍历解法以及后续遍历解法(go语言)

    leetcode题目 98. 验证二叉搜索树 前序遍历 最简洁的答案版本,由于先判断的是根节点,所以直接判断当前root的值v,是否满足大于左子树最大,小于右子树最小,然后再遍历左子树,右子树是否是这 ...

随机推荐

  1. strdup实现

    char * strdup(char *str) { char * strNew; assert(str != NULL); strNew = (); strcpy(strNew,str); retu ...

  2. 【BZOJ】【2595】【WC2008】游览计划

    Orz zky神犇http://blog.csdn.net/iamzky/article/details/42029921 spfa的灵活应用!(好像是求了一个叫做斯坦纳树的东西……) o(︶︿︶)o ...

  3. Spark向HDFS中存储数据

    程序如下: import org.apache.spark.sql.Row; import org.apache.spark.SparkConf; import org.apache.spark.ap ...

  4. 记录cocos2d-html5与cocosd-x jsb中遇到的坑

    这两天开始用coco2d-html5写游戏, 但最终是发布到手机上, 写的js代码是跑在jsb上的. 在此记录下遇到的坑. 注:cocos2d-x 简称 cx,  cocos2d-html5 简称ch ...

  5. [leetcode]Flatten Binary Tree to Linked List @ Python

    原题地址:http://oj.leetcode.com/problems/flatten-binary-tree-to-linked-list/ 题意: Given a binary tree, fl ...

  6. Android之SlideMenu实例Demo

    年末加班基本上一周都没什么时候回家写代码,回到家就想睡觉,周末难得有时间写个博客,上次写了一篇关于SlideMenu开源项目的导入问题,这次主要讲讲使用的问题,SlideMenu应用的广泛程度就不用说 ...

  7. java 解析 XML实例

    package com.hseact.fecp.servlet; import java.io.IOException; import javax.xml.parsers.DocumentBuilde ...

  8. scala 学习笔记十二 继承

    1.介绍 继承是面向对象的概念,用于代码的可重用性.可以通过使用extends关键字来实现继承. 为了实现继承,一个类必须扩展到其他类,被扩展类称为超类或父类.扩展的类称为派生类或子类. Scala支 ...

  9. scala 学习笔记三 闭包

    闭包是一个函数,返回值依赖于声明在函数外部的一个或多个变量. 闭包通常来讲可以简单的认为是可以访问一个函数里面局部变量的另外一个函数. 如下面这段匿名的函数: val multiplier = (i: ...

  10. SqlServer2008第一次安装后连接问题

    在第一次安装好SqlServer并启动服务后,对服务器进行连接: 1:根据计算机名进行windows身份验证 结果如下 2:根据计算机名进行SqlServer身份验证 结果如下: 3:根据IP进行wi ...