数据结构C语言描述11(图文结合)--二叉搜索树(BST树)的实现(数据采用KV存储形式进行封装)

news/2025/1/15 21:00:22/

前言

  • 这个专栏将会用纯C实现常用的数据结构和简单的算法
  • 有C基础即可跟着学习,代码均可运行;
  • 准备考研的也可跟着写,个人感觉,如果时间充裕,手写一遍比看书、刷题管用很多,这也是本人采用纯C语言实现的原因之一;
  • 欢迎收藏 + 关注,本人将会持续更新。

文章目录

    • 什么是二叉搜索树
    • 代码实现
      • 节点封装
      • 插入节点
      • 删除节点
      • 输出(中序遍历有序)
      • 总代码

什么是二叉搜索树

二叉搜索树(Binary Search Tree,BST)是一种特殊的二叉树数据结构其中每个节点的值都大于其左子树中的任何节点的值,且小于其右子树中的任何节点的值

它的特点使得在搜索、插入和删除操作上具有高效性。

以下是一些关于二叉搜索树的重要特性

  • 左子树中的所有节点的值都小于根节点的值。
  • 右子树中的所有节点的值都大于根节点的值。
  • 左右子树本身也是二叉搜索树。
  • 中序遍历有序。

由于这些特性,二叉搜索树可以用于高效地实现插入、搜索和删除操作。

  • 搜索操作可以在平均情况下以O(log n)的时间复杂度完成,其中n是树中节点的数量。
  • 然而,最坏情况下,树可能退化为链表,搜索操作的时间复杂度将变为O(n)
  • 插入操作的时间复杂度与搜索操作类似,平均情况下为O(log n),最坏情况下为O(n)
  • 删除操作的时间复杂度也是O(log n),最坏情况下为O(n)

BST书图示为:

在这里插入图片描述

代码实现

节点封装

节点封装,采用KV存储方式,数据在BST树中是存储K值这里规定K值不重复

typedef struct Data {int key;char data[DATAMAX];
}Data;typedef struct Node {Data* data;struct Node* lChild;struct Node* rChild;
}Node;Data* creata_data(Data data)
{Data* new_data = (Data*)calloc(1, sizeof(Data));assert(new_data);new_data->key = data.key;strncpy(new_data->data, data.data, DATAMAX);return new_data;
}Node* create_node(Data data)
{Node* node = (Node*)calloc(1, sizeof(Node));assert(node);node->data = creata_data(data);assert(node->data);return node;
}

插入节点

采用递归简历树。

// 插入过程建树
void push_tree(Node** root, Data data)
{assert(root);// 树为NULLif (*root == NULL) {*root = create_node(data);return;}else {   // 树不为NULLif (data.key < (*root)->data->key) {push_tree(&(*root)->lChild, data);}else {   // > =默认也插在右边,但是一般这种kv存储,是不允许有重复值的push_tree(&(*root)->rChild, data);}}
}

删除节点

删除节点要注意,采用递归删除有5种情况,据图代码所示(清理可以参考代码随想录力扣题目解析:BST树的删除):

// 删除
// 这里采用:左节点,最右节点
// 利用BST树的特点
// 5种情况
Node* erase_tree(Node* root, Data data)
{if (root == NULL) {return root;}if (root->data->key == data.key) {if (root->lChild == NULL && root->rChild == NULL) {free(root);root = NULL;return root;}else if (root->lChild == NULL && root->rChild != NULL) {Node* t = root;root = root->rChild;free(t);t = NULL;return root;}else if (root->lChild != NULL && root->rChild == NULL) {Node* t = root;root = root->lChild;free(t);t = NULL;return root;}else {Node* t = root->lChild;while (t->rChild) {t = t->rChild;}t->rChild = root->rChild;Node* temp = root;root = root->lChild;free(temp);return root;}}if (root && root->data->key > data.key) root->lChild = erase_tree(root->lChild, data);if (root && root->data->key < data.key) root->rChild = erase_tree(root->rChild, data);
}

输出(中序遍历有序)

BST树的中序遍历是有序的

// 中序有序
void mid_travel(Node* root)
{if (root == NULL) {return;}mid_travel(root->lChild);printf("K: %d, V: %s\n", root->data->key, root->data->data);mid_travel(root->rChild);
}

