c/c++ 二叉排序树

概念:

左树的所有节点的值(包括子节点)必须小于中心节点,右树所有节点的值(包括子节点)必须大于中心节点。

不允许有值相同的节点。

二叉排序树的特点:

  • 中序遍历后,就是从小到大排序了。
  • 根节点的最左边的值,就是树中最小的值。
  • 根节点的最右边的值,就是树中最大的值。

创建二叉排序树的思路:

  • 用递归的方式
  • 和根节点比较大小
  • 比根节点小的话,用递归去和根节点的左节点比较,至到找到合适的位置
  • 比根节点大的话,用递归去和根节点的右节点比较,至到找到合适的位置

二叉排序树的一些实用函数

init_bst 初始化二叉排序树
insert_bst_tree 插入树的节点
min 求树中最小节点
max 求树中最大节点
sort 排序二叉树(中序遍历就是从小到大排序了)
remove_bst 删除节点

删除节点

pattern1:要被删除的节点是root节点

  • 方案1:用根节点左树中的最大的节点作为新的根节点

删除45

  • 方案2:用根节点又树中的最小的节点作为新的根节点

删除45

pattern2:要被删除的节点是其父节点的左树,并且要被删除的节点有右树

删除12

pattern3:要被删除的节点是其父节点的左树,并且要被删除的节点无右树

删除12

pattern4:要被删除的节点是其父节点的右树,并且要被删除的节点无左树

删除53

pattern5:要被删除的节点是其父节点的右树,并且要被删除的节点有左树

删除100

bst.h

#ifndef __BST__
#define __BST__ #include <stdio.h>
#include <malloc.h>
#include <assert.h> #define T int
#define FALSE 0
#define TRUE 1
#define BOOL int typedef struct BSTNode{
T data;
struct BSTNode* left;
struct BSTNode* right;
}BSTNode; typedef struct BST{
BSTNode* root;
}BST; //初始化二叉排序树
void init_bst(BST* bst);
//插入树的节点
BOOL insert_bst_node(BSTNode** t, T x);
BOOL insert_bst_tree(BST* bst, T x);
//求树中最小节点
T min(BST* bst);
//求树中最大节点
T max(BST* bst);
//排序
void sort(BST* bst);
//查找父节点
BSTNode* get_parent(BST* bst, BSTNode* tar);
//删除节点
BOOL remove_bst(BST* bst, T key);
//搜索节点
BSTNode* search_bst(BST* bst, T key);
//搜索节点
BSTNode* search_bst1(BST* bst, T key);
//清空树
void clear_bst(BST* bst); #endif

bst.c

#include "bst.h"

