【数据结构】(C语言):二叉搜索树

news2025/1/20 5:54:47

二叉搜索树:

  • 树不是线性的,是层级结构。
  • 基本单位是节点,每个节点最多2个子节点。
  • 有序。每个节点,其左子节点都比它小,其右子节点都比它大。
  • 每个子树都是一个二叉搜索树。每个节点及其所有子节点形成子树。
  • 可以是空树。

添加元素:从根节点开始,比对数值。若比它小,往左子树比对;若比它大,往右子树比对;直到找到为空,则为新元素的位置。

删除元素:

  1. 若删除的节点为叶子节点(即无子节点),则直接删除。
  2. 若删除的节点只有左子节点,则左子节点替代删除节点。
  3. 若删除的节点只有右子节点,则右子节点替代删除节点。
  4. 若删除的节点既有左子节点又有右子节点,则找到直接前驱(即删除节点的左子树中的最大值,即删除节点的左子节点的最右节点),直接前驱的值替代删除节点的值,删除直接前驱节点。

遍历元素:(可使用递归)

  • 前序遍历(顺序:根节点、左子节点、右子节点)。
  • 中序遍历(顺序:左子节点、根节点、右子节点)。
  • 后序遍历(顺序:左子节点、右子节点、根节点)。

查找元素:从根节点开始,比对数值。若比它小,往左子树查找;若比它大,往右子树查找;直到找到该元素,则返回1(true),若没有,则返回0(false)。


C语言实现:(使用链表实现)

 创建结构体数据类型(记录二叉搜索树的根节点和数据个数):

typedef struct Link
{
	LinkNode *root;			// 根节点
	int length;			    // 统计有多少数据
} LinkBST;                  // 别名

创建二叉搜索树,并初始化:

LinkBST bst;
bst.root = NULL;    // 根节点,初始化为NULL
bst.length = 0;     // 数据个数,初始化为0

创建节点(结构体数据类型),并创建具体节点实例的函数:

// 节点(结构体数据类型)
typedef struct Node
{
	int value;			    // 数据类型为整型
	struct Node *left;		// 左子节点
	struct Node *right;		// 右子节点
}LinkNode;                  // 别名
// 函数:创建节点
LinkNode *createNode(int data)
{
	LinkNode *node = (LinkNode *)malloc(sizeof(LinkNode));    // 分配节点内存空间

	if(node == NULL)
	{
		perror("Memory allocation failed");
		exit(-1);
	}
	node->value = data;    // 数据
	node->left = NULL;     // 左子节点,初始化为NULL
	node->right = NULL;    // 右子节点,初始化为NULL
	return node;
}

添加元素:

void add(LinkBST *bst, int data)	// add element
{
	// 函数:往二叉搜索树中添加元素	
	LinkNode *addNode(LinkNode *node, int data)
	{
		if(node == NULL)
		{
			LinkNode *newnode = createNode(data);
			node = newnode;
			bst->length++;    // 每添加一个元素,length+1
			return node;
		}
		if(data < node->value) node->left = addNode(node->left, data);
		else if(data > node->value) node->right = addNode(node->right, data);
		return node;
	}

	// 从根节点开始比对,root指针始终指向二叉搜索树的根节点
	bst->root = addNode(bst->root, data);	
}

删除元素:

void delete(LinkBST *bst, int data)	// delete element
{
	// 函数:删除节点	
	LinkNode *del(LinkNode *node)
	{   
        // 若只有右子节点,则右子节点替代删除节点
		if(node->left == NULL)
		{
			bst->length--;        // 每删除一个元素,length-1
			return node->right;
		}
        // 若只有左子节点,则左子节点替代删除节点
		else if(node->right == NULL)
		{
			bst->length--;        // 每删除一个元素,length-1
			return node->left;
		}
        // 左右子节点都有,则直接前驱(左子节点的最右节点)替代删除节点,并删除直接前驱
		else if(node->left && node->right)
		{
			LinkNode *tmp = node, *cur = node->left;
			while(cur->right)
			{
				tmp = cur;
				cur = cur->right;
			}
			node->value = cur->value;
			if(tmp != node) tmp->right = cur->left;
			else tmp->left = cur->left;
			bst->length--;        // 每删除一个元素,length-1
			return node;
		}
	}

	// 函数:找到将要删除的节点
	LinkNode *delNode(LinkNode *node, int data)
	{
		if(node == NULL) return node;
		if(data == node->value) node = del(node);
		else if(data < node->value) node->left = delNode(node->left, data);
		else if(data > node->value) node->right = delNode(node->right, data);
		return node;
	}	
	
	// 从根节点开始比对。root指针始终指向二叉搜索树的根节点
	bst->root = delNode(bst->root, data);	
}