总代码

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <string.h>// 这里采用  kv 存储的方法,进行建立,  key也可以作为一个权重,具体情况需要结合业务#define DATAMAX 20typedef struct Data {int key;char data[DATAMAX];
}Data;typedef struct Node {Data* data;struct Node* lChild;struct Node* rChild;
}Node;Data* creata_data(Data data)
{Data* new_data = (Data*)calloc(1, sizeof(Data));assert(new_data);new_data->key = data.key;strncpy(new_data->data, data.data, DATAMAX);return new_data;
}Node* create_node(Data data)
{Node* node = (Node*)calloc(1, sizeof(Node));assert(node);node->data = creata_data(data);assert(node->data);return node;
}// 插入过程建树
void push_tree(Node** root, Data data)
{assert(root);// 树为NULLif (*root == NULL) {*root = create_node(data);return;}else {   // 树不为NULLif (data.key < (*root)->data->key) {push_tree(&(*root)->lChild, data);}else {   // > =默认也插在右边,但是一般这种kv存储,是不允许有重复值的push_tree(&(*root)->rChild, data);}}
}// 删除
// 这里采用:左节点,最右节点
// 利用BST树的特点
// 5种情况
Node* erase_tree(Node* root, Data data)
{if (root == NULL) {return root;}if (root->data->key == data.key) {if (root->lChild == NULL && root->rChild == NULL) {free(root);root = NULL;return root;}else if (root->lChild == NULL && root->rChild != NULL) {Node* t = root;root = root->rChild;free(t);t = NULL;return root;}else if (root->lChild != NULL && root->rChild == NULL) {Node* t = root;root = root->lChild;free(t);t = NULL;return root;}else {Node* t = root->lChild;while (t->rChild) {t = t->rChild;}t->rChild = root->rChild;Node* temp = root;root = root->lChild;free(temp);return root;}}if (root && root->data->key > data.key) root->lChild = erase_tree(root->lChild, data);if (root && root->data->key < data.key) root->rChild = erase_tree(root->rChild, data);
}// 中序有序
void mid_travel(Node* root)
{if (root == NULL) {return;}mid_travel(root->lChild);printf("K: %d, V: %s\n", root->data->key, root->data->data);mid_travel(root->rChild);
}int main()
{Data data[10] = { {17, "yy"}, {9, "xx"}, {22, "zz"}, {2, "ll"}, {8, "tt"}, {33, "xh"}, {20, "tt"}, {18, "ee"}, {77, "zz"}, {10, "hh"} };Node* root = NULL;for (int i = 0; i < 10; i++) {push_tree(&root, data[i]);}mid_travel(root);int key = 22;Data temp = { 22, "tt" };erase_tree(root, temp);printf("*****************************\n");mid_travel(root);return 0;
}

http://www.ppmy.cn/news/1563424.html

相关文章

首选DNS服务器地址和备用DNS服务器地址怎么设置

在计算机网络中&#xff0c;DNS&#xff08;域名系统&#xff09;服务器扮演着至关重要的角色。它负责将域名转换为 IP 地址&#xff0c;使我们能够通过易于记忆的域名访问互联网上的各种资源。而设置合适的首选DNS服务器地址和备用DNS服务器地址&#xff0c;对于保障网络连接的…

大语言模型训练数据集格式

1. SFT&#xff08;有监督微调&#xff09;的数据集格式 对于大语言模型的训练中&#xff0c;SFT&#xff08;Supervised Fine-Tuning&#xff09;的数据集格式可以采用以下方式&#xff1a; 输入数据&#xff1a;输入数据是一个文本序列&#xff0c;通常是一个句子或者一个段…

【机器学习:十二、TensorFlow简介及实现】

TensorFlow简介 1. 背景 TensorFlow是由谷歌团队开发的一种开源机器学习框架&#xff0c;最初于2015年发布&#xff0c;其主要目的是为研究人员和开发者提供一个高效、灵活且易于部署的工具&#xff0c;用于深度学习和其他机器学习任务。它支持多种平台和语言&#xff0c;包括…

Ubuntu服务器提示:检测到存在恶意文件,补救思路

1. 确定文件类型 可以使用file命令来检查该文件的类型&#xff0c;这有助于判断它是否真的是一个恶意文件 file /path/to/the/file 2. 检查文件内容 使用strings命令查看文件内容&#xff0c;看是否有可疑的命令或脚本&#xff1a; strings /path/to/the/file 3. 扫描系统…

[CTF/网络安全] 攻防世界 Web_php_unserialize 解题详析

代码审计 这段代码首先定义了一个名为 Demo 的类&#xff0c;包含了一个私有变量 $file 和三个魔术方法 __construct()、__destruct() 和 __wakeup()。其中&#xff1a; __construce()方法用于初始化 $file 变量__destruce方法用于输出文件内容__wakeup() 方法检查当前对象的…

Java Stream流操作List全攻略:Filter、Sort、GroupBy、Average、Sum实践

在Java 8及更高版本中&#xff0c;Stream API为集合处理带来了革命性的改变。本文将深入解析如何运用Stream对List进行高效的操作&#xff0c;包括筛选&#xff08;Filter&#xff09;、排序&#xff08;Sort&#xff09;、分组&#xff08;GroupBy&#xff09;、求平均值&…

从github上,下载的android项目,从0-1进行编译运行-踩坑精力,如何进行部署

因为国内的网络原因&#xff0c;一直在anroidstudio开发的问题上&#xff0c;是个每个开发者都会踩坑 一直以为是自己的原因&#xff0c;其实很多都是国内网络的原因&#xff0c;今天就从一个开发者的视角 把从github上一个陌生的项目&#xff0c;如何通过本地就行运行的 首先…

Vue 框架深度剖析:原理、应用与最佳实践

目录 一、Vue 框架简介 二、Vue 的安装与基本使用 &#xff08;一&#xff09;安装 &#xff08;二&#xff09;基本使用 三、Vue 组件 &#xff08;一&#xff09;创建组件 &#xff08;二&#xff09;组件通信 四、Vue 模板语法 &#xff08;一&#xff09;插值 &a…