//初始化二叉排序树
void init_bst(BST* bst){
bst->root = NULL;
} //插入树的节点
BOOL insert_bst_node(BSTNode** t, T x){
if(*t == NULL){
*t = (BSTNode*)malloc(sizeof(BSTNode));
assert(NULL != *t);
(*t)->data = x;
(*t)->left = NULL;
(*t)->right = NULL;
return TRUE;
}
else if(x < (*t)->data){
insert_bst_node(&((*t)->left), x);
}
else if(x > (*t)->data){
insert_bst_node(&((*t)->right), x);
}
return FALSE;
}
BOOL insert_bst_tree(BST* bst, T x){
return insert_bst_node(&(bst->root), x);
} //求树中最小节点
T min_node(BSTNode* t){
while(t->left != NULL)
t = t->left;
return t->data;
}
T min(BST* bst){
assert(bst->root != NULL);
return min_node(bst->root);
}
//求树中最大节点
T max_node(BSTNode* t){
while(t->right != NULL){
t = t->right;
}
return t->data;
}
T max(BST* bst){
assert(bst->root != NULL);
return max_node(bst->root);
}
//二叉树中序排序
void sort_node(BSTNode* t){
if(NULL == t){
return;
}else{
sort_node(t->left);
printf("%d ", t->data);
sort_node(t->right);
}
}
void sort(BST* bst){
assert(NULL != bst->root);
sort_node(bst->root);
}
//搜索节点
BSTNode* search_node(BSTNode* t, T key){
if(NULL == t || t->data == key){
return t;
}
else{
BSTNode* p;
p = search_node(t->left, key);
if(NULL == p){
p = search_node(t->right, key);
}
return p;
}
}
BSTNode* search_bst(BST* bst, T key){
return search_node(bst->root, key);
}
BSTNode* search_node1(BSTNode* t, T key){
if(NULL == t || t->data == key){
return t;
}
else{
if(key < t->data){
search_node1(t->left, key);
}
else{
search_node1(t->right, key);
}
}
}
BSTNode* search_bst1(BST* bst, T key){
return search_node1(bst->root, key);
}
//清空树
void clear_node(BSTNode** t){
if(NULL != *t){
clear_node(&((*t)->left));
clear_node(&((*t)->right));
free(*t);
*t = NULL;
}
}
void clear_bst(BST* bst){
clear_node(&bst->root);
} //查找父节点
BSTNode* get_parent_node(BSTNode* t, BSTNode* tar){
if(NULL == t || NULL == tar)return NULL;
if(t->left == tar || t->right == tar){
return t;
}
else{
BSTNode* p = NULL;
p = get_parent_node(t->left, tar);
if(NULL == p){
p = get_parent_node(t->right, tar);
}
return p;
}
}
BSTNode* get_parent(BST* bst, BSTNode* tar){
return get_parent_node(bst->root, tar);
}
BOOL remove_bst(BST* bst, T key){ BSTNode* tar = search_bst(bst, key);
//树为空或者要删除的节点不存在,返回失败
if(bst->root == NULL || NULL == tar) return FALSE; BSTNode* parent = get_parent(bst, tar);
//因为要被删除的顶点有左子节点,所以要找到以左子节点为根的右子节点中值最大的
BSTNode* X = NULL;
if(NULL != tar->left){
X = tar->left;
while(X->right != NULL){
X = X->right;
} //因为要被删除的顶点的左子节点,有右子节点,所以要找到最大的
if(X != tar->left){
//找到最大节点的父节点
BSTNode* X1 = get_parent(bst, X);
//最大节点的父节点的右边指向最大节点的左边
X1->right = X->left; //最大节点的左边代替被删除节点的左边,右边代替右边
X->left = tar->left;
X->right = tar->right;
}
//因为要被删除的顶点的左子节点,没有右子节点,所以它就是最大的
else{
X->right = tar->right;
}
}
//因为要被删除的顶点没有左子节点,所以要找到以右子节点为根的左子节点中值最小的
else{
X = tar->right;
//要被删除的节点既没有左节点,也没有右节点
if(NULL == X){
//找到父节点
BSTNode* X2 = get_parent(bst, X);
//要被删除的节点不是根节点
if(parent != NULL){
//要被删除的顶点在父节点的左边
if(tar->data < parent->data){
parent->left = X;
}
//要被删除的顶点在父节点的右边
else{
parent->right = X;
}
}
else{
bst->root = NULL;
}
free(tar);
return TRUE;
}
while(X->left != NULL){
X = X->left;
}
//因为要被删除的顶点的右子节点,有左子节点,所以要找到最小的
if(X != tar->right){
//找到最小节点的父节点
BSTNode* X1 = get_parent(bst, X);
//最小节点的父节点的左边指向最小节点的右边
X1->left = X->right; //最小节点的左边代替被删除节点的左边,右边代替右边
X->right = tar->right;
X->left = tar->left;
}
}
//要被删除的节点不是根节点
if(parent != NULL){
//要被删除的顶点在父节点的左边
if(tar->data < parent->data){
parent->left = X;
}
//要被删除的顶点在父节点的右边
else{
parent->right = X;
}
}
else{
bst->root = X;
}
free(tar);
}

bstmain.c

#include "bst.h"

int main(){
BST bst;
init_bst(&bst); //patten1 目标节点是root,root没有右子节点,左子节点中有右子节点
//T ar[] = {45,12,3,37,24,38};
//patten2 目标节点是root,root没有右子节点,左子节点中没有右子节点
//T ar[] = {45,12,3};
//patten3 目标节点是root,只有root节点
//T ar[] = {45};
//patten4 目标节点是root,root有右子节点,右子节点中没有左子节点
//T ar[] = {45,12,53,3,37,100,24};
//patten5 目标节点是root,root有右子节点,右子节点中有左子节点
//T ar[] = {45,12,53,3,37,100,24,61,90,78}; //patten6 目标节点(8)不是root,目标节点有左子节点,左子节点没有右边
//T ar[] = {45,12,53,3,27,2,4,24,1,6,5,8,7};
//patten7 目标节点(12)不是root,目标节点有左子节点,左子节点有右边
//T ar[] = {45,12,53,3,27,2,4,24,1,6,5,8,7};
//patten8 目标节点(120)不是root,目标节点没有左子节点,右子节点没有左边
T ar[] = {45,12,53,3,37,52,100,2,4,24,51,61,120,1,6,90,130,5,8,78,126,140,7,124,127,125}; //T ar[] = {45,12,53,3,37,100,24,61,90,78};
//T ar[] = {45,3,4,12,53};
int n = sizeof(ar) / sizeof(T);
for(int i = 0; i < n; ++i){
insert_bst_tree(&bst, ar[i]);
} sort(&bst);
printf("\n"); //删除节点
remove_bst(&bst, 45);
sort(&bst);
printf("\n"); clear_bst(&bst);
}