遍历元素:(使用递归)

// 前序遍历(根,左,右)
void pretravel(LinkNode *node)
{
	if(node == NULL) return ;
	printf("%d  ", node->value);
	pretravel(node->left);
	pretravel(node->right);
}
// 中序遍历(左,根,右)
void midtravel(LinkNode *node)
{
	if(node == NULL) return ;
	midtravel(node->left);
	printf("%d  ", node->value);
	midtravel(node->right);
}
// 后序遍历(左,右,根)
void posttravel(LinkNode *node)
{
	if(node == NULL) return ;
	posttravel(node->left);
	posttravel(node->right);
	printf("%d  ", node->value);
}

查找元素:

找到元素,返回1(true);没找到,返回0(false)。

int find(LinkNode *node, int data)
{
	if(node ==  NULL) return 0;
	if(data == node->value) return 1;
	if(data < node->value) find(node->left, data);
	else if(data > node->value) find(node->right, data);	
}


完整代码:(bst.c)

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

/* structure */
typedef struct Node			// linkedlist node
{
	int value;			// value type is integer
	struct Node *left;		// left child node
	struct Node *right;		// right child node
}LinkNode;

typedef struct Link			// binary search tree
{
	LinkNode *root;			// root node of the tree
	int length;			// the number of the tree
} LinkBST;

/* function prototype */
void add(LinkBST *, int);		// add element to the tree
void delete(LinkBST *, int);		// delete element from the tree
void pretravel(LinkNode *);		// show element one by one,(root,left,right)
void midtravel(LinkNode *);		// show element one by one,(left,root,right)
void posttravel(LinkNode *);		// show element one by one,(left,right,root)
int find(LinkNode *, int);		// if find data,return 1(true),or return 0(false)

/* main function */
int main(void)
{
	// create binary search tree and initialization
	LinkBST bst;
	bst.root = NULL;
	bst.length = 0;
	printf("isempty(1:true, 0:false): %d, length is %d\n",  bst.root==NULL, bst.length);
	
	add(&bst, 15);
	add(&bst, 8);
	add(&bst, 23);
	add(&bst, 10);
	add(&bst, 12);
	add(&bst, 19);
	add(&bst, 6);
	printf("isempty(1:true, 0:false): %d, length is %d\n",  bst.root==NULL, bst.length);

	printf("midtravel: ");
	midtravel(bst.root);
	printf("\n");
	printf("pretravel: ");
	pretravel(bst.root);
	printf("\n");
	printf("posttravel: ");
	posttravel(bst.root);
	printf("\n");
	
	printf("find 10 (1:true, 0:false): %d\n", find(bst.root, 10));
	printf("find 9 (1:true, 0:false): %d\n", find(bst.root, 9));
	
	delete(&bst, 23);
	delete(&bst, 15);
	delete(&bst, 6);

	printf("isempty(1:true, 0:false): %d, length is %d\n",  bst.root==NULL, bst.length);
	printf("midtravel: ");
	midtravel(bst.root);
	printf("\n");
	printf("pretravel: ");
	pretravel(bst.root);
	printf("\n");
	printf("posttravel: ");
	posttravel(bst.root);
	printf("\n");
	return 0;
}

/* subfunction */
LinkNode *createNode(int data)		// create a node
{
	LinkNode *node = (LinkNode *)malloc(sizeof(LinkNode));

	if(node == NULL)
	{
		perror("Memory allocation failed");
		exit(-1);
	}
	node->value = data;
	node->left = NULL;
	node->right = NULL;
	return node;
}

void add(LinkBST *bst, int data)	// add element
{
	// subfunction(recursion): add element to the binary search tree	
	LinkNode *addNode(LinkNode *node, int data)
	{
		if(node == NULL)
		{
			LinkNode *newnode = createNode(data);
			node = newnode;
			bst->length++;
			return node;
		}
		if(data < node->value) node->left = addNode(node->left, data);
		else if(data > node->value) node->right = addNode(node->right, data);
		return node;
	}

	// root node receive the result
	bst->root = addNode(bst->root, data);	
}

void delete(LinkBST *bst, int data)	// delete element
{
	// subfunction(recursion): delete element from the binary search tree	
	LinkNode *del(LinkNode *node)
	{
		if(node->left == NULL)
		{
			bst->length--;
			return node->right;
		}
		else if(node->right == NULL)
		{
			bst->length--;
			return node->left;
		}
		else if(node->left && node->right)
		{
			LinkNode *tmp = node, *cur = node->left;
			while(cur->right)
			{
				tmp = cur;
				cur = cur->right;
			}
			node->value = cur->value;
			if(tmp != node) tmp->right = cur->left;
			else tmp->left = cur->left;
			bst->length--;
			return node;
		}
	}

	// subfunction: find delete node,return node
	LinkNode *delNode(LinkNode *node, int data)
	{
		if(node == NULL) return node;
		if(data == node->value) node = del(node);
		else if(data < node->value) node->left = delNode(node->left, data);
		else if(data > node->value) node->right = delNode(node->right, data);
		return node;
	}	
	
	// root node receive the result
	bst->root = delNode(bst->root, data);	
}