完整代码

编译方法:gcc -g bst.c bstmain.c

c/c++ 二叉排序树的更多相关文章

  1. 【数据结构】简单谈一谈二分法和二叉排序树BST查找的比较

    二分法查找: 『在有序数组的基础上通过折半方法不断缩小查找范围,直至命中或者查询失败.』   二分法的存储要求:要求顺序存储,以便于根据下标随机访问   二分法的时间效率:O(Log(n))   二分 ...

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

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

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

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

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

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

  5. PAT A 1115. Counting Nodes in a BST (30)【二叉排序树】

    题目:二叉排序树,统计最后两层节点个数 思路:数组格式存储,insert建树,dfs遍历 #include<cstdio> #include<iostream> #includ ...

  6. 二叉排序树(Binary Sort Tree)

    参考文章:http://blog.csdn.net/ns_code/article/details/19823463 不过博主的使用第一种方法操作后的树已经不是二叉排序树了,值得深思!! #inclu ...

  7. HDU 3999 二叉排序树

    The order of a Tree Problem Description The shape of a binary search tree is greatly related to the ...

  8. 二叉排序树(BST)的建立

    给一个非递归的吧. /* 已知,二叉树存储结构定义见bstree.h,请编写一个算法函数bstree creatBstree(int a[],int n), 以数组a中的数据作为输入建立一棵二叉排序树 ...

  9. POJ 2418 各种二叉排序树

    题意很明确,统计各个字符串所占总串数的百分比,暴力的话肯定超时,看了书上的题解后发现这题主要是用二叉排序树来做,下面附上n种树的代码. 简单的二叉排序树,不作任何优化(C语言版的): #include ...

  10. c语言编程之二叉排序树

    二叉排序树,又称为二叉查找树.它是一颗空树,或者是具有下面的性质的二叉树: 1.若它的左子树不空,则左子树上所有节点的值均小于它的根结构的值: 2.若它的右子树不空,则右子树上所有节点的值均大于它的根 ...

随机推荐

  1. 【原创】uC/OS 中LES BX,DWORD PTR DS:_OSTCBCur的作用及原理

    LES BX, DWORD PTR DS:_OSTCBCur ;OSTCBCur->OSTCBStkPtr = SS:SP!!! ], SS ;将当前SS(栈的基地址)寄存器值存放至当前任务控制 ...

  2. 五分钟轻松了解Hbase面向列的存储

    说明:从严格的列式存储的定义来看,Hbase并不属于列式存储,有人称它为面向列的存储,请各位看官注意这一点. 行式存储 传统的数据库是关系型的,且是按行来存储的.如下图: 其中只有张三把一行数据填满了 ...

  3. git在工作中的用法总结-使用篇

    上一篇介绍了git的环境安装配置,本篇对git在工作中常用的用法进行总结,已满足大部分的日常工作需求,对于其他的一些git命令用法在今后使用到时我也会更新上来,文中如有错误,欢迎大家指出来,谢谢~ 一 ...

  4. vue的路由映射问题

    遇到的问题 今天在项目中遇到了一个问题,明明在Router文件夹下的路由js映射文件中,配置好了,如下: // 生日贺卡 { path: 'birthdayRemind', component: lo ...

  5. python变量和变量赋值的几种形式

    动态类型的语言 python是动态类型的语言,不需要声明变量的类型. 实际上,python中的变量仅仅只是用来保存一个数据对象的地址.无论是什么数据对象,在内存中创建好数据对象之后,都只是把它的地址保 ...

  6. OpenCV入门之获取验证码的单个字符(二)

      在文章 OpenCV入门之获取验证码的单个字符(字符切割)中,介绍了一类验证码的处理方法,该验证码如下: 该验证码的特点是字母之间的间隔较大,很容易就能提取出其中的单个字符.接下来,笔者将会介绍如 ...

  7. Docker虚拟机实战

    安装Docker虚拟机 ◆ 先更新yum软件管理器,然后再安装Docker    #更新yum软件管理器    yum -y update    #安装Docker    yum install -y ...

  8. SQL去除数据库表中tab、空格、回车符等特殊字符的解决方法

    按照ASCII码, SELECT char(64) 例如64 对应 @,则 ), 'kk'); 则结果为 abckkqq.com 依此类推, 去掉其他特殊符号,参考ASCII码对照表, 去掉tab符号 ...

  9. 如何去掉C#字符串中的所有空格

    字符串行数Trim()可以去掉字符串前后的空格,如:  C# Code  string myString = " this is a test "; Console.WriteLi ...

  10. 【Java每日一题】20170313

    20170310问题解析请点击今日问题下方的“[Java每日一题]20170313”查看(问题解析在公众号首发,公众号ID:weknow619) package Mar2017; import jav ...