void pretravel(LinkNode *node)		// show element one by one,(root,left,right)
{
	if(node == NULL) return ;
	printf("%d  ", node->value);
	pretravel(node->left);
	pretravel(node->right);
}

void midtravel(LinkNode *node)		// show element one by one,(left,root,right)
{
	if(node == NULL) return ;
	midtravel(node->left);
	printf("%d  ", node->value);
	midtravel(node->right);
}

void posttravel(LinkNode *node)		// show element one by one,(left,right,root)
{
	if(node == NULL) return ;
	posttravel(node->left);
	posttravel(node->right);
	printf("%d  ", node->value);
}

int find(LinkNode *node, int data)	// if find data,return 1(true),or return 0(false)
{
	if(node ==  NULL) return 0;
	if(data == node->value) return 1;
	if(data < node->value) find(node->left, data);
	else if(data > node->value) find(node->right, data);	
}

编译链接: gcc -o bst bst.c

执行可执行文件: ./bst

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1880793.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

昇思25天学习打卡营第7天|网络构建

昇思25天学习打卡营第7天|网络构建 前言函数式自动微分函数与计算图微分函数与梯度计算Stop GradientAuxiliary data神经网络梯度计算 个人任务打卡&#xff08;读者请忽略&#xff09;个人理解与总结 前言 非常感谢华为昇思大模型平台和CSDN邀请体验昇思大模型&#xff01;从今…

绿色算力|暴雨发布浸没式液冷服务器

随着数字经济的飞速发展和AI创新应用的不断突破&#xff0c;算力规模持续增长&#xff0c;最新发布的《数字中国发展报告&#xff08;2023年&#xff09;》显示&#xff0c;2023年中国算力总规模达到230EFLOPS&#xff0c;居全球第二位。 服务器作为算力基础设施底座&#xff…

mac安装navicate

1.下载好之后点击安装包安装 2.一般情况下会提示安全性什么的,点击允许即可,然后会出现如下界面,点击安装即可. 3.点击打开 4.然后出现如下界面,点击Enter 5.将安装包拖入即可. 6.等待安装即可 7.安装完成后会在启动台看到Navicat16 的图标 8.然后打开软件界面如下:

Variables Reference for vscode

Predefined variables Visual Studio Code 支持在调试、任务配置文件以及一些特定的设置中使用变量替换。这些变量可以使用 ${variableName} 语法在 launch.json 和 tasks.json 文件的某些键和值字符串中使用。 Predefined variables Visual Studio Code 支持以下预定义变量…

[图解]分析模式高阶+课程讲解03物品模式

1 00:00:00,280 --> 00:00:03,440 下一个要探讨的模式是物品模式 2 00:00:04,310 --> 00:00:08,300 说是物品模式&#xff0c;实际上更多的说物品规格 3 00:00:09,210 --> 00:00:12,560 首先&#xff0c;我们要区分一下物品和物品规格的定义 4 00:00:14,440 -->…

205.Mit6.S081-实验二 system calls

Lab2:system calls 在上一个实验室中&#xff0c;您使用系统调用编写了一些实用程序。在本实验室中&#xff0c;您将向xv6添加一些新的系统调用&#xff0c;这将帮助您了解它们是如何工作的&#xff0c;并使您了解xv6内核的一些内部结构。您将在以后的实验室中添加更多系统调用…

人工智能期末复习笔记(更新中)

分类问题 分类&#xff1a;根据已知样本的某些特征&#xff0c;判断一个新的样本属于哪种已知的样本类 垃圾分类、图像分类 怎么解决分类问题 分类和回归的区别 1. 逻辑回归分类 用于解决分类问题的一种模型。根据数据特征或属性&#xff0c;计算其归属于某一类别 的概率P,…

[Cloud Networking] OSPF

OSPF 开放式最短路径优先&#xff08;Open Shortest Path First&#xff09;是一种动态路由协议&#xff0c;它属于链路状态路由协议&#xff0c;具有路由变化收敛速度快、无路由环路、支持变长子网掩码和汇总、层次区域划分等优点。 1 OSPF Area 为了适应大型网络&#xff0…

C程序设计谭浩强第五版

程序习题 第一章1、第5题2、第6题 第三章1、第2题2、第2题3、第3题4、第4题Tips 第一章 1、第5题 编写一个C程序,运行时输出以下图形: #include <stdio.h> int main() {for (int i 0; i < 4; i) // 输出4行循环控制{for (int j 0; j < i; j) //第几行就输出几…

leetcode-19-回溯-组合问题(剪枝、去重)

引自代码随想录 一、[77]组合 给定两个整数 n 和 k&#xff0c;返回 1 ... n 中所有可能的 k 个数的组合。 示例: 输入: n 4, k 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4]] 1、大致逻辑 k为树的深度&#xff0c;到叶子节点的路径即为一个结果 开始索引保证不…

一、Redis简介

一、Redis介绍与一般应用 1.1 基本了解 Redis全称Remote Dictionary Server(远程字典服务)&#xff0c; 是一个开源的高性能键值存储系统&#xff0c;通常用作数据库、缓存和消息代理。使用ANSI C语言编写遵守BSD协议&#xff0c;是一个高性能的Key-Value数据库提供了丰富的数…

VMware中的三种虚拟网络模式

虚拟机网络模式 1 主机网络环境2 VMware中的三种虚拟网络模式2.1 桥接模式2.2 NAT模式2.3 仅主机模式 3 网络模式选择及配置NAT模式3.1 VMware虚拟网络配置3.2 虚拟机选择网络模式3.3 Windows主机网络配置 4 配置静态IP 虚拟机联网方式为桥接模式&#xff0c;这种模式下&#x…

5.6 0-1背包问题

#include<iostream> #include<string> #include<stdlib.h> #include<bits/stdc.h> using namespace std;int c;//背包容纳的重量 int n;//物品数量 int cw;//当前重量 int cv;//当前价值 int bestv;//当前最优价值 int x[100]; int bestx[100]; struct…

Python 算法交易实验75 QTV200后续想法梳理

说明 在第一步获取数据源&#xff0c;然后进入Mongo(第一个数据节点)开始&#xff0c;QTV200的数据流体系就开始动了。后续用多少时间完成不太好确定&#xff0c;短则数周&#xff0c;长则数月。毕竟有过第一版实验的基础&#xff0c;应该还是可以做到的。 下面就是天马行空&…

【TB作品】玩具电子琴,ATMEGA128单片机,Proteus仿真

题目 7 &#xff1a;玩具电子琴 基于单片机设计一能够发出中音八个音阶的音乐信号的电子琴&#xff0c;能够实现弹奏和音符显示功 能。 具有 8 个音阶按键&#xff0c;每按下一个按键时&#xff0c;所对应的 LED 点亮&#xff0c;音符进行显示。 具体要求如下&#xff1a; &…

zabbix server client 安装配置

Zabbix Server 采用源码包部署&#xff0c;数据库采用 MySQL8.0 版本&#xff0c;zabbix-web 使用 nginxphp 来实现。具体信息如下&#xff1a; 软件名 版本 安装方式 Zabbix Server 6.0.3 源码安装 Zabbix Agent 6.0.3 源码安装 MySQL 8.0.28 yum安装 Nginx 1.20…

淀山湖之行随笔

我们仰望清新&#xff0c;但又不得不被世俗所伴。 近日上海开始进入梅雨季节&#xff0c;每天大大小小的雨水不断&#xff0c;整个环境也格外的潮湿&#xff0c;不过已经逐渐习惯这种气候&#xff0c;所谓的见怪不怪。 今日是周日&#xff0c;思绪好久&#xff0c;准备去淀山湖…

贪心问题(POJ1700/1017/1065)(C++)

一、贪心问题 贪心算法 贪心算法&#xff08;greedy algorithm&#xff09;&#xff0c;是用计算机来模拟一个「贪心」的人做出决策的过程。这个人十分贪婪&#xff0c;每一步行动总是按某种指标选取最优的操作。而且他目光短浅&#xff0c;总是只看眼前&#xff0c;并不考虑…

【mysql死锁】示例 和讨论 “SHOW ENGINE INNODB STATUS“

文章目录 mysql 死锁死锁演示表结构如下 死锁查询mysql 详情命令行 SHOW ENGINE INNODB STATUS 如果 两个事务都是按照先更新1 再更新2的顺序去做更新 会发生死锁么&#xff1f;验证一下所以 如果顺序是一致的 不会产生死锁 只会进行等待 防止mysql 死锁的方式优化sql 自行顺序…

(2024,DDPM,DDIM,流匹配,SDE,ODE)扩散:基础教程

Step-by-Step Diffusion: An Elementary Tutorial 公和众与号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0 前言 1 扩散的基础知识 1.1 高斯扩散 1.2 抽象中的扩散 1.3 离散化 2 随机采样…