- 数据结构与算法
- DSA - 首页
- DSA - 概述
- DSA - 环境设置
- DSA - 算法基础
- DSA - 渐进分析
- 数据结构
- DSA - 数据结构基础
- DSA - 数据结构和类型
- DSA - 数组数据结构
- 链表
- DSA - 链表数据结构
- DSA - 双向链表数据结构
- DSA - 循环链表数据结构
- 栈与队列
- DSA - 栈数据结构
- DSA - 表达式解析
- DSA - 队列数据结构
- 搜索算法
- DSA - 搜索算法
- DSA - 线性搜索算法
- DSA - 二分搜索算法
- DSA - 插值搜索
- DSA - 跳跃搜索算法
- DSA - 指数搜索
- DSA - 斐波那契搜索
- DSA - 子列表搜索
- DSA - 哈希表
- 排序算法
- DSA - 排序算法
- DSA - 冒泡排序算法
- DSA - 插入排序算法
- DSA - 选择排序算法
- DSA - 归并排序算法
- DSA - 希尔排序算法
- DSA - 堆排序
- DSA - 桶排序算法
- DSA - 计数排序算法
- DSA - 基数排序算法
- DSA - 快速排序算法
- 图数据结构
- DSA - 图数据结构
- DSA - 深度优先遍历
- DSA - 广度优先遍历
- DSA - 生成树
- 树数据结构
- DSA - 树数据结构
- DSA - 树的遍历
- DSA - 二叉搜索树
- DSA - AVL树
- DSA - 红黑树
- DSA - B树
- DSA - B+树
- DSA - 伸展树
- DSA - 字典树
- DSA - 堆数据结构
- 递归
- DSA - 递归算法
- DSA - 使用递归实现汉诺塔问题
- DSA - 使用递归实现斐波那契数列
- 分治法
- DSA - 分治法
- DSA - 最大最小问题
- DSA - Strassen矩阵乘法
- DSA - Karatsuba算法
- 贪心算法
- DSA - 贪心算法
- DSA - 旅行商问题(贪心算法)
- DSA - Prim最小生成树
- DSA - Kruskal最小生成树
- DSA - Dijkstra最短路径算法
- DSA - 地图着色算法
- DSA - 分数背包问题
- DSA - 带截止日期的作业排序
- DSA - 最佳合并模式算法
- 动态规划
- DSA - 动态规划
- DSA - 矩阵链乘法
- DSA - Floyd-Warshall算法
- DSA - 0-1背包问题
- DSA - 最长公共子序列算法
- DSA - 旅行商问题(动态规划方法)
- 近似算法
- DSA - 近似算法
- DSA - 顶点覆盖算法
- DSA - 集合覆盖问题
- DSA - 旅行商问题(近似方法)
- 随机化算法
- DSA - 随机化算法
- DSA - 随机化快速排序算法
- DSA - Karger最小割算法
- DSA - Fisher-Yates洗牌算法
- DSA 有用资源
- DSA - 常见问题解答
- DSA - 快速指南
- DSA - 有用资源
- DSA - 讨论
数据结构与算法 - 快速指南
概述
数据结构是以一种系统化的方式组织数据,以便高效地使用它。以下术语是数据结构的基础术语。
接口 - 每个数据结构都有一个接口。接口表示数据结构支持的操作集合。接口仅提供支持的操作列表、它们可以接受的参数类型以及这些操作的返回类型。
实现 - 实现提供了数据结构的内部表示。实现还提供了数据结构操作中使用的算法的定义。
数据结构的特征
正确性 - 数据结构的实现应正确实现其接口。
时间复杂度 - 数据结构操作的运行时间或执行时间必须尽可能短。
空间复杂度 - 数据结构操作的内存使用量应尽可能少。
数据结构的必要性
随着应用程序变得越来越复杂和数据丰富,如今应用程序面临着三个常见问题。
数据搜索 - 考虑一个商店拥有 100 万 (106) 件商品的库存。如果应用程序要搜索一件商品,它每次都必须在 100 万 (106) 件商品中搜索,从而降低搜索速度。随着数据量的增长,搜索将变得更慢。
处理器速度 - 尽管处理器速度非常高,但如果数据增长到数十亿条记录,它也会受到限制。
多个请求 - 由于数千名用户可以在 Web 服务器上同时搜索数据,即使是速度最快的服务器在搜索数据时也会失效。
为了解决上述问题,数据结构可以提供帮助。数据可以以这样一种方式组织在数据结构中,即可能不需要搜索所有项目,并且可以几乎立即搜索所需的数据。
执行时间案例
通常使用三种情况以相对的方式比较各种数据结构的执行时间。
最坏情况 - 这是数据结构操作可能花费的最长时间的情况。如果操作的最坏情况时间为 ƒ(n),则此操作不会花费超过 ƒ(n) 时间,其中 ƒ(n) 表示 n 的函数。
平均情况 - 这种情况描述了数据结构操作的平均执行时间。如果一个操作需要 ƒ(n) 时间执行,则 m 个操作将需要 mƒ(n) 时间。
最佳情况 - 这种情况描述了数据结构操作的最小可能执行时间。如果操作需要 ƒ(n) 时间执行,则实际操作可能花费的时间与随机数相同,该随机数最大为 ƒ(n)。
基本术语
数据 - 数据是值或一组值。
数据项 - 数据项指的是单个值的单元。
分组项 - 被划分为子项的数据项称为分组项。
基本项 - 无法再细分的数据项称为基本项。
属性和实体 - 实体是包含某些属性或特性的东西,这些属性或特性可以被赋予值。
实体集 - 具有相似属性的实体构成一个实体集。
字段 - 字段是表示实体属性的单个基本信息单元。
记录 - 记录是给定实体的字段值的集合。
文件 - 文件是给定实体集中实体的记录的集合。
环境设置
本地环境设置
如果您仍然希望为 C 编程语言设置您的环境,则需要在您的计算机上提供以下两个工具:(a) 文本编辑器和 (b) C 编译器。
文本编辑器
这将用于键入您的程序。一些编辑器的示例包括 Windows 记事本、OS Edit 命令、Brief、Epsilon、EMACS 以及 vim 或 vi。
文本编辑器的名称和版本在不同的操作系统上可能有所不同。例如,Notepad 将用于 Windows,而 vim 或 vi 既可以用于 Windows,也可以用于 Linux 或 UNIX。
您使用编辑器创建的文件称为源文件,其中包含程序源代码。C 程序的源文件通常以扩展名“.c”命名。
在开始编程之前,请确保您已准备好一个文本编辑器,并且您拥有足够的经验来编写计算机程序,将其保存在文件中,编译它,最后执行它。
C 编译器
源文件中编写的源代码是程序的人类可读源代码。它需要“编译”才能转换为机器语言,以便您的 CPU 能够根据给定的指令实际执行程序。
此 C 编程语言编译器将用于将您的源代码编译成最终的可执行程序。我们假设您具备关于编程语言编译器的基本知识。
最常使用且免费提供的编译器是 GNU C/C++ 编译器。或者,如果您有相应的操作系统 (OS),则可以使用 HP 或 Solaris 的编译器。
以下部分指导您如何在各种操作系统上安装 GNU C/C++ 编译器。我们一起提到 C/C++,因为 GNU GCC 编译器适用于 C 和 C++ 编程语言。
在 UNIX/Linux 上安装
如果您使用的是Linux 或 UNIX,请通过从命令行输入以下命令来检查您的系统上是否安装了 GCC:
$ gcc -v
如果您的机器上安装了 GNU 编译器,则它应该打印类似于以下内容的消息:
Using built-in specs. Target: i386-redhat-linux Configured with: ../configure --prefix = /usr ....... Thread model: posix gcc version 4.1.2 20080704 (Red Hat 4.1.2-46)
如果未安装 GCC,则您需要使用 https://gcc.gnu.org/install/ 中提供的详细说明自行安装。
本教程是基于 Linux 编写的,所有给出的示例都已在 Cent OS 版本的 Linux 系统上编译。
在 Mac OS 上安装
如果您使用 Mac OS X,获取 GCC 的最简单方法是从 Apple 的网站下载 Xcode 开发环境,并按照简单的安装说明进行操作。设置好 Xcode 后,您就可以使用 GNU 编译器来编译 C/C++ 了。
Xcode 目前可在 developer.apple.com/technologies/tools/ 获取。
在 Windows 上安装
要在 Windows 上安装 GCC,您需要安装 MinGW。要安装 MinGW,请访问 MinGW 主页 www.mingw.org,并按照链接到 MinGW 下载页面的链接进行操作。下载最新版本的 MinGW 安装程序,其名称应为 MinGW-<version>.exe。
在安装 MinWG 时,至少必须安装 gcc-core、gcc-g++、binutils 和 MinGW 运行时,但您可能希望安装更多内容。
将 MinGW 安装的 bin 子目录添加到您的PATH环境变量中,以便您可以在命令行中通过其简单的名称指定这些工具。
安装完成后,您将能够从 Windows 命令行运行 gcc、g++、ar、ranlib、dlltool 和其他几个 GNU 工具。
数据结构基础
本章解释了与数据结构相关的基本术语。
数据定义
数据定义使用以下特征定义特定数据。
原子性 - 定义应定义单个概念。
可追溯的 - 定义应该能够映射到某些数据元素。
准确的 - 定义应该明确无误。
清晰简洁 - 定义应该易于理解。
数据对象
数据对象表示具有数据的一个对象。
数据类型
数据类型是将各种类型的数据(例如整数、字符串等)进行分类的一种方式,它决定了可以与相应类型的数据一起使用的值,以及可以对相应类型的数据执行的操作类型。有两种数据类型 -
- 内置数据类型
- 派生数据类型
内置数据类型
语言内置支持的那些数据类型称为内置数据类型。例如,大多数语言提供以下内置数据类型。
- 整数
- 布尔值(真,假)
- 浮点数(十进制数)
- 字符和字符串
派生数据类型
那些与实现无关的数据类型,因为它们可以以一种或另一种方式实现,被称为派生数据类型。这些数据类型通常由基本或内置数据类型及其相关操作组合而成。例如 -
- 列表
- 数组
- 栈
- 队列
基本操作
数据结构中的数据通过某些操作进行处理。选择特定的数据结构很大程度上取决于需要对数据结构执行的操作的频率。
- 遍历
- 搜索
- 插入
- 删除
- 排序
- 合并
数据结构和类型
数据结构是为了在编程语言中存储、组织和操作数据而引入的。它们的设计方式使数据访问和处理更加容易和简单。这些数据结构不限于一种特定的编程语言;它们只是在内存中组织数据的代码片段。
数据类型经常被误认为是一种数据结构,但即使它们被称为抽象数据类型,这也不完全正确。数据类型表示数据的性质,而数据结构只是一组相似或不同的数据类型的集合。
通常只有两种类型的数据结构 -
线性
非线性
线性数据结构
数据在线性数据结构中按顺序存储。这些是基本的结构,因为元素一个接一个地存储,无需应用任何数学运算。
线性数据结构通常易于实现,但由于内存分配可能会变得复杂,因此时间和空间复杂度会增加。线性数据结构的一些示例包括 -
数组
链表
栈
队列
根据数据存储方法,这些线性数据结构分为两种子类型。它们是 - 静态和动态数据结构。
静态线性数据结构
在静态线性数据结构中,内存分配不可扩展。一旦使用完所有内存,就无法检索更多空间来存储更多数据。因此,需要根据程序的大小预留内存。这也会成为一个缺点,因为预留比所需更多的内存会导致内存块的浪费。
静态线性数据结构的最佳示例是数组。
动态线性数据结构
在动态线性数据结构中,可以在需要时动态地进行内存分配。考虑到程序的空间复杂度,这些数据结构是有效的。
动态线性数据结构的一些示例包括:链表、栈和队列。
非线性数据结构
非线性数据结构以层次结构的形式存储数据。因此,与线性数据结构相反,数据可以在多个级别中找到,并且难以遍历。
但是,它们旨在克服线性数据结构的问题和局限性。例如,线性数据结构的主要缺点是内存分配。由于数据在线性数据结构中按顺序分配,因此这些数据结构中的每个元素都使用一个完整的内存块。但是,如果数据使用的内存少于分配的块可以容纳的内存,则块中的额外内存空间就会浪费。因此,引入了非线性数据结构。它们降低了空间复杂度并优化了内存使用。
非线性数据结构的一些类型是 -
图
树
字典树
映射
数组数据结构
数组是一种线性数据结构类型,定义为具有相同或不同数据类型的元素的集合。它们存在于单维和多维中。当需要将多个类似性质的元素存储在一个地方时,这些数据结构就会出现。
数组索引和内存地址之间的区别在于,数组索引充当标记数组中元素的键值。但是,内存地址是可用空闲内存的起始地址。
以下是理解数组概念的重要术语。
元素 - 存储在数组中的每个项目称为元素。
索引 - 数组中每个元素的位置都有一个数字索引,用于识别该元素。
语法
在C和C++编程语言中创建数组 -
data_type array_name[array_size] = {elements separated using commas} or, data_type array_name[array_size];
在Java编程语言中创建数组 -
data_type[] array_name = {elements separated by commas} or, data_type array_name = new data_type[array_size];
数组的必要性
数组被用作从小型排序问题到更复杂问题(如旅行商问题)的许多问题的解决方案。除了数组之外,还有许多其他数据结构为这些问题提供了有效的时间和空间复杂度,那么是什么使使用数组更好呢?答案在于随机访问查找时间。
数组提供O(1)随机访问查找时间。这意味着访问数组的第一个索引和数组的第 1000 个索引将花费相同的时间。这是因为数组带有一个指针和一个偏移值。指针指向内存的正确位置,偏移值显示在所述内存中查找多远。
array_name[index] | | Pointer Offset
因此,在一个包含 6 个元素的数组中,要访问第一个元素,数组指向第 0 个索引。类似地,要访问第 6 个元素,数组指向第 5 个索引。
数组表示
数组表示为存储桶的集合,每个存储桶存储一个元素。这些存储桶从“0”到“n-1”索引,其中 n 是该特定数组的大小。例如,大小为 10 的数组将具有从 0 到 9 索引的存储桶。
此索引对于多维数组也类似。如果它是二维数组,则每个存储桶中将有子存储桶。然后它将被索引为 array_name[m][n],其中 m 和 n 是数组中每个级别的尺寸。
根据以上说明,以下是要考虑的重要事项。
索引从 0 开始。
数组长度为 9,这意味着它可以存储 9 个元素。
可以通过其索引访问每个元素。例如,我们可以获取索引为 6 的元素作为 23。
数组中的基本操作
数组中的基本操作是插入、删除、搜索、显示、遍历和更新。这些操作通常用于修改数组中的数据或报告数组的状态。
以下是数组支持的基本操作。
遍历 - 一个接一个地打印所有数组元素。
插入 - 在给定索引处添加元素。
删除 - 删除给定索引处的元素。
搜索 - 使用给定索引或值搜索元素。
更新 - 更新给定索引处的元素。
显示 - 显示数组的内容。
在 C 中,当数组初始化为指定大小时,它会按照以下顺序为其元素分配默认值。
数据类型 | 默认值 |
---|---|
bool | false |
char | 0 |
int | 0 |
float | 0.0 |
double | 0.0f |
void | |
wchar_t | 0 |
插入操作
在插入操作中,我们向数组中添加一个或多个元素。根据需要,可以在数组的开头、结尾或任何给定索引处添加新元素。这是使用编程语言的输入语句完成的。
算法
以下是将元素插入线性数组直到到达数组末尾的算法 -
1. Start 2. Create an Array of a desired datatype and size. 3. Initialize a variable ‘i’ as 0. 4. Enter the element at ith index of the array. 5. Increment i by 1. 6. Repeat Steps 4 & 5 until the end of the array. 7. Stop
在这里,我们看到了插入操作的实际实现,我们将在数组末尾添加数据 -
示例
#include <stdio.h> int main(){ int LA[3] = {}, i; printf("Array Before Insertion:\n"); for(i = 0; i < 3; i++) printf("LA[%d] = %d \n", i, LA[i]); printf("Inserting Elements.. \n"); printf("The array elements after insertion :\n"); // prints array values for(i = 0; i < 3; i++) { LA[i] = i + 2; printf("LA[%d] = %d \n", i, LA[i]); } return 0; }
输出
Array Before Insertion: LA[0] = 0 LA[1] = 0 LA[2] = 0 Inserting Elements.. The array elements after insertion : LA[0] = 2 LA[1] = 3 LA[2] = 4
#include <iostream> using namespace std; int main(){ int LA[3] = {}, i; cout << "Array Before Insertion:" << endl; for(i = 0; i < 3; i++) cout << "LA[" << i <<"] = " << LA[i] << endl; //prints garbage values cout << "Inserting elements.." <<endl; cout << "Array After Insertion:" << endl; // prints array values for(i = 0; i < 5; i++) { LA[i] = i + 2; cout << "LA[" << i <<"] = " << LA[i] << endl; } return 0; }
输出
Array Before Insertion: LA[0] = 0 LA[1] = 0 LA[2] = 0 Inserting elements.. Array After Insertion: LA[0] = 2 LA[1] = 3 LA[2] = 4 LA[3] = 5 LA[4] = 6
public class ArrayDemo { public static void main(String []args) { int LA[] = new int[3]; System.out.println("Array Before Insertion:"); for(int i = 0; i < 3; i++) System.out.println("LA[" + i + "] = " + LA[i]); //prints empty array System.out.println("Inserting Elements.."); // Printing Array after Insertion System.out.println("Array After Insertion:"); for(int i = 0; i < 3; i++) { LA[i] = i+3; System.out.println("LA[" + i + "] = " + LA[i]); } } }
输出
Array Before Insertion: LA[0] = 0 LA[1] = 0 LA[2] = 0 Inserting Elements.. Array After Insertion: LA[0] = 3 LA[1] = 4 LA[2] = 5
# python program to insert element using insert operation def insert(arr, element): arr.append(element) # Driver's code if __name__ == '__main__': # declaring array and value to insert LA = [0, 0, 0] x = 0 # array before inserting an element print("Array Before Insertion: ") for x in range(len(LA)): print("LA", [x], " = " , LA[x]) print("Inserting elements....") # array after Inserting element for x in range(len(LA)): LA.append(x); LA[x] = x+1; print("Array After Insertion: ") for x in range(len(LA)): print("LA", [x], " = " , LA[x])
输出
Array Before Insertion: LA [0] = 0 LA [1] = 0 LA [2] = 0 Inserting elements.... Array After Insertion: LA [0] = 1 LA [1] = 2 LA [2] = 3 LA [3] = 0 LA [4] = 1 LA [5] = 2
有关数组插入操作的其他变体,点击此处。
删除操作
在此数组操作中,我们从数组的特定索引中删除一个元素。此删除操作发生在我们为后续索引中的值分配给当前索引时。
算法
假设 LA 是一个包含 N 个元素的线性数组,K 是一个正整数,使得 K<=N。以下是删除 LA 第 K 个位置上的元素的算法。
1. Start 2. Set J = K 3. Repeat steps 4 and 5 while J < N 4. Set LA[J] = LA[J + 1] 5. Set J = J+1 6. Set N = N-1 7. Stop
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> void main(){ int LA[] = {1,3,5}; int n = 3; int i; printf("The original array elements are :\n"); for(i = 0; i<n; i++) printf("LA[%d] = %d \n", i, LA[i]); for(i = 1; i<n; i++) { LA[i] = LA[i+1]; n = n - 1; } printf("The array elements after deletion :\n"); for(i = 0; i<n; i++) printf("LA[%d] = %d \n", i, LA[i]); }
输出
The original array elements are : LA[0] = 1 LA[1] = 3 LA[2] = 5 The array elements after deletion : LA[0] = 1 LA[1] = 5
#include <iostream> using namespace std; int main(){ int LA[] = {1,3,5}; int i, n = 3; cout << "The original array elements are :"<<endl; for(i = 0; i<n; i++) { cout << "LA[" << i << "] = " << LA[i] << endl; } for(i = 1; i<n; i++) { LA[i] = LA[i+1]; n = n - 1; } cout << "The array elements after deletion :"<<endl; for(i = 0; i<n; i++) { cout << "LA[" << i << "] = " << LA[i] <<endl; } }
输出
The original array elements are : LA[0] = 1 LA[1] = 3 LA[2] = 5 The array elements after deletion : LA[0] = 1 LA[1] = 5
public class ArrayDemo { public static void main(String []args) { int LA[] = new int[3]; int n = LA.length; System.out.println("Array Before Deletion:"); for(int i = 0; i < n; i++) { LA[i] = i + 3; System.out.println("LA[" + i + "] = " + LA[i]); } for(int i = 1; i<n-1; i++) { LA[i] = LA[i+1]; n = n - 1; } System.out.println("Array After Deletion:"); for(int i = 0; i < n; i++) { System.out.println("LA[" + i + "] = " + LA[i]); } } }
输出
Array Before Deletion: LA[0] = 3 LA[1] = 4 LA[2] = 5 Array After Deletion: LA[0] = 3 LA[1] = 5
#python program to delete the value using delete operation if __name__ == '__main__': # Declaring array and deleting value LA = [0,0,0] n = len(LA) print("Array Before Deletion: ") for x in range(len(LA)): LA.append(x) LA[x] = x + 3 print("LA", [x], " = " , LA[x]) # delete the value if exists # or show error it does not exist in the list for x in range(1, n-1): LA[x] = LA[x+1] n = n-1 print("Array After Deletion: ") for x in range(n): print("LA", [x], " = " , LA[x])
输出
Array Before Deletion: LA [0] = 3 LA [1] = 4 LA [2] = 5 Array After Deletion: LA [0] = 3 LA [1] = 5
搜索操作
使用键在数组中搜索元素;键元素依次比较数组中的每个值,以检查键是否存在于数组中。
算法
假设 LA 是一个包含 N 个元素的线性数组,K 是一个正整数,使得 K<=N。以下是使用顺序搜索查找值为 ITEM 的元素的算法。
1. Start 2. Set J = 0 3. Repeat steps 4 and 5 while J < N 4. IF LA[J] is equal ITEM THEN GOTO STEP 6 5. Set J = J +1 6. PRINT J, ITEM 7. Stop
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> void main(){ int LA[] = {1,3,5,7,8}; int item = 5, n = 5; int i = 0, j = 0; printf("The original array elements are :\n"); for(i = 0; i<n; i++) { printf("LA[%d] = %d \n", i, LA[i]); } for(i = 0; i<n; i++) { if( LA[i] == item ) { printf("Found element %d at position %d\n", item, i+1); } } }
输出
The original array elements are : LA[0] = 1 LA[1] = 3 LA[2] = 5 LA[3] = 7 LA[4] = 8 Found element 5 at position 3
#include <iostream> using namespace std; int main(){ int LA[] = {1,3,5,7,8}; int item = 5, n = 5; int i = 0; cout << "The original array elements are : " <<endl; for(i = 0; i<n; i++) { cout << "LA[" << i << "] = " << LA[i] << endl; } for(i = 0; i<n; i++) { if( LA[i] == item ) { cout << "Found element " << item << " at position " << i+1 <<endl; } } return 0; }
输出
The original array elements are : LA[0] = 1 LA[1] = 3 LA[2] = 5 LA[3] = 7 LA[4] = 8 Found element 5 at position 3
public class ArrayDemo{ public static void main(String []args){ int LA[] = new int[5]; System.out.println("Array:"); for(int i = 0; i < 5; i++) { LA[i] = i + 3; System.out.println("LA[" + i + "] = " + LA[i]); } for(int i = 0; i < 5; i++) { if(LA[i] == 6) System.out.println("Element " + 6 + " is found at index " + i); } } }
输出
Array: LA[0] = 3 LA[1] = 4 LA[2] = 5 LA[3] = 6 LA[4] = 7 Element 6 is found at index 3
#search operation using python def findElement(arr, n, value): for i in range(n): if (arr[i] == value): return i # If the key is not found return -1 # Driver's code if __name__ == '__main__': LA = [1,3,5,7,8] print("Array element are: ") for x in range(len(LA)): print("LA", [x], " = ", LA[x]) value = 5 n = len(LA) # element found using search operation index = findElement(LA, n, value) if index != -1: print("Element", value, "Found at position = " + str(index + 1)) else: print("Element not found")
输出
Array element are: LA [0] = 1 LA [1] = 3 LA [2] = 5 LA [3] = 7 LA [4] = 8 Element 5 Found at position = 3
遍历操作
此操作遍历数组的所有元素。我们使用循环语句来执行此操作。
算法
以下是遍历线性数组中所有元素的算法 -
1 Start 2. Initialize an Array of certain size and datatype. 3. Initialize another variable ‘i’ with 0. 4. Print the ith value in the array and increment i. 5. Repeat Step 4 until the end of the array is reached. 6. End
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> int main(){ int LA[] = {1,3,5,7,8}; int item = 10, k = 3, n = 5; int i = 0, j = n; printf("The original array elements are :\n"); for(i = 0; i<n; i++) { printf("LA[%d] = %d \n", i, LA[i]); } }
输出
The original array elements are : LA[0] = 1 LA[1] = 3 LA[2] = 5 LA[3] = 7 LA[4] = 8
#include <iostream> using namespace std; int main(){ int LA[] = {1,3,5,7,8}; int item = 10, k = 3, n = 5; int i = 0, j = n; cout << "The original array elements are:\n"; for(i = 0; i<n; i++) cout << "LA[" << i << "] = " << LA[i] << endl; return 0; }
输出
The original array elements are: LA[0] = 1 LA[1] = 3 LA[2] = 5 LA[3] = 7 LA[4] = 8
public class ArrayDemo { public static void main(String []args) { int LA[] = new int[5]; System.out.println("The array elements are: "); for(int i = 0; i < 5; i++) { LA[i] = i + 2; System.out.println("LA[" + i + "] = " + LA[i]); } } }
输出
The array elements are: LA[0] = 2 LA[1] = 3 LA[2] = 4 LA[3] = 5 LA[4] = 6
# Python code to iterate over a array using python LA = [1, 3, 5, 7, 8] # length of the elements length = len(LA) # Traversing the elements using For loop and range # same as 'for x in range(len(array))' print("Array elements are: ") for x in range(length): print("LA", [x], " = ", LA[x])
输出
Array elements are: LA [0] = 1 LA [1] = 3 LA [2] = 5 LA [3] = 7 LA [4] = 8
更新操作
更新操作是指更新数组中给定索引处的现有元素。
算法
假设 LA 是一个包含 N 个元素的线性数组,K 是一个正整数,使得 K<=N。以下是更新 LA 第 K 个位置上的元素的算法。
1. Start 2. Set LA[K-1] = ITEM 3. Stop
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> void main(){ int LA[] = {1,3,5,7,8}; int k = 3, n = 5, item = 10; int i, j; printf("The original array elements are :\n"); for(i = 0; i<n; i++) { printf("LA[%d] = %d \n", i, LA[i]); } LA[k-1] = item; printf("The array elements after updation :\n"); for(i = 0; i<n; i++) { printf("LA[%d] = %d \n", i, LA[i]); } }
输出
The original array elements are : LA[0] = 1 LA[1] = 3 LA[2] = 5 LA[3] = 7 LA[4] = 8 The array elements after updation : LA[0] = 1 LA[1] = 3 LA[2] = 10 LA[3] = 7 LA[4] = 8
#include <iostream> using namespace std; int main(){ int LA[] = {1,3,5,7,8}; int item = 10, k = 3, n = 5; int i = 0, j = n; cout << "The original array elements are :\n"; for(i = 0; i<n; i++) cout << "LA[" << i << "] = " << LA[i] << endl; LA[2] = item; cout << "The array elements after updation are :\n"; for(i = 0; i<n; i++) cout << "LA[" << i << "] = " << LA[i] << endl; return 0; }
输出
The original array elements are : LA[0] = 1 LA[1] = 3 LA[2] = 5 LA[3] = 7 LA[4] = 8 The array elements after updation are : LA[0] = 1 LA[1] = 3 LA[2] = 10 LA[3] = 7 LA[4] = 8
public class ArrayDemo { public static void main(String []args) { int LA[] = new int[5]; int item = 15; System.out.println("The array elements are: "); for(int i = 0; i < 5; i++) { LA[i] = i + 2; System.out.println("LA[" + i + "] = " + LA[i]); } LA[3] = item; System.out.println("The array elements after updation are: "); for(int i = 0; i < 5; i++) System.out.println("LA[" + i + "] = " + LA[i]); } }
输出
The array elements are: LA[0] = 2 LA[1] = 3 LA[2] = 4 LA[3] = 5 LA[4] = 6 The array elements after updation are: LA[0] = 2 LA[1] = 3 LA[2] = 4 LA[3] = 15 LA[4] = 6
#update operation using python #Declaring array elements LA = [1,3,5,7,8] #before updation print("The original array elements are :"); for x in range(len(LA)): print("LA", [x], " = ", LA[x]) #after updation LA[2] = 10 print("The array elements after updation are: ") for x in range(len(LA)): print("LA", [x], " = ", LA[x])
输出
The original array elements are : LA [0] = 1 LA [1] = 3 LA [2] = 5 LA [3] = 7 LA [4] = 8 The array elements after updation are: LA [0] = 1 LA [1] = 3 LA [2] = 10 LA [3] = 7 LA [4] = 8
显示操作
此操作使用打印语句显示整个数组中的所有元素。
算法
1. Start 2. Print all the elements in the Array 3. Stop
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> int main(){ int LA[] = {1,3,5,7,8}; int n = 5; int i; printf("The original array elements are :\n"); for(i = 0; i<n; i++) { printf("LA[%d] = %d \n", i, LA[i]); } }
输出
The original array elements are : LA[0] = 1 LA[1] = 3 LA[2] = 5 LA[3] = 7 LA[4] = 8
#include <iostream> using namespace std; int main(){ int LA[] = {1,3,5,7,8}; int n = 5; int i; cout << "The original array elements are :\n"; for(i = 0; i<n; i++) cout << "LA[" << i << "] = " << LA[i] << endl; return 0; }
输出
The original array elements are : LA[0] = 1 LA[1] = 3 LA[2] = 5 LA[3] = 7 LA[4] = 8
public class ArrayDemo { public static void main(String []args) { int LA[] = new int[5]; System.out.println("The array elements are: "); for(int i = 0; i < 5; i++) { LA[i] = i + 2; System.out.println("LA[" + i + "] = " + LA[i]); } } }
输出
The array elements are: LA[0] = 2 LA[1] = 3 LA[2] = 4 LA[3] = 5 LA[4] = 6
#Display operation using python #Display operation using python #Declaring array elements LA = [2,3,4,5,6] #Displaying the array print("The array elements are: ") for x in range(len(LA)): print("LA", [x], " = " , LA[x])
输出
The array elements are: LA [0] = 2 LA [1] = 3 LA [2] = 4 LA [3] = 5 LA [4] = 6
链表数据结构
如果数组容纳类似类型的数据类型,则链表由具有不同数据类型的元素组成,这些元素也按顺序排列。
但是这些链表是如何创建的呢?
链表是由一系列称为“节点”的元素通过链接连接而成的数据结构。每个节点包含要存储的数据以及指向链表中下一个节点地址的指针。数组的大小受定义限制,但链表没有固定的大小。可以在其中存储任意数量的数据,也可以从中删除数据。
链表主要分为三种类型:
单向链表 - 节点只指向列表中下一个节点的地址。
双向链表 - 节点同时指向其前一个节点和后一个节点的地址。
循环链表 - 链表中的最后一个节点指向链表中的第一个节点。循环链表可以是单向的,也可以是双向的。
链表表示
链表可以被形象地理解为节点组成的链条,每个节点都指向下一个节点。
根据以上说明,以下是要考虑的重要事项。
链表包含一个称为 first(头节点)的链接元素。
每个链接都包含一个或多个数据域和一个称为 next 的链接域。
每个链接都使用其 next 链接与其下一个链接连接。
最后一个链接的 next 链接为 null,用于标记链表的结尾。
链表的类型
以下是各种类型的链表。
单向链表
单向链表的每个节点包含两个“存储单元”:一个存储数据,另一个存储列表中下一个节点的地址。由于节点之间只有一个链接,因此只能单向遍历链表。
双向链表
双向链表的每个节点包含三个“存储单元”:一个存储数据,另外两个分别存储列表中前一个节点和后一个节点的地址。由于列表中的节点从两侧相互连接,因此可以双向遍历链表。
循环链表
循环链表可以是单向链表,也可以是双向链表。
由于循环链表的最后一个节点和第一个节点是连接的,因此遍历此链表将无限循环,直到链条被断开。
链表的基本操作
链表的基本操作包括插入、删除、搜索、显示以及删除指定键值元素。以下是在单向链表上执行这些操作的方法:
插入 - 在列表开头添加一个元素。
删除 - 删除列表开头的一个元素。
显示 - 显示整个列表。
搜索 - 使用给定的键值搜索元素。
删除 - 使用给定的键值删除元素。
插入操作
在链表中添加新节点是一个多步骤的操作。我们将在这里用图表学习它。首先,使用相同的结构创建一个节点,并找到要插入节点的位置。
假设我们要在节点 A(LeftNode)和节点 C(RightNode)之间插入节点 B(NewNode)。然后将 B.next 指向 C -
NewNode.next −> RightNode;
它应该看起来像这样 -
现在,左侧的下一个节点应该指向新节点。
LeftNode.next −> NewNode;
这将把新节点放在这两个节点的中间。新的列表应该看起来像这样 -
链表的插入操作可以分为三种不同的方式。解释如下:
头部插入
在此操作中,我们在列表的开头添加一个元素。
算法
1. START 2. Create a node to store the data 3. Check if the list is empty 4. If the list is empty, add the data to the node and assign the head pointer to it. 5 If the list is not empty, add the data to a node and link to the current head. Assign the head to the newly added node. 6. END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <string.h> #include <stdlib.h> struct node { int data; struct node *next; }; struct node *head = NULL; struct node *current = NULL; // display the list void printList(){ struct node *p = head; printf("\n["); //start from the beginning while(p != NULL) { printf(" %d ",p->data); p = p->next; } printf("]"); } //insertion at the beginning void insertatbegin(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; // point it to old first node lk->next = head; //point first to new first node head = lk; } void main(){ int k=0; insertatbegin(12); insertatbegin(22); insertatbegin(30); insertatbegin(44); insertatbegin(50); printf("Linked List: "); // print list printList(); }
输出
Linked List: [ 50 44 30 22 12 ]
#include <bits/stdc++.h> #include <string> using namespace std; struct node { int data; struct node *next; }; struct node *head = NULL; struct node *current = NULL; // display the list void printList(){ struct node *p = head; cout << "\n["; //start from the beginning while(p != NULL) { cout << " " << p->data << " "; p = p->next; } cout << "]"; } //insertion at the beginning void insertatbegin(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; // point it to old first node lk->next = head; //point first to new first node head = lk; } int main(){ insertatbegin(12); insertatbegin(22); insertatbegin(30); insertatbegin(44); insertatbegin(50); cout << "Linked List: "; // print list printList(); }
输出
Linked List: [ 50 44 30 22 12 ]
public class Linked_List { static class node { int data; node next; node (int value) { data = value; next = null; } } static node head; // display the list static void printList() { node p = head; System.out.print("\n["); //start from the beginning while(p != null) { System.out.print(" " + p.data + " "); p = p.next; } System.out.print("]"); } //insertion at the beginning static void insertatbegin(int data) { //create a link node lk = new node(data);; // point it to old first node lk.next = head; //point first to new first node head = lk; } public static void main(String args[]) { int k=0; insertatbegin(12); insertatbegin(22); insertatbegin(30); insertatbegin(44); insertatbegin(50); insertatbegin(33); System.out.println("Linked List: "); // print list printList(); } }
输出
Linked List: [33 50 44 30 22 12 ]
class Node: def __init__(self, data=None): self.data = data self.next = None class SLL: def __init__(self): self.head = None # Print the linked list def listprint(self): printval = self.head print("Linked List: ") while printval is not None: print (printval.data) printval = printval.next def AddAtBeginning(self,newdata): NewNode = Node(newdata) # Update the new nodes next val to existing node NewNode.next = self.head self.head = NewNode l1 = SLL() l1.head = Node("731") e2 = Node("672") e3 = Node("63") l1.head.next = e2 e2.next = e3 l1.AddAtBeginning("122") l1.listprint()
输出
Linked List: 122 731 672 63
尾部插入
在此操作中,我们在列表的末尾添加一个元素。
算法
1. START 2. Create a new node and assign the data 3. Find the last node 4. Point the last node to new node 5. END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <string.h> #include <stdlib.h> struct node { int data; struct node *next; }; struct node *head = NULL; struct node *current = NULL; // display the list void printList(){ struct node *p = head; printf("\n["); //start from the beginning while(p != NULL) { printf(" %d ",p->data); p = p->next; } printf("]"); } //insertion at the beginning void insertatbegin(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; // point it to old first node lk->next = head; //point first to new first node head = lk; } void insertatend(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; struct node *linkedlist = head; // point it to old first node while(linkedlist->next != NULL) linkedlist = linkedlist->next; //point first to new first node linkedlist->next = lk; } void main(){ int k=0; insertatbegin(12); insertatend(22); insertatend(30); insertatend(44); insertatend(50); printf("Linked List: "); // print list printList(); }
输出
Linked List: [ 12 22 30 44 50 ]
#include <bits/stdc++.h> #include <string> using namespace std; struct node { int data; struct node *next; }; struct node *head = NULL; struct node *current = NULL; // display the list void printList(){ struct node *p = head; cout << "\n["; //start from the beginning while(p != NULL) { cout << " " << p->data << " "; p = p->next; } cout << "]"; } //insertion at the beginning void insertatbegin(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; // point it to old first node lk->next = head; //point first to new first node head = lk; } void insertatend(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; struct node *linkedlist = head; // point it to old first node while(linkedlist->next != NULL) linkedlist = linkedlist->next; //point first to new first node linkedlist->next = lk; } int main(){ insertatbegin(12); insertatend(22); insertatbegin(30); insertatend(44); insertatbegin(50); cout << "Linked List: "; // print list printList(); }
输出
Linked List: [ 50 30 12 22 44 ]
public class Linked_List { static class node { int data; node next; node (int value) { data = value; next = null; } } static node head; // display the list static void printList() { node p = head; System.out.print("\n["); //start from the beginning while(p != null) { System.out.print(" " + p.data + " "); p = p.next; } System.out.print("]"); } //insertion at the beginning static void insertatbegin(int data) { //create a link node lk = new node(data);; // point it to old first node lk.next = head; //point first to new first node head = lk; } static void insertatend(int data) { //create a link node lk = new node(data); node linkedlist = head; // point it to old first node while(linkedlist.next != null) linkedlist = linkedlist.next; //point first to new first node linkedlist.next = lk; } public static void main(String args[]) { int k=0; insertatbegin(12); insertatbegin(22); insertatbegin(30); insertatend(44); insertatend(50); insertatend(33); System.out.println("Linked List: "); // print list printList(); } }
输出
Linked List: [ 30 22 12 44 50 33 ]
class Node: def __init__(self, data=None): self.data = data self.next = None class LL: def __init__(self): self.head = None def listprint(self): val = self.head print("Linked List:") while val is not None: print(val.data) val = val.next l1 = LL() l1.head = Node("23") l2 = Node("12") l3 = Node("7") l4 = Node("14") l5 = Node("61") # Linking the first Node to second node l1.head.next = l2 # Linking the second Node to third node l2.next = l3 l3.next = l4 l4.next = l5 l1.listprint()
输出
Linked List: 23 12 7 14 61
指定位置插入
在此操作中,我们在列表中的任何位置添加一个元素。
算法
1. START 2. Create a new node and assign data to it 3. Iterate until the node at position is found 4. Point first to new first node 5. END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <string.h> #include <stdlib.h> struct node { int data; struct node *next; }; struct node *head = NULL; struct node *current = NULL; // display the list void printList(){ struct node *p = head; printf("\n["); //start from the beginning while(p != NULL) { printf(" %d ",p->data); p = p->next; } printf("]"); } //insertion at the beginning void insertatbegin(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; // point it to old first node lk->next = head; //point first to new first node head = lk; } void insertafternode(struct node *list, int data){ struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; lk->next = list->next; list->next = lk; } void main(){ int k=0; insertatbegin(12); insertatbegin(22); insertafternode(head->next, 30); printf("Linked List: "); // print list printList(); }
输出
Linked List: [ 22 12 30 ]
#include <bits/stdc++.h> #include <string> using namespace std; struct node { int data; struct node *next; }; struct node *head = NULL; struct node *current = NULL; // display the list void printList(){ struct node *p = head; cout << "\n["; //start from the beginning while(p != NULL) { cout << " " << p->data << " "; p = p->next; } cout << "]"; } //insertion at the beginning void insertatbegin(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; // point it to old first node lk->next = head; //point first to new first node head = lk; } void insertafternode(struct node *list, int data){ struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; lk->next = list->next; list->next = lk; } int main(){ insertatbegin(12); insertatbegin(22); insertatbegin(30); insertafternode(head->next,44); insertafternode(head->next->next, 50); cout << "Linked List: "; // print list printList(); }
输出
Linked List: [ 30 22 44 50 12 ]
public class Linked_List { static class node { int data; node next; node (int value) { data = value; next = null; } } static node head; // display the list static void printList() { node p = head; System.out.print("\n["); //start from the beginning while(p != null) { System.out.print(" " + p.data + " "); p = p.next; } System.out.print("]"); } //insertion at the beginning static void insertatbegin(int data) { //create a link node lk = new node(data);; // point it to old first node lk.next = head; //point first to new first node head = lk; } static void insertafternode(node list, int data) { node lk = new node(data); lk.next = list.next; list.next = lk; } public static void main(String args[]) { int k=0; insertatbegin(12); insertatbegin(22); insertatbegin(30); insertatbegin(44); insertafternode(head.next, 50); insertafternode(head.next.next, 33); System.out.println("Linked List: "); // print list printList(); } }
输出
Linked List: [44 30 50 33 22 12 ]
class Node: def __init__(self, data=None): self.data = data self.next = None class SLL: def __init__(self): self.head = None # Print the linked list def listprint(self): printval = self.head print("Linked List: ") while printval is not None: print (printval.data) printval = printval.next # Function to add node def InsertAtPos(self,nodeatpos,newdata): if nodeatpos is None: print("The mentioned node is absent") return NewNode = Node(newdata) NewNode.next = nodeatpos.next nodeatpos.next = NewNode l1 = SLL() l1.head = Node("731") e2 = Node("672") e3 = Node("63") l1.head.next = e2 e2.next = e3 l1.InsertAtPos(l1.head.next, "122") l1.listprint()
输出
Linked List: 731 672 122 63
删除操作
删除也是一个多步骤的过程。我们将用图形表示来学习。首先,使用搜索算法找到要删除的目标节点。
目标节点左侧(前一个)节点现在应该指向目标节点的下一个节点 -
LeftNode.next −> TargetNode.next;
这将删除指向目标节点的链接。现在,使用以下代码,我们将删除目标节点指向的内容。
TargetNode.next −> NULL;
我们需要使用已删除的节点。我们可以将其保留在内存中,或者可以简单地释放内存并完全清除目标节点。
如果节点要插入到列表的开头,则应采取类似的步骤。在末尾插入时,列表的倒数第二个节点应指向新节点,而新节点将指向 NULL。
链表的删除操作也可以分为三种不同的方式。它们如下:
头部删除
在此链表的删除操作中,我们从列表的开头删除一个元素。为此,我们将 head 指向第二个节点。
算法
1. START 2. Assign the head pointer to the next node in the list 3. END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <string.h> #include <stdlib.h> struct node { int data; struct node *next; }; struct node *head = NULL; struct node *current = NULL; // display the list void printList(){ struct node *p = head; printf("\n["); //start from the beginning while(p != NULL) { printf(" %d ",p->data); p = p->next; } printf("]"); } //insertion at the beginning void insertatbegin(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; // point it to old first node lk->next = head; //point first to new first node head = lk; } void deleteatbegin(){ head = head->next; } int main(){ int k=0; insertatbegin(12); insertatbegin(22); insertatbegin(30); insertatbegin(40); insertatbegin(55); printf("Linked List: "); // print list printList(); deleteatbegin(); printf("\nLinked List after deletion: "); // print list printList(); }
输出
Linked List: [ 55 40 30 22 12 ] Linked List after deletion: [ 40 30 22 12 ]
#include <bits/stdc++.h> #include <string> using namespace std; struct node { int data; struct node *next; }; struct node *head = NULL; struct node *current = NULL; // display the list void printList(){ struct node *p = head; cout << "\n["; //start from the beginning while(p != NULL) { cout << " " << p->data << " "; p = p->next; } cout << "]"; } //insertion at the beginning void insertatbegin(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; // point it to old first node lk->next = head; //point first to new first node head = lk; } void deleteatbegin(){ head = head->next; } int main(){ insertatbegin(12); insertatbegin(22); insertatbegin(30); insertatbegin(44); insertatbegin(50); cout << "Linked List: "; // print list printList(); deleteatbegin(); cout << "Linked List after deletion: "; printList(); }
输出
Linked List: [ 50 44 30 22 12 ] Linked List after deletion: [ 44 30 22 12 ]
public class Linked_List { static class node { int data; node next; node (int value) { data = value; next = null; } } static node head; // display the list static void printList() { node p = head; System.out.print("\n["); //start from the beginning while(p != null) { System.out.print(" " + p.data + " "); p = p.next; } System.out.print("]"); } //insertion at the beginning static void insertatbegin(int data) { //create a link node lk = new node(data);; // point it to old first node lk.next = head; //point first to new first node head = lk; } static void deleteatbegin() { head = head.next; } public static void main(String args[]) { int k=0; insertatbegin(12); insertatbegin(22); insertatbegin(30); insertatbegin(44); insertatbegin(50); insertatbegin(33); System.out.println("Linked List: "); // print list printList(); deleteatbegin(); System.out.println("\nLinked List after deletion: "); // print list printList(); } }
输出
Linked List: [ 33 50 44 30 22 12 ] Linked List after deletion: [50 44 30 22 12 ]
#python code for deletion at beginning using linked list. from typing import Optional class Node: def __init__(self, data: int, next: Optional['Node'] = None): self.data = data self.next = next class LinkedList: def __init__(self): self.head = None #display the list def print_list(self): p = self.head print("\n[", end="") while p: print(f" {p.data} ", end="") p = p.next print("]") #Insertion at the beginning def insert_at_begin(self, data: int): lk = Node(data) #point it to old first node lk.next = self.head #point firt to new first node self.head = lk def delete_at_begin(self): self.head = self.head.next if __name__ == "__main__": linked_list = LinkedList() linked_list.insert_at_begin(12) linked_list.insert_at_begin(22) linked_list.insert_at_begin(30) linked_list.insert_at_begin(44) linked_list.insert_at_begin(50) #print list print("Linked List: ", end="") linked_list.print_list() linked_list.delete_at_begin() print("Linked List after deletion: ", end="") linked_list.print_list()
输出
Linked List: [ 50 44 30 22 12 ] Linked List after deletion: [ 44 30 22 12 ]
尾部删除
在此链表的删除操作中,我们从列表的末尾删除一个元素。
算法
1. START 2. Iterate until you find the second last element in the list. 3. Assign NULL to the second last element in the list. 4. END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <string.h> #include <stdlib.h> struct node { int data; struct node *next; }; struct node *head = NULL; struct node *current = NULL; // display the list void printList(){ struct node *p = head; printf("\n["); //start from the beginning while(p != NULL) { printf(" %d ",p->data); p = p->next; } printf("]"); } //insertion at the beginning void insertatbegin(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; // point it to old first node lk->next = head; //point first to new first node head = lk; } void deleteatend(){ struct node *linkedlist = head; while (linkedlist->next->next != NULL) linkedlist = linkedlist->next; linkedlist->next = NULL; } void main(){ int k=0; insertatbegin(12); insertatbegin(22); insertatbegin(30); insertatbegin(40); insertatbegin(55); printf("Linked List: "); // print list printList(); deleteatend(); printf("\nLinked List after deletion: "); // print list printList(); }
输出
Linked List: [ 55 40 30 22 12 ] Linked List after deletion: [ 55 40 30 22 ]
#include <bits/stdc++.h> #include <string> using namespace std; struct node { int data; struct node *next; }; struct node *head = NULL; struct node *current = NULL; // Displaying the list void printList(){ struct node *p = head; while(p != NULL) { cout << " " << p->data << " "; p = p->next; } } // Insertion at the beginning void insertatbegin(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; // point it to old first node lk->next = head; //point first to new first node head = lk; } void deleteatend(){ struct node *linkedlist = head; while (linkedlist->next->next != NULL) linkedlist = linkedlist->next; linkedlist->next = NULL; } int main(){ insertatbegin(12); insertatbegin(22); insertatbegin(30); insertatbegin(44); insertatbegin(50); cout << "Linked List: "; // print list printList(); deleteatend(); cout << "\nLinked List after deletion: "; printList(); }
输出
Linked List: 50 44 30 22 12 Linked List after deletion: 50 44 30 22
public class Linked_List { static class node { int data; node next; node (int value) { data = value; next = null; } } static node head; // display the list static void printList() { node p = head; System.out.print("\n["); //start from the beginning while(p != null) { System.out.print(" " + p.data + " "); p = p.next; } System.out.print("]"); } //insertion at the beginning static void insertatbegin(int data) { //create a link node lk = new node(data);; // point it to old first node lk.next = head; //point first to new first node head = lk; } static void deleteatend() { node linkedlist = head; while (linkedlist.next.next != null) linkedlist = linkedlist.next; linkedlist.next = null; } public static void main(String args[]) { int k=0; insertatbegin(12); insertatbegin(22); insertatbegin(30); insertatbegin(44); insertatbegin(50); insertatbegin(33); System.out.println("Linked List: "); // print list printList(); //deleteatbegin(); deleteatend(); System.out.println("\nLinked List after deletion: "); // print list printList(); } }
输出
Linked List: [ 33 50 44 30 22 12 ] Linked List after deletion: [ 33 50 44 30 22 ]
#python code for deletion at beginning using linked list. class Node: def __init__(self, data=None): self.data = data self.next = None class LinkedList: def __init__(self): self.head = None #Displaying the list def printList(self): p = self.head print("\n[", end="") while p != None: print(" " + str(p.data) + " ", end="") p = p.next print("]") #Insertion at the beginning def insertatbegin(self, data): #create a link lk = Node(data) #point it to old first node lk.next = self.head #point first to new first node self.head = lk def deleteatend(self): linkedlist = self.head while linkedlist.next.next != None: linkedlist = linkedlist.next linkedlist.next = None if __name__ == "__main__": linked_list = LinkedList() linked_list.insertatbegin(12) linked_list.insertatbegin(22) linked_list.insertatbegin(30) linked_list.insertatbegin(40) linked_list.insertatbegin(55) #print list print("Linked List: ", end="") linked_list.printList() linked_list.deleteatend() print("Linked List after deletion: ", end="") linked_list.printList()
输出
Linked List: [ 55 40 30 22 12 ] Linked List after deletion: [ 55 40 30 22 ]
指定位置删除
在此链表的删除操作中,我们从列表的任何位置删除一个元素。
算法
1. START 2. Iterate until find the current node at position in the list 3. Assign the adjacent node of current node in the list to its previous node. 4. END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <string.h> #include <stdlib.h> struct node { int data; struct node *next; }; struct node *head = NULL; struct node *current = NULL; // display the list void printList(){ struct node *p = head; printf("\n["); //start from the beginning while(p != NULL) { printf(" %d ",p->data); p = p->next; } printf("]"); } //insertion at the beginning void insertatbegin(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; // point it to old first node lk->next = head; //point first to new first node head = lk; } void deletenode(int key){ struct node *temp = head, *prev; if (temp != NULL && temp->data == key) { head = temp->next; return; } // Find the key to be deleted while (temp != NULL && temp->data != key) { prev = temp; temp = temp->next; } // If the key is not present if (temp == NULL) return; // Remove the node prev->next = temp->next; } void main(){ int k=0; insertatbegin(12); insertatbegin(22); insertatbegin(30); insertatbegin(40); insertatbegin(55); printf("Linked List: "); // print list printList(); deletenode(30); printf("\nLinked List after deletion: "); // print list printList(); }
输出
Linked List: [ 55 40 30 22 12 ] Linked List after deletion: [ 55 40 22 12 ]
#include <bits/stdc++.h> #include <string> using namespace std; struct node { int data; struct node *next; }; struct node *head = NULL; struct node *current = NULL; // display the list void printList(){ struct node *p = head; cout << "\n["; //start from the beginning while(p != NULL) { cout << " " << p->data << " "; p = p->next; } cout << "]"; } //insertion at the beginning void insertatbegin(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; // point it to old first node lk->next = head; //point first to new first node head = lk; } void deletenode(int key){ struct node *temp = head, *prev; if (temp != NULL && temp->data == key) { head = temp->next; return; } // Find the key to be deleted while (temp != NULL && temp->data != key) { prev = temp; temp = temp->next; } // If the key is not present if (temp == NULL) return; // Remove the node prev->next = temp->next; } int main(){ insertatbegin(12); insertatbegin(22); insertatbegin(30); insertatbegin(44); insertatbegin(50); cout << "Linked List: "; // print list printList(); deletenode(30); cout << "Linked List after deletion: "; printList(); }
输出
Linked List: [ 50 44 30 22 12 ]Linked List after deletion: [ 50 44 22 12 ]
public class Linked_List { static class node { int data; node next; node (int value) { data = value; next = null; } } static node head; // display the list static void printList() { node p = head; System.out.print("\n["); //start from the beginning while(p != null) { System.out.print(" " + p.data + " "); p = p.next; } System.out.print("]"); } //insertion at the beginning static void insertatbegin(int data) { //create a link node lk = new node(data);; // point it to old first node lk.next = head; //point first to new first node head = lk; } static void deletenode(int key) { node temp = head; node prev = null; if (temp != null && temp.data == key) { head = temp.next; return; } // Find the key to be deleted while (temp != null && temp.data != key) { prev = temp; temp = temp.next; } // If the key is not present if (temp == null) return; // Remove the node prev.next = temp.next; } public static void main(String args[]) { int k=0; insertatbegin(12); insertatbegin(22); insertatbegin(30); insertatbegin(44); insertatbegin(50); insertatbegin(33); System.out.println("Linked List: "); // print list printList(); //deleteatbegin(); //deleteatend(); deletenode(12); System.out.println("\nLinked List after deletion: "); // print list printList(); } }
输出
Linked List: [ 33 50 44 30 22 12 ] Linked List after deletion: [ 33 50 44 30 22 ]
#python code for deletion at given position using linked list. class Node: def __init__(self, data=None): self.data = data self.next = None class LinkedList: def __init__(self): self.head = None # display the list def printList(self): p = self.head print("\n[", end="") #start from the beginning while(p != None): print(" ", p.data, " ", end="") p = p.next print("]") #insertion at the beginning def insertatbegin(self, data): #create a link lk = Node(data) # point it to old first node lk.next = self.head #point first to new first node self.head = lk def deletenode(self, key): temp = self.head if (temp != None and temp.data == key): self.head = temp.next return # Find the key to be deleted while (temp != None and temp.data != key): prev = temp temp = temp.next # If the key is not present if (temp == None): return # Remove the node prev.next = temp.next llist = LinkedList() llist.insertatbegin(12) llist.insertatbegin(22) llist.insertatbegin(30) llist.insertatbegin(40) llist.insertatbegin(55) print("Original Linked List: ", end="") # print list llist.printList() llist.deletenode(30) print("\nLinked List after deletion: ", end="") # print list llist.printList()
输出
Linked List: [ 55 40 30 22 12 ] Linked List after deletion: [ 55 40 22 12 ]
反转操作
此操作比较复杂。我们需要使最后一个节点由头节点指向,并反转整个链表。
首先,我们遍历到列表的末尾。它应该指向 NULL。现在,我们将使其指向其前一个节点 -
我们必须确保最后一个节点不是最后一个节点。所以我们将有一些 temp 节点,它看起来像 head 节点指向最后一个节点。现在,我们将一个接一个地使所有左侧节点指向其前一个节点。
除了 head 节点指向的节点(第一个节点)之外,所有节点都应该指向其前驱节点,使其成为其新的后继节点。第一个节点将指向 NULL。
我们将使用 temp 节点使 head 节点指向新的第一个节点。
算法
反转链表的分步过程如下:
1 START 2. We use three pointers to perform the reversing: prev, next, head. 3. Point the current node to head and assign its next value to the prev node. 4. Iteratively repeat the step 3 for all the nodes in the list. 5. Assign head to the prev node.
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <string.h> #include <stdlib.h> struct node { int data; struct node *next; }; struct node *head = NULL; struct node *current = NULL; // display the list void printList(){ struct node *p = head; printf("\n["); //start from the beginning while(p != NULL) { printf(" %d ",p->data); p = p->next; } printf("]"); } //insertion at the beginning void insertatbegin(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; // point it to old first node lk->next = head; //point first to new first node head = lk; } void reverseList(struct node** head){ struct node *prev = NULL, *cur=*head, *tmp; while(cur!= NULL) { tmp = cur->next; cur->next = prev; prev = cur; cur = tmp; } *head = prev; } void main(){ int k=0; insertatbegin(12); insertatbegin(22); insertatbegin(30); insertatbegin(40); insertatbegin(55); printf("Linked List: "); // print list printList(); reverseList(&head); printf("\nReversed Linked List: "); printList(); }
输出
Linked List: [ 55 40 30 22 12 ] Reversed Linked List: [ 12 22 30 40 55 ]
#include <bits/stdc++.h> struct node { int data; struct node *next; }; struct node *head = NULL; struct node *current = NULL; // display the list void printList(){ struct node *p = head; printf("\n["); //start from the beginning while(p != NULL) { printf(" %d ",p->data); p = p->next; } printf("]"); } //insertion at the beginning void insertatbegin(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; // point it to old first node lk->next = head; //point first to new first node head = lk; } void reverseList(struct node** head){ struct node *prev = NULL, *cur=*head, *tmp; while(cur!= NULL) { tmp = cur->next; cur->next = prev; prev = cur; cur = tmp; } *head = prev; } int main(){ int k=0; insertatbegin(12); insertatbegin(22); insertatbegin(30); insertatbegin(40); insertatbegin(55); printf("Linked List: "); // print list printList(); reverseList(&head); printf("\nReversed Linked List: "); printList(); return 0; }
输出
Linked List: [ 55 40 30 22 12 ] Reversed Linked List: [ 12 22 30 40 55 ]
public class Linked_List { static Node head; static class Node { int data; Node next; Node (int value) { data = value; next = null; } } // display the list static void printList(Node node) { System.out.print("\n["); //start from the beginning while(node != null) { System.out.print(" " + node.data + " "); node = node.next; } System.out.print("]"); } static Node reverseList(Node head) { Node prev = null; Node cur = head; Node temp = null; while (cur != null) { temp = cur.next; cur.next = prev; prev = cur; cur = temp; } head = prev; return head; } public static void main(String args[]) { Linked_List list = new Linked_List(); list.head = new Node(33); list.head.next = new Node(50); list.head.next.next = new Node(44); list.head.next.next.next = new Node(22); list.head.next.next.next.next = new Node(12); System.out.println("Linked List: "); // print list list.printList(head); head = list.reverseList(head); System.out.println("\nReversed linked list "); list.printList(head); } }
输出
Linked List: [ 33 50 44 22 12 ] Reversed linked list [ 12 22 44 50 33 ]
class Node: def __init__(self, data=None): self.data = data self.next = None class SLL: def __init__(self): self.head = None # Print the linked list def listprint(self): printval = self.head print("Linked List: ") while printval is not None: print (printval.data) printval = printval.next def reverse(self): prev = None curr = self.head while(curr is not None): next = curr.next curr.next = prev prev = curr curr = next self.head = prev l1 = SLL() l1.head = Node("731") e2 = Node("672") e3 = Node("63") l1.head.next = e2 e2.next = e3 l1.listprint() l1.reverse() print("After reversing: ") l1.listprint()
输出
Linked List: 731 672 63 After reversing: Linked List: 63 672 731
搜索操作
使用键值元素搜索列表中的元素。此操作与数组搜索的方式相同;将列表中的每个元素与给定的键值元素进行比较。
算法
1 START 2 If the list is not empty, iteratively check if the list contains the key 3 If the key element is not present in the list, unsuccessful search 4 END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <string.h> #include <stdlib.h> struct node { int data; struct node *next; }; struct node *head = NULL; struct node *current = NULL; // display the list void printList(){ struct node *p = head; printf("\n["); //start from the beginning while(p != NULL) { printf(" %d ",p->data); p = p->next; } printf("]"); } //insertion at the beginning void insertatbegin(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; // point it to old first node lk->next = head; //point first to new first node head = lk; } int searchlist(int key){ struct node *temp = head; while(temp != NULL) { if (temp->data == key) { return 1; } temp=temp->next; } return 0; } void main(){ int k=0; insertatbegin(12); insertatbegin(22); insertatbegin(30); insertatbegin(40); insertatbegin(55); printf("Linked List: "); // print list printList(); k = searchlist(30); if (k == 1) printf("\nElement is found"); else printf("\nElement is not present in the list"); }
输出
Linked List: [ 55 40 30 22 12 ] Element is found
#include <bits/stdc++.h> #include <string> using namespace std; struct node { int data; struct node *next; }; struct node *head = NULL; struct node *current = NULL; // display the list void printList(){ struct node *p = head; cout << "\n["; //start from the beginning while(p != NULL) { cout << " " << p->data << " "; p = p->next; } cout << "]"; } //insertion at the beginning void insertatbegin(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; // point it to old first node lk->next = head; //point first to new first node head = lk; } int searchlist(int key){ struct node *temp = head; while(temp != NULL) { if (temp->data == key) { return 1; } temp=temp->next; } return 0; } int main(){ int k = 0; insertatbegin(12); insertatbegin(22); insertatbegin(30); insertatbegin(44); insertatbegin(50); cout << "Linked List: "; // print list printList(); k = searchlist(16); if (k == 1) cout << "\nElement is found"; else cout << "\nElement is not present in the list"; }
输出
Linked List: [ 50 44 30 22 12 ] Element is not present in the list
public class Linked_List { static class node { int data; node next; node (int value) { data = value; next = null; } } static node head; // display the list static void printList() { node p = head; System.out.print("\n["); //start from the beginning while(p != null) { System.out.print(" " + p.data + " "); p = p.next; } System.out.print("]"); } //insertion at the beginning static void insertatbegin(int data) { //create a link node lk = new node(data);; // point it to old first node lk.next = head; //point first to new first node head = lk; } static int searchlist(int key) { node temp = head; while(temp != null) { if (temp.data == key) { return 1; } temp=temp.next; } return 0; } public static void main(String args[]) { int k=0; insertatbegin(12); insertatbegin(22); insertatbegin(30); insertatbegin(44); insertatbegin(50); insertatbegin(33); System.out.println("Linked List: "); // print list printList(); k = searchlist(44); if (k == 1) System.out.println("\nElement is found"); else System.out.println("\nElement is not present in the list"); } }
输出
Linked List: [33 50 44 30 22 12 ] Element is found
class Node: def __init__(self, data=None): self.data = data self.next = None class SLL: def __init__(self): self.head = None def search(self, x): count = 0 # Initialize current to head current = self.head # loop till current not equal to None while current != None: if current.data == x: print("data found") count = count + 1 current = current.next if count == 0: print("Data Not found") l1 = SLL() l1.head = Node("731") e2 = Node("672") e3 = Node("63") l1.head.next = e2 e2.next = e3 l1.search("63")
输出
data found
遍历操作
遍历操作按顺序遍历列表的所有元素,并按该顺序显示元素。
算法
1. START 2. While the list is not empty and did not reach the end of the list, print the data in each node 3. END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <string.h> #include <stdlib.h> struct node { int data; struct node *next; }; struct node *head = NULL; struct node *current = NULL; // display the list void printList(){ struct node *p = head; printf("\n["); //start from the beginning while(p != NULL) { printf(" %d ",p->data); p = p->next; } printf("]"); } //insertion at the beginning void insertatbegin(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; // point it to old first node lk->next = head; //point first to new first node head = lk; } void main(){ int k=0; insertatbegin(12); insertatbegin(22); insertatbegin(30); printf("Linked List: "); // print list printList(); }
输出
Linked List: [ 30 22 12 ]
#include <bits/stdc++.h> #include <string> using namespace std; struct node { int data; struct node *next; }; struct node *head = NULL; struct node *current = NULL; // Displaying the list void printList(){ struct node *p = head; while(p != NULL) { cout << " " << p->data << " "; p = p->next; } } // Insertion at the beginning void insertatbegin(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; // point it to old first node lk->next = head; //point first to new first node head = lk; } int main(){ insertatbegin(12); insertatbegin(22); insertatbegin(30); insertatbegin(44); insertatbegin(50); cout << "Linked List: "; // print list printList(); }
输出
Linked List: 50 44 30 22 12
public class Linked_List { static class node { int data; node next; node (int value) { data = value; next = null; } } static node head; // display the list static void printList() { node p = head; System.out.print("\n["); //start from the beginning while(p != null) { System.out.print(" " + p.data + " "); p = p.next; } System.out.print("]"); } //insertion at the beginning static void insertatbegin(int data) { //create a link node lk = new node(data);; // point it to old first node lk.next = head; //point first to new first node head = lk; } public static void main(String args[]) { int k=0; insertatbegin(12); insertatbegin(22); insertatbegin(30); insertatbegin(44); insertatbegin(50); insertatbegin(33); System.out.println("Linked List: "); // print list printList(); } }
输出
Linked List: [ 33 50 44 30 22 12 ]
class Node: def __init__(self, data=None): self.data = data self.next = None class SLL: def __init__(self): self.head = None # Print the linked list def listprint(self): printval = self.head print("Linked List: ") while printval is not None: print (printval.data) printval = printval.next l1 = SLL() l1.head = Node("731") e2 = Node("672") e3 = Node("63") l1.head.next = e2 e2.next = e3 l1.listprint()
输出
Linked List: 731 672 63
完整实现
#include <stdio.h> #include <string.h> #include <stdlib.h> struct node { int data; struct node *next; }; struct node *head = NULL; struct node *current = NULL; // display the list void printList(){ struct node *p = head; printf("\n["); //start from the beginning while(p != NULL) { printf(" %d ",p->data); p = p->next; } printf("]"); } //insertion at the beginning void insertatbegin(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; // point it to old first node lk->next = head; //point first to new first node head = lk; } void insertatend(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; struct node *linkedlist = head; // point it to old first node while(linkedlist->next != NULL) linkedlist = linkedlist->next; //point first to new first node linkedlist->next = lk; } void insertafternode(struct node *list, int data){ struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; lk->next = list->next; list->next = lk; } void deleteatbegin(){ head = head->next; } void deleteatend(){ struct node *linkedlist = head; while (linkedlist->next->next != NULL) linkedlist = linkedlist->next; linkedlist->next = NULL; } void deletenode(int key){ struct node *temp = head, *prev; if (temp != NULL && temp->data == key) { head = temp->next; return; } // Find the key to be deleted while (temp != NULL && temp->data != key) { prev = temp; temp = temp->next; } // If the key is not present if (temp == NULL) return; // Remove the node prev->next = temp->next; } int searchlist(int key){ struct node *temp = head; while(temp != NULL) { if (temp->data == key) { return 1; } temp=temp->next; } return 0; } void main(){ int k=0; insertatbegin(12); insertatbegin(22); insertatend(30); insertatend(44); insertatbegin(50); insertafternode(head->next->next, 33); printf("Linked List: "); // print list printList(); deleteatbegin(); deleteatend(); deletenode(12); printf("\nLinked List after deletion: "); // print list printList(); insertatbegin(4); insertatbegin(16); printf("\nUpdated Linked List: "); printList(); k = searchlist(16); if (k == 1) printf("\nElement is found"); else printf("\nElement is not present in the list"); }
输出
Linked List: [ 50 22 12 33 30 44 ] Linked List after deletion: [ 22 33 30 ] Updated Linked List: [ 16 4 22 33 30 ] Element is found
#include <bits/stdc++.h> #include <string> using namespace std; struct node { int data; struct node *next; }; struct node *head = NULL; struct node *current = NULL; // display the list void printList(){ struct node *p = head; cout << "\n["; //start from the beginning while(p != NULL) { cout << " " << p->data << " "; p = p->next; } cout << "]"; } //insertion at the beginning void insertatbegin(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; // point it to old first node lk->next = head; //point first to new first node head = lk; } void insertatend(int data){ //create a link struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; struct node *linkedlist = head; // point it to old first node while(linkedlist->next != NULL) linkedlist = linkedlist->next; //point first to new first node linkedlist->next = lk; } void insertafternode(struct node *list, int data){ struct node *lk = (struct node*) malloc(sizeof(struct node)); lk->data = data; lk->next = list->next; list->next = lk; } void deleteatbegin(){ head = head->next; } void deleteatend(){ struct node *linkedlist = head; while (linkedlist->next->next != NULL) linkedlist = linkedlist->next; linkedlist->next = NULL; } void deletenode(int key){ struct node *temp = head, *prev; if (temp != NULL && temp->data == key) { head = temp->next; return; } // Find the key to be deleted while (temp != NULL && temp->data != key) { prev = temp; temp = temp->next; } // If the key is not present if (temp == NULL) return; // Remove the node prev->next = temp->next; } int searchlist(int key){ struct node *temp = head; while(temp != NULL) { if (temp->data == key) { temp=temp->next; return 1; } else return 0; } } int main(){ int k=0; insertatbegin(12); insertatbegin(22); insertatend(30); insertatend(44); insertatbegin(50); insertafternode(head->next->next, 33); cout << "Linked List: "; // print list printList(); deleteatbegin(); deleteatend(); deletenode(12); cout << "\nLinked List after deletion: "; // print list printList(); insertatbegin(4); insertatbegin(16); cout << "\nUpdated Linked List: "; printList(); k = searchlist(16); if (k == 1) cout << "\nElement is found"; else cout << "\nElement is not present in the list"; return 0; }
输出
Linked List: [ 50 22 12 33 30 44 ] Linked List after deletion: [ 22 33 30 ] Updated Linked List: [ 16 4 22 33 30 ] Element is found
public class Linked_List { static class node { int data; node next; node (int value) { data = value; next = null; } } static node head; // display the list static void printList() { node p = head; System.out.print("\n["); //start from the beginning while(p != null) { System.out.print(" " + p.data + " "); p = p.next; } System.out.print("]"); } //insertion at the beginning static void insertatbegin(int data) { //create a link node lk = new node(data);; // point it to old first node lk.next = head; //point first to new first node head = lk; } static void insertatend(int data) { //create a link node lk = new node(data); node linkedlist = head; // point it to old first node while(linkedlist.next != null) linkedlist = linkedlist.next; //point first to new first node linkedlist.next = lk; } static void insertafternode(node list, int data) { node lk = new node(data); lk.next = list.next; list.next = lk; } static void deleteatbegin() { head = head.next; } static void deleteatend() { node linkedlist = head; while (linkedlist.next.next != null) linkedlist = linkedlist.next; linkedlist.next = null; } static void deletenode(int key) { node temp = head; node prev = null; if (temp != null && temp.data == key) { head = temp.next; return; } // Find the key to be deleted while (temp != null && temp.data != key) { prev = temp; temp = temp.next; } // If the key is not present if (temp == null) return; // Remove the node prev.next = temp.next; } static int searchlist(int key) { node temp = head; while(temp != null) { if (temp.data == key) { temp=temp.next; return 1; } } return 0; } public static void main(String args[]) { int k=0; insertatbegin(12); insertatbegin(22); insertatend(30); insertatend(44); insertatbegin(50); insertafternode(head.next.next, 33); System.out.println("Linked List: "); // print list printList(); deleteatbegin(); deleteatend(); deletenode(12); System.out.println("\nLinked List after deletion: "); // print list printList(); insertatbegin(4); insertatbegin(16); System.out.println("\nUpdated Linked List: "); printList(); k = searchlist(16); if (k == 1) System.out.println("\nElement is found"); else System.out.println("\nElement is not present in the list"); } }
输出
Linked List: [ 50 22 12 33 30 44 ] Linked List after deletion: [ 22 33 30 ] Updated Linked List: [ 16 4 22 33 30 ] Element is found
class LLNode: def __init__(self, data=None): self.data = data self.next = None class LL: def __init__(self): self.head = None def listprint(self): printval = self.head while printval is not None: print(printval.data) printval = printval.next def AddAtBeginning(self,newdata): NewNode = LLNode(newdata) # Update the new nodes next val to existing node NewNode.next = self.head self.head = NewNode # Function to add node at a position def InsertAtPos(self,nodeatpos,newdata): if nodeatpos is None: print("The mentioned node is absent") return NewNode = LLNode(newdata) NewNode.next = nodeatpos.next nodeatpos.next = NewNode def reverse(self): prev = None curr = self.head while(curr is not None): next = curr.next curr.next = prev prev = curr curr = next self.head = prev def search(self, x): count = 0 # Initialize current to head current = self.head # loop till current not equal to None while current != None: if current.data == x: print("data found") count = count + 1 current = current.next if count == 0: print("Data Not found") l1 = LL() l1.head = LLNode("23") l2 = LLNode("12") l3 = LLNode("7") l4 = LLNode("14") l5 = LLNode("61") # Linking the first Node to second node l1.head.next = l2 # Linking the second Node to third node l2.next = l3 l3.next = l4 l4.next = l5 print("Original Linked List: ") l1.listprint() l1.AddAtBeginning("45") l1.InsertAtPos(l1.head.next.next, "4") print("Updated Linked List:") l1.listprint() l1.reverse() print("Reversed Linked List:") l1.listprint() l1.search("7")
输出
Original Linked List: 23 12 7 14 61 Updated Linked List: 45 23 12 4 7 14 61 Reversed Linked List: 61 14 7 4 12 23 45 data found
双向链表数据结构
双向链表是链表的一种变体,与单向链表相比,它可以更容易地向前和向后导航。以下是一些理解双向链表概念的重要术语。
链接 - 链表的每个链接都可以存储称为元素的数据。
Next - 链表的每个链接都包含一个指向下一个链接的链接,称为 Next。
Prev - 链表的每个链接都包含一个指向前一个链接的链接,称为 Prev。
链表 - 链表包含一个指向第一个链接(称为 First)和最后一个链接(称为 Last)的连接链接。
双向链表表示
根据以上说明,以下是要考虑的重要事项。
双向链表包含一个称为 first 和 last 的链接元素。
每个链接都包含一个或多个数据域和一个称为 next 的链接域。
每个链接都使用其 next 链接与其下一个链接连接。
每个链接都使用其前一个链接与其前一个链接连接。
最后一个链接的链接为 null,用于标记列表的结尾。
基本操作
以下是列表支持的基本操作。
插入 - 在列表开头添加一个元素。
删除 - 删除列表开头的一个元素。
尾部插入 - 在列表末尾添加一个元素。
尾部删除 - 从列表末尾删除一个元素。
指定元素后插入 - 在列表的某个元素之后添加一个元素。
删除 - 使用键值从列表中删除一个元素。
正向显示 - 以正向方式显示整个列表。
反向显示 - 以反向方式显示整个列表。
头部插入
在此操作中,我们创建一个包含三个存储单元的新节点,一个存储数据,另外两个分别存储列表中其前一个节点和后一个节点的地址。此新节点插入到列表的开头。
算法
1. START 2. Create a new node with three variables: prev, data, next. 3. Store the new data in the data variable 4. If the list is empty, make the new node as head. 5. Otherwise, link the address of the existing first node to the next variable of the new node, and assign null to the prev variable. 6. Point the head to the new node. 7. END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> struct node { int data; int key; struct node *next; struct node *prev; }; //this link always point to first Link struct node *head = NULL; //this link always point to last Link struct node *last = NULL; struct node *current = NULL; //is list empty bool isEmpty(){ return head == NULL; } //display the doubly linked list void printList(){ struct node *ptr = head; while(ptr != NULL) { printf("(%d,%d) ",ptr->key,ptr->data); ptr = ptr->next; } } //insert link at the first location void insertFirst(int key, int data){ //create a link struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; if(isEmpty()) { //make it the last link last = link; } else { //update first prev link head->prev = link; } //point it to old first link link->next = head; //point first to new first link head = link; } void main(){ insertFirst(1,10); insertFirst(2,20); insertFirst(3,30); insertFirst(4,1); insertFirst(5,40); insertFirst(6,56); printf("\nDoubly Linked List: "); printList(); }
输出
Doubly Linked List: (6,56) (5,40) (4,1) (3,30) (2,20) (1,10)
#include <iostream> #include <cstring> #include <cstdlib> #include <cstdbool> struct node { int data; int key; struct node *next; struct node *prev; }; //this link always point to first Link struct node *head = NULL; //this link always point to last Link struct node *last = NULL; struct node *current = NULL; //is list empty bool isEmpty(){ return head == NULL; } //display the doubly linked list void printList(){ struct node *ptr = head; while(ptr != NULL) { printf("(%d,%d) ",ptr->key,ptr->data); ptr = ptr->next; } } //insert link at the first location void insertFirst(int key, int data){ //create a link struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; if(isEmpty()) { //make it the last link last = link; } else { //update first prev link head->prev = link; } //point it to old first link link->next = head; //point first to new first link head = link; } int main(){ insertFirst(1,10); insertFirst(2,20); insertFirst(3,30); insertFirst(4,1); insertFirst(5,40); insertFirst(6,56); printf("\nDoubly Linked List: "); printList(); return 0; }
输出
Doubly Linked List: (6,56) (5,40) (4,1) (3,30) (2,20) (1,10)
//Java code for doubly linked list import java.util.*; class Node { public int data; public int key; public Node next; public Node prev; public Node(int data, int key) { this.data = data; this.key = key; this.next = null; this.prev = null; } } public class Main { //this link always point to first Link static Node head = null; //this link always point to last Link static Node last = null; static Node current = null; // is list empty public static boolean is_empty() { return head == null; } //display the doubly linked list public static void print_list() { Node ptr = head; while (ptr != null) { System.out.println("(" + ptr.key + "," + ptr.data + ")"); ptr = ptr.next; } } //insert link at the first location public static void insert_first(int key, int data) { //create a link Node link = new Node(data, key); if (is_empty()) { //make it the last link last = link; } else { //update first prev link head.prev = link; } //point it to old first link link.next = head; //point first to new first link head = link; } public static void main(String[] args) { insert_first(1, 10); insert_first(2, 20); insert_first(3, 30); insert_first(4, 1); insert_first(5, 40); insert_first(6, 56); System.out.println("\nDoubly Linked List: "); print_list(); } }
输出
Doubly Linked List: (6,56)(5,40)(4,1)(3,30)(2,20)(1,10)
#Python code for doubly linked list class Node: def __init__(self, data=None, key=None): self.data = data self.key = key self.next = None self.prev = None #this link always point to first Link head = None #this link always point to last Link last = None current = None #is list empty def is_empty(): return head == None #display the doubly linked list def print_list(): ptr = head while ptr != None: print(f"({ptr.key},{ptr.data})") ptr = ptr.next #insert link at the first location def insert_first(key, data): global head, last #create a link link = Node(data, key) if is_empty(): #make it the last link last = link else: #update first prev link head.prev = link #point it to old first link link.next = head #point first to new first link head = link insert_first(1,10) insert_first(2,20) insert_first(3,30) insert_first(4,1) insert_first(5,40) insert_first(6,56) print("\nDoubly Linked List: ") print_list()
输出
Doubly Linked List: (6,56) (5,40) (4,1) (3,30) (2,20) (1,10)
头部删除
此删除操作删除双向链表中现有的第一个节点。head 指针移到下一个节点,并删除链接。
算法
1. START 2. Check the status of the doubly linked list 3. If the list is empty, deletion is not possible 4. If the list is not empty, the head pointer is shifted to the next node. 5. END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> struct node { int data; int key; struct node *next; struct node *prev; }; //this link always point to first Link struct node *head = NULL; //this link always point to last Link struct node *last = NULL; struct node *current = NULL; //is list empty bool isEmpty(){ return head == NULL; } //display the doubly linked list void printList(){ struct node *ptr = head; while(ptr != NULL) { printf("(%d,%d) ",ptr->key,ptr->data); ptr = ptr->next; } } //insert link at the first location void insertFirst(int key, int data){ //create a link struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; if(isEmpty()) { //make it the last link last = link; } else { //update first prev link head->prev = link; } //point it to old first link link->next = head; //point first to new first link head = link; } //delete first item struct node* deleteFirst(){ //save reference to first link struct node *tempLink = head; //if only one link if(head->next == NULL) { last = NULL; } else { head->next->prev = NULL; } head = head->next; //return the deleted link return tempLink; } void main(){ insertFirst(1,10); insertFirst(2,20); insertFirst(3,30); insertFirst(4,1); insertFirst(5,40); insertFirst(6,56); printf("\nDoubly Linked List: "); printList(); printf("\nList after deleting first record: "); deleteFirst(); printList(); }
输出
Doubly Linked List: (6,56) (5,40) (4,1) (3,30) (2,20) (1,10) List after deleting first record: (5,40) (4,1) (3,30) (2,20) (1,10)
#include <iostream> #include <cstring> #include <cstdlib> #include <cstdbool> struct node { int data; int key; struct node *next; struct node *prev; }; //this link always point to first Link struct node *head = NULL; //this link always point to last Link struct node *last = NULL; struct node *current = NULL; //is list empty bool isEmpty(){ return head == NULL; } //display the doubly linked list void printList(){ struct node *ptr = head; while(ptr != NULL) { printf("(%d,%d) ",ptr->key,ptr->data); ptr = ptr->next; } } //insert link at the first location void insertFirst(int key, int data){ //create a link struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; if(isEmpty()) { //make it the last link last = link; } else { //update first prev link head->prev = link; } //point it to old first link link->next = head; //point first to new first link head = link; } //delete first item struct node* deleteFirst(){ //save reference to first link struct node *tempLink = head; //if only one link if(head->next == NULL) { last = NULL; } else { head->next->prev = NULL; } head = head->next; //return the deleted link return tempLink; } int main(){ insertFirst(1,10); insertFirst(2,20); insertFirst(3,30); insertFirst(4,1); insertFirst(5,40); insertFirst(6,56); printf("\nDoubly Linked List: "); printList(); printf("\nList after deleting first record: "); deleteFirst(); printList(); return 0; }
输出
Doubly Linked List: (6,56) (5,40) (4,1) (3,30) (2,20) (1,10) List after deleting first record: (5,40) (4,1) (3,30) (2,20) (1,10)
//Java code for doubly linked list import java.util.*; class Node { public int data; public int key; public Node next; public Node prev; public Node(int data, int key) { this.data = data; this.key = key; this.next = null; this.prev = null; } } public class Main { //this link always point to first Link public static Node head = null; //this link always point to last Link public static Node last = null; //this link always point to current Link public static Node current = null; //is list empty public static boolean isEmpty() { return head == null; } //display the doubly linked list public static void printList() { Node ptr = head; while (ptr != null) { System.out.print("(" + ptr.key + "," + ptr.data + ") "); ptr = ptr.next; } } //insert link at the first location public static void insertFirst(int key, int data) { //create a link Node link = new Node(data, key); if (isEmpty()) { //make it the last link last = link; } else { //update first prev link head.prev = link; } //point it to old first link link.next = head; head = link; } //delete the first item public static Node deleteFirst() { //save reference to first link Node tempLink = head; //if only one link if (head.next == null) { last = null; } else { head.next.prev = null; } head = head.next; //return the deleted link return tempLink; } public static void main(String[] args) { insertFirst(1, 10); insertFirst(2, 20); insertFirst(3, 30); insertFirst(4, 1); insertFirst(5, 40); insertFirst(6, 56); System.out.print("\nDoubly Linked List: "); printList(); System.out.print("\nList after deleting first record: "); deleteFirst(); printList(); } }
输出
Doubly Linked List: (6,56) (5,40) (4,1) (3,30) (2,20) (1,10) List after deleting first record: (5,40) (4,1) (3,30) (2,20) (1,10)
#Python code for doubly linked list class Node: def __init__(self, data=None, key=None): self.data = data self.key = key self.next = None self.prev = None #this link always point to first Link head = None #this link always point to last Link last = None current = None #is list empty def isEmpty(): return head == None #display the doubly linked list def printList(): ptr = head while ptr != None: print(f"({ptr.key},{ptr.data}) ", end="") ptr = ptr.next #insert link at the first location def insertFirst(key, data): #create a link global head, last link = Node(data, key) if isEmpty(): #make it the last link last = link else: #update first prev link head.prev = link #point it to old first link link.next = head head = link #delete first item def deleteFirst(): #save reference to first link global head, last tempLink = head #if only one link if head.next == None: last = None else: head.next.prev = None head = head.next #return the deleted link return tempLink insertFirst(1,10) insertFirst(2,20) insertFirst(3,30) insertFirst(4,1) insertFirst(5,40) insertFirst(6,56) print("\nDoubly Linked List: ", end="") printList() print("\nList after deleting first record: ") deleteFirst() printList()
输出
Doubly Linked List: (6,56) (5,40) (4,1) (3,30) (2,20) (1,10) List after deleting first record: (5,40) (4,1) (3,30) (2,20) (1,10)
尾部插入
在此插入操作中,新的输入节点添加到双向链表的末尾;如果列表不为空。如果列表为空,则 head 将指向新节点。
算法
1. START 2. If the list is empty, add the node to the list and point the head to it. 3. If the list is not empty, find the last node of the list. 4. Create a link between the last node in the list and the new node. 5. The new node will point to NULL as it is the new last node. 6. END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> struct node { int data; int key; struct node *next; struct node *prev; }; //this link always point to first Link struct node *head = NULL; //this link always point to last Link struct node *last = NULL; struct node *current = NULL; //is list empty bool isEmpty(){ return head == NULL; } //display the doubly linked list void printList(){ struct node *ptr = head; while(ptr != NULL) { printf("(%d,%d) ",ptr->key,ptr->data); ptr = ptr->next; } } //insert link at the first location void insertFirst(int key, int data){ //create a link struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; if(isEmpty()) { //make it the last link last = link; } else { //update first prev link head->prev = link; } //point it to old first link link->next = head; //point first to new first link head = link; } //insert link at the last location void insertLast(int key, int data){ //create a link struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; if(isEmpty()) { //make it the last link last = link; } else { //make link a new last link last->next = link; //mark old last node as prev of new link link->prev = last; } //point last to new last node last = link; } void main(){ insertFirst(1,10); insertFirst(2,20); insertFirst(3,30); insertFirst(4,1); insertLast(5,40); insertLast(6,56); printf("\nDoubly Linked List: "); printList(); }
输出
Doubly Linked List: (4,1) (3,30) (2,20) (1,10) (5,40) (6,56)
#include <iostream> #include <cstring> #include <cstdlib> #include <cstdbool> struct node { int data; int key; struct node *next; struct node *prev; }; //this link always point to first Link struct node *head = NULL; //this link always point to last Link struct node *last = NULL; struct node *current = NULL; //is list empty bool isEmpty(){ return head == NULL; } //display the doubly linked list void printList(){ struct node *ptr = head; while(ptr != NULL) { printf("(%d,%d) ",ptr->key,ptr->data); ptr = ptr->next; } } //insert link at the first location void insertFirst(int key, int data){ //create a link struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; if(isEmpty()) { //make it the last link last = link; } else { //update first prev link head->prev = link; } //point it to old first link link->next = head; //point first to new first link head = link; } //insert link at the last location void insertLast(int key, int data){ //create a link struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; if(isEmpty()) { //make it the last link last = link; } else { //make link a new last link last->next = link; //mark old last node as prev of new link link->prev = last; } //point last to new last node last = link; } int main(){ insertFirst(1,10); insertFirst(2,20); insertFirst(3,30); insertFirst(4,1); insertLast(5,40); insertLast(6,56); printf("\nDoubly Linked List: "); printList(); return 0; }
输出
Doubly Linked List: (4,1) (3,30) (2,20) (1,10) (5,40) (6,56)
import java.util.*; class Node { public int data; public int key; public Node next; public Node prev; public Node(int data, int key) { this.data = data; this.key = key; this.next = null; this.prev = null; } } public class Main { static Node head = null; static Node last = null; static Node current = null; public static boolean isEmpty() { return head == null; } public static void printList() { Node ptr = head; while (ptr != null) { System.out.print("(" + ptr.key + "," + ptr.data + ") "); ptr = ptr.next; } } public static void insertFirst(int key, int data) { Node link = new Node(data, key); if (isEmpty()) { last = link; } else { head.prev = link; } link.next = head; head = link; } public static void insertLast(int key, int data) { Node link = new Node(data, key); if (isEmpty()) { last = link; } else { last.next = link; link.prev = last; } last = link; } public static void main(String[] args) { insertFirst(1,10); insertFirst(2,20); insertFirst(3,30); insertFirst(4,1); insertLast(5,40); insertLast(6,56); System.out.print("\nDoubly Linked List: "); printList(); } }
输出
Doubly Linked List: (4,1) (3,30) (2,20) (1,10) (5,40) (6,56)
class Node: def __init__(self, data=None, key=None): self.data = data self.key = key self.next = None self.prev = None head = None last = None current = None def isEmpty(): return head == None def printList(): ptr = head while ptr != None: print(f"({ptr.key},{ptr.data})", end=" ") ptr = ptr.next def insertFirst(key, data): global head, last link = Node(data, key) if isEmpty(): last = link else: head.prev = link link.next = head head = link def insertLast(key, data): global head, last link = Node(data, key) if isEmpty(): last = link else: last.next = link link.prev = last last = link insertFirst(1,10) insertFirst(2,20) insertFirst(3,30) insertFirst(4,1) insertLast(5,40) insertLast(6,56) print("\nDoubly Linked List: ", end="") printList()
输出
Doubly Linked List: (4,1) (3,30) (2,20) (1,10) (5,40) (6,56)
完整实现
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> struct node { int data; int key; struct node *next; struct node *prev; }; //this link always point to first Link struct node *head = NULL; //this link always point to last Link struct node *last = NULL; struct node *current = NULL; //is list empty bool isEmpty(){ return head == NULL; } //display the list in from first to last void displayForward(){ //start from the beginning struct node *ptr = head; //navigate till the end of the list printf("\n[ "); while(ptr != NULL) { printf("(%d,%d) ",ptr->key,ptr->data); ptr = ptr->next; } printf(" ]"); } //display the list from last to first void displayBackward(){ //start from the last struct node *ptr = last; //navigate till the start of the list printf("\n[ "); while(ptr != NULL) { //print data printf("(%d,%d) ",ptr->key,ptr->data); //move to next item ptr = ptr ->prev; printf(" "); } printf(" ]"); } //insert link at the first location void insertFirst(int key, int data){ //create a link struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; if(isEmpty()) { //make it the last link last = link; } else { //update first prev link head->prev = link; } //point it to old first link link->next = head; //point first to new first link head = link; } //insert link at the last location void insertLast(int key, int data){ //create a link struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; if(isEmpty()) { //make it the last link last = link; } else { //make link a new last link last->next = link; //mark old last node as prev of new link link->prev = last; } //point last to new last node last = link; } //delete first item struct node* deleteFirst(){ //save reference to first link struct node *tempLink = head; //if only one link if(head->next == NULL) { last = NULL; } else { head->next->prev = NULL; } head = head->next; //return the deleted link return tempLink; } //delete link at the last location struct node* deleteLast(){ //save reference to last link struct node *tempLink = last; //if only one link if(head->next == NULL) { head = NULL; } else { last->prev->next = NULL; } last = last->prev; //return the deleted link return tempLink; } //delete a link with given key struct node* delete(int key){ //start from the first link struct node* current = head; struct node* previous = NULL; //if list is empty if(head == NULL) { return NULL; } //navigate through list while(current->key != key) { //if it is last node if(current->next == NULL) { return NULL; } else { //store reference to current link previous = current; //move to next link current = current->next; } } //found a match, update the link if(current == head) { //change first to point to next link head = head->next; } else { //bypass the current link current->prev->next = current->next; } if(current == last) { //change last to point to prev link last = current->prev; } else { current->next->prev = current->prev; } return current; } bool insertAfter(int key, int newKey, int data){ //start from the first link struct node *current = head; //if list is empty if(head == NULL) { return false; } //navigate through list while(current->key != key) { //if it is last node if(current->next == NULL) { return false; } else { //move to next link current = current->next; } } //create a link struct node *newLink = (struct node*) malloc(sizeof(struct node)); newLink->key = key; newLink->data = data; if(current == last) { newLink->next = NULL; last = newLink; } else { newLink->next = current->next; current->next->prev = newLink; } newLink->prev = current; current->next = newLink; return true; } int main(){ insertFirst(1,10); insertFirst(2,20); insertFirst(3,30); insertFirst(4,1); insertFirst(5,40); insertFirst(6,56); printf("\nList (First to Last): "); displayForward(); printf("\n"); printf("\nList (Last to first): "); displayBackward(); printf("\nList , after deleting first record: "); deleteFirst(); displayForward(); printf("\nList , after deleting last record: "); deleteLast(); displayForward(); printf("\nList , insert after key(4) : "); insertAfter(4,7, 13); displayForward(); printf("\nList , after delete key(4) : "); delete(4); displayForward(); }
输出
List (First to Last): [ (6,56) (5,40) (4,1) (3,30) (2,20) (1,10) ] List (Last to first): [ (1,10) (2,20) (3,30) (4,1) (5,40) (6,56) ] List , after deleting first record: [ (5,40) (4,1) (3,30) (2,20) (1,10) ] List , after deleting last record: [ (5,40) (4,1) (3,30) (2,20) ] List , insert after key(4) : [ (5,40) (4,1) (4,13) (3,30) (2,20) ] List , after delete key(4) : [ (5,40) (4,13) (3,30) (2,20) ]
#include <iostream> #include <cstring> #include <cstdlib> #include <cstdbool> using namespace std; struct node { int data; int key; struct node *next; struct node *prev; }; //this link always point to first Link struct node *head = NULL; //this link always point to last Link struct node *last = NULL; struct node *current = NULL; //is list empty bool isEmpty(){ return head == NULL; } //display the list in from first to last void displayForward(){ //start from the beginning struct node *ptr = head; //navigate till the end of the list cout << "\n[ "; while(ptr != NULL) { cout << "(" << ptr->key << "," << ptr->data << ")"; ptr = ptr->next; } cout << " ]" << endl; } //display the list from last to first void displayBackward(){ //start from the last struct node *ptr = last; //navigate till the start of the list cout << "\n[ "; while(ptr != NULL) { //print data cout << "(" << ptr->key << "," << ptr->data << ")"; //move to next item ptr = ptr ->prev; cout << " "; } cout << " ]" << endl; } //insert link at the first location void insertFirst(int key, int data){ //create a link struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; if(isEmpty()) { //make it the last link last = link; } else { //update first prev link head->prev = link; } //point it to old first link link->next = head; //point first to new first link head = link; } //insert link at the last location void insertLast(int key, int data){ //create a link struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; if(isEmpty()) { //make it the last link last = link; } else { //make link a new last link last->next = link; //mark old last node as prev of new link link->prev = last; } //point last to new last node last = link; } //delete first item struct node* deleteFirst(){ //save reference to first link struct node *tempLink = head; //if only one link if(head->next == NULL) { last = NULL; } else { head->next->prev = NULL; } head = head->next; //return the deleted link return tempLink; } //delete link at the last location struct node* deleteLast(){ //save reference to last link struct node *tempLink = last; //if only one link if(head->next == NULL) { head = NULL; } else { last->prev->next = NULL; } last = last->prev; //return the deleted link return tempLink; } //delete a link with given key struct node* deletenode(int key){ //start from the first link struct node* current = head; struct node* previous = NULL; //if list is empty if(head == NULL) { return NULL; } //navigate through list while(current->key != key) { //if it is last node if(current->next == NULL) { return NULL; } else { //store reference to current link previous = current; //move to next link current = current->next; } } //found a match, update the link if(current == head) { //change first to point to next link head = head->next; } else { //bypass the current link current->prev->next = current->next; } if(current == last) { //change last to point to prev link last = current->prev; } else { current->next->prev = current->prev; } return current; } bool insertAfter(int key, int newKey, int data){ //start from the first link struct node *current = head; //if list is empty if(head == NULL) { return false; } //navigate through list while(current->key != key) { //if it is last node if(current->next == NULL) { return false; } else { //move to next link current = current->next; } } //create a link struct node *newLink = (struct node*) malloc(sizeof(struct node)); newLink->key = key; newLink->data = data; if(current == last) { newLink->next = NULL; last = newLink; } else { newLink->next = current->next; current->next->prev = newLink; } newLink->prev = current; current->next = newLink; return true; } int main(){ insertFirst(1,10); insertFirst(2,20); insertFirst(3,30); insertFirst(4,1); insertFirst(5,40); insertFirst(6,56); printf("\nList (First to Last): "); displayForward(); printf("\n"); printf("\nList (Last to first): "); displayBackward(); printf("\nList , after deleting first record: "); deleteFirst(); displayForward(); printf("\nList , after deleting last record: "); deleteLast(); displayForward(); printf("\nList , insert after key(4) : "); insertAfter(4, 7, 13); displayForward(); printf("\nList , after delete key(4) : "); deletenode(4); displayForward(); return 0; }
输出
List (First to Last): [ (6, 56) (5, 40) (4, 1) (3, 30) (2, 20) (1, 10) ] List (Last to First): [ (1, 10) (2, 20) (3, 30) (4, 1) (5, 40) (6, 56) ] List, after deleting first record: [ (5, 40) (4, 1) (3, 30) (2, 20) (1, 10) ] List, after deleting last record: [ (5, 40) (4, 1) (3, 30) (2, 20) ] List, insert after key(4): [ (5, 40) (4, 1) (7, 13) (3, 30) (2, 20) ] List, after delete key(4): [ (5, 40) (7, 13) (3, 30) (2, 20) ]
class Node { int data; int key; Node next; Node prev; public Node(int key, int data) { this.key = key; this.data = data; this.next = null; this.prev = null; } } class DoublyLinkedList { Node head; Node last; boolean isEmpty() { return head == null; } void displayForward() { Node ptr = head; System.out.print("[ "); while (ptr != null) { System.out.print("(" + ptr.key + "," + ptr.data + ") "); ptr = ptr.next; } System.out.println("]"); } void displayBackward() { Node ptr = last; System.out.print("[ "); while (ptr != null) { System.out.print("(" + ptr.key + "," + ptr.data + ") "); ptr = ptr.prev; } System.out.println("]"); } void insertFirst(int key, int data) { Node link = new Node(key, data); if (isEmpty()) { last = link; } else { head.prev = link; } link.next = head; head = link; } void insertLast(int key, int data) { Node link = new Node(key, data); if (isEmpty()) { last = link; } else { last.next = link; link.prev = last; } last = link; } Node deleteFirst() { if (isEmpty()) { return null; } Node tempLink = head; if (head.next == null) { last = null; } else { head.next.prev = null; } head = head.next; return tempLink; } Node deleteLast() { if (isEmpty()) { return null; } Node tempLink = last; if (head.next == null) { head = null; } else { last.prev.next = null; } last = last.prev; return tempLink; } Node delete(int key) { Node current = head; Node previous = null; if (head == null) { return null; } while (current.key != key) { if (current.next == null) { return null; } else { previous = current; current = current.next; } } if (current == head) { head = head.next; } else { current.prev.next = current.next; } if (current == last) { last = current.prev; } else { current.next.prev = current.prev; } return current; } boolean insertAfter(int key, int newKey, int data) { Node current = head; if (head == null) { return false; } while (current.key != key) { if (current.next == null) { return false; } else { current = current.next; } } Node newLink = new Node(newKey, data); if (current == last) { newLink.next = null; last = newLink; } else { newLink.next = current.next; current.next.prev = newLink; } newLink.prev = current; current.next = newLink; return true; } } public class Main { public static void main(String[] args) { DoublyLinkedList dll = new DoublyLinkedList(); dll.insertFirst(1, 10); dll.insertFirst(2, 20); dll.insertFirst(3, 30); dll.insertFirst(4, 1); dll.insertFirst(5, 40); dll.insertFirst(6, 56); System.out.println("List (First to Last):"); dll.displayForward(); System.out.println(); System.out.println("List (Last to First):"); dll.displayBackward(); System.out.println("List, after deleting first record:"); dll.deleteFirst(); dll.displayForward(); System.out.println("List, after deleting last record:"); dll.deleteLast(); dll.displayForward(); System.out.println("List, insert after key(4):"); dll.insertAfter(4, 7, 13); dll.displayForward(); System.out.println("List, after delete key(4):"); dll.delete(4); dll.displayForward(); } }
输出
List (First to Last): [ (6, 56) (5, 40) (4, 1) (3, 30) (2, 20) (1, 10) ] List (Last to First): [ (1, 10) (2, 20) (3, 30) (4, 1) (5, 40) (6, 56) ] List, after deleting first record: [ (5, 40) (4, 1) (3, 30) (2, 20) (1, 10) ] List, after deleting last record: [ (5, 40) (4, 1) (3, 30) (2, 20) ] List, insert after key(4): [ (5, 40) (4, 1) (7, 13) (3, 30) (2, 20) ] List, after delete key(4): [ (5, 40) (7, 13) (3, 30) (2, 20) ]
class Node: def __init__(self, key, data): self.key = key self.data = data self.next = None self.prev = None class DoublyLinkedList: def __init__(self): self.head = None self.last = None def is_empty(self): return self.head is None def display_forward(self): ptr = self.head print("[", end=" ") while ptr: print("({}, {})".format(ptr.key, ptr.data), end=" ") ptr = ptr.next print("]") def display_backward(self): ptr = self.last print("[", end=" ") while ptr: print("({}, {})".format(ptr.key, ptr.data), end=" ") ptr = ptr.prev print("]") def insert_first(self, key, data): link = Node(key, data) if self.is_empty(): self.last = link else: self.head.prev = link link.next = self.head self.head = link def insert_last(self, key, data): link = Node(key, data) if self.is_empty(): self.last = link else: self.last.next = link link.prev = self.last self.last = link def delete_first(self): if self.is_empty(): return None temp_link = self.head if self.head.next is None: self.last = None else: self.head.next.prev = None self.head = self.head.next return temp_link def delete_last(self): if self.is_empty(): return None temp_link = self.last if self.head.next is None: self.head = None else: self.last.prev.next = None self.last = self.last.prev return temp_link def delete(self, key): current = self.head while current and current.key != key: current = current.next if current is None: return None if current == self.head: self.head = self.head.next else: current.prev.next = current.next if current == self.last: self.last = current.prev else: current.next.prev = current.prev return current def insert_after(self, key, new_key, data): current = self.head while current and current.key != key: current = current.next if current is None: return False new_link = Node(new_key, data) if current == self.last: new_link.next = None self.last = new_link else: new_link.next = current.next current.next.prev = new_link new_link.prev = current current.next = new_link return True # Example usage dll = DoublyLinkedList() dll.insert_first(1, 10) dll.insert_first(2, 20) dll.insert_first(3, 30) dll.insert_first(4, 1) dll.insert_first(5, 40) dll.insert_first(6, 56) print("List (First to Last):") dll.display_forward() print() print("List (Last to First):") dll.display_backward() print("List, after deleting first record:") dll.delete_first() dll.display_forward() print("List, after deleting last record:") dll.delete_last() dll.display_forward() print("List, insert after key(4):") dll.insert_after(4, 7, 13) dll.display_forward() print("List, after delete key(4):") dll.delete(4) dll.display_forward()
输出
List (First to Last): [ (6, 56) (5, 40) (4, 1) (3, 30) (2, 20) (1, 10) ] List (Last to First): [ (1, 10) (2, 20) (3, 30) (4, 1) (5, 40) (6, 56) ] List, after deleting first record: [ (5, 40) (4, 1) (3, 30) (2, 20) (1, 10) ] List, after deleting last record: [ (5, 40) (4, 1) (3, 30) (2, 20) ] List, insert after key(4): [ (5, 40) (4, 1) (7, 13) (3, 30) (2, 20) ] List, after delete key(4): [ (5, 40) (7, 13) (3, 30) (2, 20) ]
循环链表数据结构
循环链表是链表的一种变体,其中第一个元素指向最后一个元素,最后一个元素指向第一个元素。单向链表和双向链表都可以转换为循环链表。
单向循环链表
在单向链表中,最后一个节点的 next 指针指向第一个节点。
双向循环链表
在双向链表中,最后一个节点的 next 指针指向第一个节点,第一个节点的 prev 指针指向最后一个节点,从而形成双向循环。
根据以上说明,以下是要考虑的重要事项。
在单向和双向链表的两种情况下,最后一个链接的 next 都指向列表的第一个链接。
在双向链表的情况下,第一个链接的 prev 指向列表的最后一个链接。
基本操作
以下是循环列表支持的重要操作。
插入 (insert) − 在列表开头插入一个元素。
删除 (delete) − 从列表开头删除一个元素。
显示 (display) − 显示列表。
插入操作
循环链表的插入操作只在列表开头插入元素。这与通常的单向和双向链表不同,因为此列表没有特定的起点和终点。插入操作可以在开头进行,或者在列表中的特定节点(或给定位置)之后进行。
算法
1. START 2. Check if the list is empty 3. If the list is empty, add the node and point the head to this node 4. If the list is not empty, link the existing head as the next node to the new node. 5. Make the new node as the new head. 6. END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> struct node { int data; int key; struct node *next; }; struct node *head = NULL; struct node *current = NULL; bool isEmpty(){ return head == NULL; } //insert link at the first location void insertFirst(int key, int data){ //create a link struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; if (isEmpty()) { head = link; head->next = head; } else { //point it to old first node link->next = head; //point first to new first node head = link; } } //display the list void printList(){ struct node *ptr = head; printf("\n[ "); //start from the beginning if(head != NULL) { while(ptr->next != ptr) { printf("(%d,%d) ",ptr->key,ptr->data); ptr = ptr->next; } } printf(" ]"); } void main(){ insertFirst(1,10); insertFirst(2,20); insertFirst(3,30); insertFirst(4,1); insertFirst(5,40); insertFirst(6,56); printf("Circular Linked List: "); //print list printList(); }
输出
Circular Linked List: [ (6,56) (5,40) (4,1) (3,30) (2,20) ]
#include <iostream> #include <cstring> #include <cstdlib> #include <cstdbool> struct node { int data; int key; struct node *next; }; struct node *head = NULL; struct node *current = NULL; bool isEmpty(){ return head == NULL; } //insert link at the first location void insertFirst(int key, int data){ //create a link struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; if (isEmpty()) { head = link; head->next = head; } else { //point it to old first node link->next = head; //point first to new first node head = link; } } //display the list void printList(){ struct node *ptr = head; printf("\n[ "); //start from the beginning if(head != NULL) { while(ptr->next != ptr) { printf("(%d,%d) ",ptr->key,ptr->data); ptr = ptr->next; } } printf(" ]"); } int main(){ insertFirst(1,10); insertFirst(2,20); insertFirst(3,30); insertFirst(4,1); insertFirst(5,40); insertFirst(6,56); printf("Circular Linked List: "); //print list printList(); return 0; }
输出
Circular Linked List: [ (6,56) (5,40) (4,1) (3,30) (2,20) ]
//Java program for circular link list import java.util.*; class Node { int data; int key; Node next; } public class Main { static Node head = null; static Node current = null; static boolean isEmpty() { return head == null; } //insert link at the first location static void insertFirst(int key, int data) { //create a link Node link = new Node(); link.key = key; link.data = data; if (isEmpty()) { head = link; head.next = head; } else { //point it to old first node link.next = head; //point first to new first node head = link; } } //display the list static void printList() { Node ptr = head; System.out.print("\n[ "); //start from the beginning if (head != null) { while (ptr.next != ptr) { System.out.print("(" + ptr.key + "," + ptr.data + ") "); ptr = ptr.next; } } System.out.print(" ]"); } public static void main(String[] args) { insertFirst(1, 10); insertFirst(2, 20); insertFirst(3, 30); insertFirst(4, 1); insertFirst(5, 40); insertFirst(6, 56); System.out.print("Circular Linked List: "); //print list printList(); } }
输出
Circular Linked List: [ (6,56) (5,40) (4,1) (3,30) (2,20) ]
#python program for circular linked list class Node: def __init__(self, key, data): self.key = key self.data = data self.next = None head = None current = None def is_empty(): return head is None #insert link at the first location def insert_first(key, data): #create a link global head new_node = Node(key, data) if is_empty(): head = new_node head.next = head else: #point it to old first node new_node.next = head #point first to the new first node head = new_node #display the list def print_list(): global head ptr = head print("[", end=" ") #start from the beginning if head is not None: while ptr.next != ptr: print("({}, {})".format(ptr.key, ptr.data), end=" ") ptr = ptr.next print("]") insert_first(1, 10) insert_first(2, 20) insert_first(3, 30) insert_first(4, 1) insert_first(5, 40) insert_first(6, 56) #printlist print("Circular Linked List: ") print_list()
输出
Circular Linked List: [ (6,56) (5,40) (4,1) (3,30) (2,20) ]
删除操作
循环链表中的删除操作会从列表中删除某个节点。这种类型的列表中的删除操作可以在开头、给定位置或结尾进行。
算法
1. START 2. If the list is empty, then the program is returned. 3. If the list is not empty, we traverse the list using a current pointer that is set to the head pointer and create another pointer previous that points to the last node. 4. Suppose the list has only one node, the node is deleted by setting the head pointer to NULL. 5. If the list has more than one node and the first node is to be deleted, the head is set to the next node and the previous is linked to the new head. 6. If the node to be deleted is the last node, link the preceding node of the last node to head node. 7. If the node is neither first nor last, remove the node by linking its preceding node to its succeeding node. 8. END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> struct node { int data; int key; struct node *next; }; struct node *head = NULL; struct node *current = NULL; bool isEmpty(){ return head == NULL; } //insert link at the first location void insertFirst(int key, int data){ //create a link struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; if (isEmpty()) { head = link; head->next = head; } else { //point it to old first node link->next = head; //point first to new first node head = link; } } //delete first item struct node * deleteFirst(){ //save reference to first link struct node *tempLink = head; if(head->next == head) { head = NULL; return tempLink; } //mark next to first link as first head = head->next; //return the deleted link return tempLink; } //display the list void printList(){ struct node *ptr = head; //start from the beginning if(head != NULL) { while(ptr->next != ptr) { printf("(%d,%d) ",ptr->key,ptr->data); ptr = ptr->next; } } } void main(){ insertFirst(1,10); insertFirst(2,20); insertFirst(3,30); insertFirst(4,1); insertFirst(5,40); insertFirst(6,56); printf("Circular Linked List: "); //print list printList(); deleteFirst(); printf("\nList after deleting the first item: "); printList(); }
输出
Circular Linked List: (6,56) (5,40) (4,1) (3,30) (2,20) List after deleting the first item: (5,40) (4,1) (3,30) (2,20)
#include <iostream> #include <cstring> #include <cstdlib> #include <cstdbool> struct node { int data; int key; struct node *next; }; struct node *head = NULL; struct node *current = NULL; bool isEmpty(){ return head == NULL; } //insert link at the first location void insertFirst(int key, int data){ //create a link struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; if (isEmpty()) { head = link; head->next = head; } else { //point it to old first node link->next = head; //point first to new first node head = link; } } //delete first item struct node * deleteFirst(){ //save reference to first link struct node *tempLink = head; if(head->next == head) { head = NULL; return tempLink; } //mark next to first link as first head = head->next; //return the deleted link return tempLink; } //display the list void printList(){ struct node *ptr = head; //start from the beginning if(head != NULL) { while(ptr->next != ptr) { printf("(%d,%d) ",ptr->key,ptr->data); ptr = ptr->next; } } } int main(){ insertFirst(1,10); insertFirst(2,20); insertFirst(3,30); insertFirst(4,1); insertFirst(5,40); insertFirst(6,56); printf("Circular Linked List: "); //print list printList(); deleteFirst(); printf("\nList after deleting the first item: "); printList(); return 0; }
输出
Circular Linked List: (6,56) (5,40) (4,1) (3,30) (2,20) List after deleting the first item: (5,40) (4,1) (3,30) (2,20)
//Java program for circular linked list import java.util.*; public class Main { static class Node { int data; int key; Node next; } static Node head = null; static Node current = null; static boolean isEmpty() { return head == null; } //insert link at the first location static void insertFirst(int key, int data) { //create a link Node link = new Node(); link.key = key; link.data = data; if (isEmpty()) { head = link; head.next = head; } else { //point it to old first node link.next = head; //point first to new first node head = link; } } //delete first item static Node deleteFirst() { //save reference to first link Node tempLink = head; if (head.next == head) { head = null; return tempLink; } //mark next to first link as first head = head.next; //return the deleted link return tempLink; } //display the list static void printList() { Node ptr = head; //start from the beginning if (head != null) { while (ptr.next != ptr) { System.out.printf("(%d,%d) ", ptr.key, ptr.data); ptr = ptr.next; } } } public static void main(String[] args) { insertFirst(1, 10); insertFirst(2, 20); insertFirst(3, 30); insertFirst(4, 1); insertFirst(5, 40); insertFirst(6, 56); System.out.print("Circular Linked List: "); //print list printList(); deleteFirst(); } }
输出
Circular Linked List: (6,56) (5,40) (4,1) (3,30) (2,20) List after deleting the first item: (5,40) (4,1) (3,30) (2,20)
#python program for circular linked list class Node: def __init__(self, key, data): self.key = key self.data = data self.next = None head = None current = None def is_empty(): return head is None #insert link at the first location def insert_first(key, data): #create a link global head new_node = Node(key, data) if is_empty(): head = new_node head.next = head else: #point it to old first node new_node.next = head #point first to the new first node head = new_node def print_list(): global head ptr = head print("[", end=" ") #start from the beginning if head is not None: while ptr.next != ptr: print("({}, {})".format(ptr.key, ptr.data), end=" ") ptr = ptr.next print("]") def delete_first(): global head temp_link = head if head.next == head: head = None return temp_link head = head.next return temp_link insert_first(1, 10) insert_first(2, 20) insert_first(3, 30) insert_first(4, 1) insert_first(5, 40) insert_first(6, 56) #printlist print("Circular Linked List: ") print_list() delete_first() print("\nList after deleting the first item: ") print_list();
输出
Circular Linked List: (6,56) (5,40) (4,1) (3,30) (2,20) List after deleting the first item: (5,40) (4,1) (3,30) (2,20)
显示列表操作
显示列表操作访问列表中的每个节点,并将它们全部打印到输出中。
算法
1. START 2. Walk through all the nodes of the list and print them 3. END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> struct node { int data; int key; struct node *next; }; struct node *head = NULL; struct node *current = NULL; bool isEmpty(){ return head == NULL; } //insert link at the first location void insertFirst(int key, int data){ //create a link struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; if (isEmpty()) { head = link; head->next = head; } else { //point it to old first node link->next = head; //point first to new first node head = link; } } //display the list void printList(){ struct node *ptr = head; printf("\n[ "); //start from the beginning if(head != NULL) { while(ptr->next != ptr) { printf("(%d,%d) ",ptr->key,ptr->data); ptr = ptr->next; } } printf(" ]"); } void main(){ insertFirst(1,10); insertFirst(2,20); insertFirst(3,30); insertFirst(4,1); insertFirst(5,40); insertFirst(6,56); printf("Circular Linked List: "); //print list printList(); }
输出
Circular Linked List: [ (6,56) (5,40) (4,1) (3,30) (2,20) ]
#include <iostream> #include <cstring> #include <cstdlib> #include <cstdbool> struct node { int data; int key; struct node *next; }; struct node *head = NULL; struct node *current = NULL; bool isEmpty(){ return head == NULL; } //insert link at the first location void insertFirst(int key, int data){ //create a link struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; if (isEmpty()) { head = link; head->next = head; } else { //point it to old first node link->next = head; //point first to new first node head = link; } } //display the list void printList(){ struct node *ptr = head; printf("\n[ "); //start from the beginning if(head != NULL) { while(ptr->next != ptr) { printf("(%d,%d) ",ptr->key,ptr->data); ptr = ptr->next; } } printf(" ]"); } int main(){ insertFirst(1,10); insertFirst(2,20); insertFirst(3,30); insertFirst(4,1); insertFirst(5,40); insertFirst(6,56); printf("Circular Linked List: "); //print list printList(); return 0; }
输出
Circular Linked List: [ (6,56) (5,40) (4,1) (3,30) (2,20) ]
//Java program for circular link list import java.util.*; class Node { int data; int key; Node next; } public class Main { static Node head = null; static Node current = null; static boolean isEmpty() { return head == null; } //insert link at the first location static void insertFirst(int key, int data) { //create a link Node link = new Node(); link.key = key; link.data = data; if (isEmpty()) { head = link; head.next = head; } else { //point it to old first node link.next = head; //point first to new first node head = link; } } //display the list static void printList() { Node ptr = head; System.out.print("\n[ "); //start from the beginning if (head != null) { while (ptr.next != ptr) { System.out.print("(" + ptr.key + "," + ptr.data + ") "); ptr = ptr.next; } } System.out.print(" ]"); } public static void main(String[] args) { insertFirst(1, 10); insertFirst(2, 20); insertFirst(3, 30); insertFirst(4, 1); insertFirst(5, 40); insertFirst(6, 56); System.out.print("Circular Linked List: "); //print list printList(); } }
输出
Circular Linked List: [ (6,56) (5,40) (4,1) (3,30) (2,20) ]
#python program for circular linked list class Node: def __init__(self, key, data): self.key = key self.data = data self.next = None head = None current = None def is_empty(): return head is None #insert link at the first location def insert_first(key, data): #create a link global head new_node = Node(key, data) if is_empty(): head = new_node head.next = head else: #point it to old first node new_node.next = head #point first to the new first node head = new_node #display the list def print_list(): global head ptr = head print("[", end=" ") #start from the beginning if head is not None: while ptr.next != ptr: print("({}, {})".format(ptr.key, ptr.data), end=" ") ptr = ptr.next print("]") insert_first(1, 10) insert_first(2, 20) insert_first(3, 30) insert_first(4, 1) insert_first(5, 40) insert_first(6, 56) #printlist print("Circular Linked List: ") print_list()
输出
Circular Linked List: [ (6,56) (5,40) (4,1) (3,30) (2,20) ]
完整实现
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> struct node { int data; int key; struct node *next; }; struct node *head = NULL; struct node *current = NULL; bool isEmpty(){ return head == NULL; } int length(){ int length = 0; //if list is empty if(head == NULL) { return 0; } current = head->next; while(current != head) { length++; current = current->next; } return length; } //insert link at the first location void insertFirst(int key, int data){ //create a link struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; if (isEmpty()) { head = link; head->next = head; } else { //point it to old first node link->next = head; //point first to new first node head = link; } } //delete first item struct node * deleteFirst(){ //save reference to first link struct node *tempLink = head; if(head->next == head) { head = NULL; return tempLink; } //mark next to first link as first head = head->next; //return the deleted link return tempLink; } //display the list void printList(){ struct node *ptr = head; printf("\n[ "); //start from the beginning if(head != NULL) { while(ptr->next != ptr) { printf("(%d,%d) ",ptr->key,ptr->data); ptr = ptr->next; } } printf(" ]"); } int main(){ insertFirst(1,10); insertFirst(2,20); insertFirst(3,30); insertFirst(4,1); insertFirst(5,40); insertFirst(6,56); printf("Original List: "); //print list printList(); while(!isEmpty()) { struct node *temp = deleteFirst(); printf("\nDeleted value:"); printf("(%d,%d) ",temp->key,temp->data); } printf("\nList after deleting all items: "); printList(); }
输出
Original List: [ (6,56) (5,40) (4,1) (3,30) (2,20) ] Deleted value:(6,56) Deleted value:(5,40) Deleted value:(4,1) Deleted value:(3,30) Deleted value:(2,20) Deleted value:(1,10) List after deleting all items: [ ]
#include <iostream> #include <cstring> #include <cstdlib> #include <cstdbool> using namespace std; struct node { int data; int key; struct node *next; }; struct node *head = NULL; struct node *current = NULL; bool isEmpty(){ return head == NULL; } int length(){ int length = 0; //if list is empty if(head == NULL) { return 0; } current = head->next; while(current != head) { length++; current = current->next; } return length; } //insert link at the first location void insertFirst(int key, int data){ //create a link struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; if (isEmpty()) { head = link; head->next = head; } else { //point it to old first node link->next = head; //point first to new first node head = link; } } //delete first item struct node * deleteFirst(){ //save reference to first link struct node *tempLink = head; if(head->next == head) { head = NULL; return tempLink; } //mark next to first link as first head = head->next; //return the deleted link return tempLink; } //display the list void printList(){ struct node *ptr = head; cout << "\n[ "; //start from the beginning if(head != NULL) { while(ptr->next != ptr) { cout << "(" << ptr->key << "," << ptr->data << ") "; ptr = ptr->next; } } cout << " ]"; } int main(){ insertFirst(1,10); insertFirst(2,20); insertFirst(3,30); insertFirst(4,1); insertFirst(5,40); insertFirst(6,56); cout << "Original List: "; //print list printList(); while(!isEmpty()) { struct node *temp = deleteFirst(); cout << "\n Deleted value:"; cout << "(" << temp->key << "," << temp->data << ") "; } cout << "\n List after deleting all items: "; printList(); return 0; }
输出
Original List: [ (6,56) (5,40) (4,1) (3,30) (2,20) ] Deleted value:(6,56) Deleted value:(5,40) Deleted value:(4,1) Deleted value:(3,30) Deleted value:(2,20) Deleted value:(1,10) List after deleting all items: [ ]
class Node { int data; int key; Node next; Node(int key, int data) { this.key = key; this.data = data; this.next = null; } } public class LinkedList { private Node head; private Node current; boolean isEmpty() { return head == null; } int length() { int length = 0; //if list is empty if (head == null) { return 0; } current = head.next; while (current != head) { length++; current = current.next; } return length; } //insert link at the first location void insertFirst(int key, int data) { //create a link Node link = new Node(key, data); if (isEmpty()) { head = link; head.next = head; } else { //point it to old first node link.next = head; //point first to new first node head = link; } } //delete first item Node deleteFirst() { if (head.next == head) { //save reference to first link Node tempLink = head; head = null; return tempLink; } Node tempLink = head; //mark next to first link as first head = head.next; //return the deleted link return tempLink; } //display the list void printList() { Node ptr = head; System.out.print("\n[ "); //start from the beginning if (head != null) { while (ptr.next != ptr) { System.out.print("(" + ptr.key + "," + ptr.data + ") "); ptr = ptr.next; } } System.out.print(" ]"); } public static void main(String[] args) { LinkedList linkedList = new LinkedList(); linkedList.insertFirst(1, 10); linkedList.insertFirst(2, 20); linkedList.insertFirst(3, 30); linkedList.insertFirst(4, 1); linkedList.insertFirst(5, 40); linkedList.insertFirst(6, 56); System.out.print("Original List: "); linkedList.printList(); //print list while (!linkedList.isEmpty()) { Node temp = linkedList.deleteFirst(); System.out.println("\nDeleted value: (" + temp.key + "," + temp.data + ")"); } System.out.print("\nList after deleting all items: "); linkedList.printList(); } }
输出
Original List: [ (6,56) (5,40) (4,1) (3,30) (2,20) ] Deleted value: (6,56) Deleted value: (5,40) Deleted value: (4,1) Deleted value: (3,30) Deleted value: (2,20) Deleted value: (1,10) List after deleting all items: [ ]
class Node: def __init__(self, key, data): self.key = key self.data = data self.next = None class LinkedList: def __init__(self): self.head = None self.current = None def is_empty(self): return self.head is None def length(self): length = 0 # If list is empty if self.head is None: return 0 self.current = self.head.next while self.current != self.head: length += 1 self.current = self.current.next return length # insert link at the first location def insert_first(self, key, data): # create a link new_node = Node(key, data) if self.is_empty(): self.head = new_node self.head.next = self.head else: # point it to old first node new_node.next = self.head # point first to new first node self.head = new_node # delete first item def delete_first(self): # save reference to first link if self.head.next == self.head: temp_link = self.head self.head = None return temp_link # mark next to first link as first temp_link = self.head self.head = self.head.next # return the deleted link return temp_link # Diplay the list def print_list(self): ptr = self.head print("[", end=" ") # start from the beginning if self.head is not None: while ptr.next != ptr: print("({}, {})".format(ptr.key, ptr.data), end=" ") ptr = ptr.next print("]") # Main function if __name__ == '__main__': linked_list = LinkedList() linked_list.insert_first(1, 10) linked_list.insert_first(2, 20) linked_list.insert_first(3, 30) linked_list.insert_first(4, 1) linked_list.insert_first(5, 40) linked_list.insert_first(6, 56) print("Original List: ", end="") linked_list.print_list() while not linked_list.is_empty(): temp = linked_list.delete_first() print("\nDeleted value: ({}, {})".format(temp.key, temp.data)) # print list print("List after deleting all items: ", end="") linked_list.print_list()
输出
Original List: [ (6, 56) (5, 40) (4, 1) (3, 30) (2, 20) ] Deleted value: (6, 56) Deleted value: (5, 40) Deleted value: (4, 1) Deleted value: (3, 30) Deleted value: (2, 20)Deleted value: (1, 10) List after deleting all items: [ ]
栈数据结构
栈是一种抽象数据类型 (ADT),在大多数编程语言中被广泛使用。它之所以被称为栈,是因为它具有与现实世界中的栈类似的操作,例如 – 一叠卡片或一堆盘子等。
栈遵循 LIFO(后进先出)结构,其中最后插入的元素将是第一个被删除的元素。
栈的表示
栈 ADT 仅允许在一端进行所有数据操作。在任何给定时间,我们只能访问栈的顶部元素。
下图描述了一个栈及其操作:
栈可以通过数组、结构体、指针和链表来实现。栈可以是固定大小的,也可以具有动态调整大小的功能。在这里,我们将使用数组来实现栈,这使得它成为一个固定大小的栈实现。
栈的基本操作
栈操作通常用于栈 ADT 的初始化、使用和反初始化。
栈 ADT 中最基本的操作包括:push()、pop()、peek()、isFull()、isEmpty()。这些都是内置操作,用于执行数据操作并检查栈的状态。
栈使用指针始终指向栈中最顶部的元素,因此称为顶部 (top) 指针。
插入:push()
push() 是一种将元素插入栈的操作。以下是更简单地描述 push() 操作的算法。
算法
1 − Checks if the stack is full. 2 − If the stack is full, produces an error and exit. 3 − If the stack is not full, increments top to point next empty space. 4 − Adds data element to the stack location, where top is pointing. 5 − Returns success.
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> int MAXSIZE = 8; int stack[8]; int top = -1; /* Check if the stack is full*/ int isfull(){ if(top == MAXSIZE) return 1; else return 0; } /* Function to insert into the stack */ int push(int data){ if(!isfull()) { top = top + 1; stack[top] = data; } else { printf("Could not insert data, Stack is full.\n"); } } /* Main function */ int main(){ int i; push(44); push(10); push(62); push(123); push(15); printf("Stack Elements: \n"); // print stack data for(i = 0; i < 8; i++) { printf("%d ", stack[i]); } return 0; }
输出
Stack Elements: 44 10 62 123 15 0 0 0
#include <iostream> int MAXSIZE = 8; int stack[8]; int top = -1; /* Check if the stack is full*/ int isfull(){ if(top == MAXSIZE) return 1; else return 0; } /* Function to insert into the stack */ int push(int data){ if(!isfull()) { top = top + 1; stack[top] = data; } else { printf("Could not insert data, Stack is full.\n"); } } /* Main function */ int main(){ int i; push(44); push(10); push(62); push(123); push(15); printf("Stack Elements: \n"); // print stack data for(i = 0; i < 8; i++) { printf("%d ", stack[i]); } return 0; }
输出
Stack Elements: 44 10 62 123 15 0 0 0
import java.io.*; import java.util.*; // util imports the stack class public class StackExample { public static void main (String[] args) { Stack<Integer> stk = new Stack<Integer>(); // inserting elements into the stack stk.push(52); stk.push(19); stk.push(33); stk.push(14); stk.push(6); System.out.print("The stack is: " + stk); } }
输出
The stack is: [52, 19, 33, 14, 6]
class Stack: def __init__(self): self.stack = [] def __str__(self): return str(self.stack) def push(self, data): if data not in self.stack: self.stack.append(data) return True else: return False stk = Stack() stk.push(1) stk.push(2) stk.push(3) stk.push(4) stk.push(5) print("Stack Elements:") print(stk)
输出
Stack Elements: [1, 2, 3, 4, 5]
注意 - 在 Java 中,我们使用内置方法push()来执行此操作。
删除:pop()
pop() 是一种数据操作,用于从栈中删除元素。以下伪代码更简单地描述了 pop() 操作。
算法
1 − Checks if the stack is empty. 2 − If the stack is empty, produces an error and exit. 3 − If the stack is not empty, accesses the data element at which top is pointing. 4 − Decreases the value of top by 1. 5 − Returns success.
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> int MAXSIZE = 8; int stack[8]; int top = -1; /* Check if the stack is empty */ int isempty(){ if(top == -1) return 1; else return 0; } /* Check if the stack is full*/ int isfull(){ if(top == MAXSIZE) return 1; else return 0; } /* Function to delete from the stack */ int pop(){ int data; if(!isempty()) { data = stack[top]; top = top - 1; return data; } else { printf("Could not retrieve data, Stack is empty.\n"); } } /* Function to insert into the stack */ int push(int data){ if(!isfull()) { top = top + 1; stack[top] = data; } else { printf("Could not insert data, Stack is full.\n"); } } /* Main function */ int main(){ int i; push(44); push(10); push(62); push(123); push(15); printf("Stack Elements: \n"); // print stack data for(i = 0; i < 8; i++) { printf("%d ", stack[i]); } /*printf("Element at top of the stack: %d\n" ,peek());*/ printf("\nElements popped: \n"); // print stack data while(!isempty()) { int data = pop(); printf("%d ",data); } return 0; }
输出
Stack Elements: 44 10 62 123 15 0 0 0 Elements popped: 15 123 62 10 44
#include <iostream> int MAXSIZE = 8; int stack[8]; int top = -1; /* Check if the stack is empty */ int isempty(){ if(top == -1) return 1; else return 0; } /* Check if the stack is full*/ int isfull(){ if(top == MAXSIZE) return 1; else return 0; } /* Function to delete from the stack */ int pop(){ int data; if(!isempty()) { data = stack[top]; top = top - 1; return data; } else { printf("Could not retrieve data, Stack is empty.\n"); } } /* Function to insert into the stack */ int push(int data){ if(!isfull()) { top = top + 1; stack[top] = data; } else { printf("Could not insert data, Stack is full.\n"); } } /* Main function */ int main(){ int i; push(44); push(10); push(62); push(123); push(15); printf("Stack Elements: \n"); // print stack data for(i = 0; i < 8; i++) { printf("%d ", stack[i]); } /*printf("Element at top of the stack: %d\n" ,peek());*/ printf("\nElements popped: \n"); // print stack data while(!isempty()) { int data = pop(); printf("%d ",data); } return 0; }
输出
Stack Elements: 44 10 62 123 15 0 0 0 Elements popped: 15 123 62 10 44
import java.io.*; import java.util.*; // util imports the stack class public class StackExample { public static void main (String[] args) { Stack<Integer> stk = new Stack<Integer>(); // Inserting elements into the stack stk.push(52); stk.push(19); stk.push(33); stk.push(14); stk.push(6); System.out.print("The stack is: " + stk); // Deletion from the stack System.out.print("\nThe popped element is: "); Integer n = (Integer) stk.pop(); System.out.print(n); } }
输出
The stack is: [52, 19, 33, 14, 6] The popped element is: 6
class Stack: def __init__(self): self.stack = [] def __str__(self): return str(self.stack) def push(self, data): if data not in self.stack: self.stack.append(data) return True else: return False def remove(self): if len(self.stack) <= 0: return ("No element in the Stack") else: return self.stack.pop() stk = Stack() stk.push(1) stk.push(2) stk.push(3) stk.push(4) stk.push(5) print("Stack Elements:") print(stk) print("----Deletion operation in stack----") p = stk.remove() print("The popped element is: " + str(p)) print("Updated Stack:") print(stk)
输出
Stack Elements: [1, 2, 3, 4, 5] ----Deletion operation in stack---- The popped element is: 5 Updated Stack: [1, 2, 3, 4]
注意 - 在 Java 中,我们使用内置方法 pop()。
peek()
peek() 是一种操作,用于检索栈中最顶部的元素,而不会删除它。此操作用于借助顶部指针检查栈的状态。
算法
1. START 2. return the element at the top of the stack 3. END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> int MAXSIZE = 8; int stack[8]; int top = -1; /* Check if the stack is full */ int isfull(){ if(top == MAXSIZE) return 1; else return 0; } /* Function to return the topmost element in the stack */ int peek(){ return stack[top]; } /* Function to insert into the stack */ int push(int data){ if(!isfull()) { top = top + 1; stack[top] = data; } else { printf("Could not insert data, Stack is full.\n"); } } /* Main function */ int main(){ int i; push(44); push(10); push(62); push(123); push(15); printf("Stack Elements: \n"); // print stack data for(i = 0; i < 8; i++) { printf("%d ", stack[i]); } printf("\nElement at top of the stack: %d\n" ,peek()); return 0; }
输出
Stack Elements: 44 10 62 123 15 0 0 0 Element at top of the stack: 15
#include <iostream> int MAXSIZE = 8; int stack[8]; int top = -1; /* Check if the stack is full */ int isfull(){ if(top == MAXSIZE) return 1; else return 0; } /* Function to return the topmost element in the stack */ int peek(){ return stack[top]; } /* Function to insert into the stack */ int push(int data){ if(!isfull()) { top = top + 1; stack[top] = data; } else { printf("Could not insert data, Stack is full.\n"); } } /* Main function */ int main(){ int i; push(44); push(10); push(62); push(123); push(15); printf("Stack Elements: \n"); // print stack data for(i = 0; i < 8; i++) { printf("%d ", stack[i]); } printf("\nElement at top of the stack: %d\n" ,peek()); return 0; }
输出
Stack Elements: 44 10 62 123 15 0 0 0 Element at top of the stack: 15
import java.io.*; import java.util.*; // util imports the stack class public class StackExample { public static void main (String[] args) { Stack<Integer> stk = new Stack<Integer>(); // inserting elements into the stack stk.push(52); stk.push(19); stk.push(33); stk.push(14); stk.push(6); System.out.print("The stack is: " + stk); Integer pos = (Integer) stk.peek(); System.out.print("\nThe element found is " + pos); } }
输出
The stack is: [52, 19, 33, 14, 6] The element found is 6
class Stack: def __init__(self): self.stack = [] def __str__(self): return str(self.stack) def push(self, data): if data not in self.stack: self.stack.append(data) return True else: return False # Use peek to look at the top of the stack def peek(self): return self.stack[-1] stk = Stack() stk.push(1) stk.push(2) stk.push(3) stk.push(4) stk.push(5) print("Stack Elements:") print(stk) print("topmost element: ",stk.peek())
输出
Stack Elements: [1, 2, 3, 4, 5] topmost element: 5
isFull()
isFull() 操作检查栈是否已满。此操作用于借助顶部指针检查栈的状态。
算法
1. START 2. If the size of the stack is equal to the top position of the stack, the stack is full. Return 1. 3. Otherwise, return 0. 4. END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> int MAXSIZE = 8; int stack[8]; int top = -1; /* Check if the stack is full */ int isfull(){ if(top == MAXSIZE) return 1; else return 0; } /* Main function */ int main(){ printf("Stack full: %s\n" , isfull()?"true":"false"); return 0; }
输出
Stack full: false
#include <iostream> int MAXSIZE = 8; int stack[8]; int top = -1; /* Check if the stack is full */ int isfull(){ if(top == MAXSIZE) return 1; else return 0; } /* Main function */ int main(){ printf("Stack full: %s\n" , isfull()?"true":"false"); return 0; }
输出
Stack full: false
import java.io.*; public class StackExample { private int arr[]; private int top; private int capacity; StackExample(int size) { arr = new int[size]; capacity = size; top = -1; } public boolean isEmpty() { return top == -1; } public boolean isFull() { return top == capacity - 1; } public void push(int key) { if (isFull()) { System.out.println("Stack is Full\n"); return; } arr[++top] = key; } public static void main (String[] args) { StackExample stk = new StackExample(5); stk.push(1); // inserting 1 in the stack stk.push(2); stk.push(3); stk.push(4); stk.push(5); System.out.println("Stack Full? " + stk.isFull()); } }
输出
Stack Full? true
#python code for stack(IsFull) MAXSIZE = 8 stack = [None] * MAXSIZE top = -1 #Check if the stack is empty def isfull(): if top == MAXSIZE - 1: return True else: return False #main function print("Stack full:", isfull())
输出
Stack full: False
isEmpty()
isEmpty() 操作验证栈是否为空。此操作用于借助顶部指针检查栈的状态。
算法
1. START 2. If the top value is -1, the stack is empty. Return 1. 3. Otherwise, return 0. 4. END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> int MAXSIZE = 8; int stack[8]; int top = -1; /* Check if the stack is empty */ int isempty() { if(top == -1) return 1; else return 0; } /* Main function */ int main() { printf("Stack empty: %s\n" , isempty()?"true":"false"); return 0; }
输出
Stack empty: true
#include <iostream> int MAXSIZE = 8; int stack[8]; int top = -1; /* Check if the stack is empty */ int isempty(){ if(top == -1) return 1; else return 0; } /* Main function */ int main(){ printf("Stack empty: %s\n" , isempty()?"true":"false"); return 0; }
输出
Stack empty: true
import java.io.*; import java.util.*; // util imports the stack class public class StackExample { public static void main (String[] args) { Stack<Integer> stk = new Stack<Integer>(); // Inserting elements into the stack stk.push(52); stk.push(19); stk.push(33); stk.push(14); stk.push(6); System.out.println("Stack empty? "+ stk.isEmpty()); } }
输出
Stack empty? false
#python code for stack(IsFull) MAXSIZE = 8 stack = [None] * MAXSIZE top = -1 #Check if the stack is empty def isempty(): if top == -1: return True else: return False #main function print("Stack empty:", isempty())
输出
Stack empty: True
完整实现
#include <stdio.h> int MAXSIZE = 8; int stack[8]; int top = -1; /* Check if the stack is empty */ int isempty(){ if(top == -1) return 1; else return 0; } /* Check if the stack is full */ int isfull(){ if(top == MAXSIZE) return 1; else return 0; } /* Function to return the topmost element in the stack */ int peek(){ return stack[top]; } /* Function to delete from the stack */ int pop(){ int data; if(!isempty()) { data = stack[top]; top = top - 1; return data; } else { printf("Could not retrieve data, Stack is empty.\n"); } } /* Function to insert into the stack */ int push(int data){ if(!isfull()) { top = top + 1; stack[top] = data; } else { printf("Could not insert data, Stack is full.\n"); } } /* Main function */ int main(){ push(44); push(10); push(62); push(123); push(15); printf("Element at top of the stack: %d\n" ,peek()); printf("Elements: \n"); // print stack data while(!isempty()) { int data = pop(); printf("%d\n",data); } printf("Stack full: %s\n" , isfull()?"true":"false"); printf("Stack empty: %s\n" , isempty()?"true":"false"); return 0; }
输出
Element at top of the stack: 15 Elements: 15123 62 10 44 Stack full: false Stack empty: true
#include <iostream> using namespace std; int MAXSIZE = 8; int stack[8]; int top = -1; /* Check if the stack is empty */ int isempty(){ if(top == -1) return 1; else return 0; } /* Check if the stack is full */ int isfull(){ if(top == MAXSIZE) return 1; else return 0; } /* Function to return the topmost element in the stack */ int peek(){ return stack[top]; } /* Function to delete from the stack */ int pop(){ int data; if(!isempty()) { data = stack[top]; top = top - 1; return data; } else cout << "Could not retrieve data, Stack is empty." << endl; } /* Function to insert into the stack */ int push(int data){ if(!isfull()) { top = top + 1; stack[top] = data; } else cout << "Could not insert data, Stack is full." << endl; } /* Main function */ int main(){ push(44); push(10); push(62); push(123); push(15); cout << "Element at top of the stack: " << peek() << endl; printf("Elements: \n"); // print stack data while(!isempty()) { int data = pop(); cout << data <<endl; } printf("Stack full: %s\n" , isfull()?"true":"false"); printf("Stack empty: %s\n" , isempty()?"true":"false"); return 0; }
输出
Element at top of the stack: 15 Elements: 15 123 62 10 44 Stack full: false Stack empty: true
import java.io.*; import java.util.*; // util imports the stack class public class StackExample { public static void main (String[] args) { Stack<Integer> stk = new Stack<Integer>(); // inserting elements into the stack stk.push(52); stk.push(19); stk.push(33); stk.push(14); stk.push(6); System.out.print("The stack is: " + stk); // deletion from the stack System.out.print("\nThe popped element is: "); Integer n = (Integer) stk.pop(); System.out.print(n); // searching for an element in the stack Integer pos = (Integer) stk.search(19); if(pos == -1) System.out.print("\nThe element 19 not found in stack"); else System.out.print("\nThe element 19 is found at " + pos); } }
输出
The stack is: [52, 19, 33, 14, 6] The popped element is: 6 The element 19 is found at 3
class Stack: def __init__(self): self.stack = [] def add(self, data): if data not in self.stack: self.stack.append(data) return True else: return False # Use peek to look at the top of the stack def peek(self): return self.stack[-1] # Use list pop method to remove element def remove(self): if len(self.stack) <= 0: return ("No element in the Stack") else: return self.stack.pop() stk = Stack() stk.add(1) stk.add(2) stk.add(3) stk.add(4) stk.add(5) print("topmost element: ",stk.peek()) print("----Deletion operation in stack----") stk.remove() stk.peek() print("topmost element after deletion: ",stk.peek())
输出
topmost element: 5 ----Deletion operation in stack---- topmost element after deletion: 4
表达式解析
编写算术表达式的 方式称为表示法。算术表达式可以用三种不同但等价的表示法来编写,即不改变表达式的本质或输出。这些表示法是:
- 中缀表示法
- 前缀(波兰)表示法
- 后缀(逆波兰)表示法
这些表示法以它们在表达式中使用运算符的方式命名。我们将在本章中学习这些内容。
中缀表示法
我们用中缀表示法编写表达式,例如 a - b + c,其中运算符位于操作数之间。对于我们人类来说,用中缀表示法阅读、编写和说话很容易,但对于计算设备来说却并非如此。处理中缀表示法的算法在时间和空间消耗方面可能很复杂且成本很高。
前缀表示法
在这种表示法中,运算符位于操作数之前,即运算符写在操作数前面。例如,+ab。这等价于其中缀表示法a + b。前缀表示法也称为波兰表示法。
后缀表示法
这种表示法风格称为逆波兰表示法。在这种表示法风格中,运算符位于操作数之后,即运算符写在操作数后面。例如,ab+。这等价于其中缀表示法a + b。
下表简要地试图显示三种表示法的区别:
序号 | 中缀表示法 | 前缀表示法 | 后缀表示法 |
---|---|---|---|
1 | a + b | + a b | a b + |
2 | (a + b) ∗ c | ∗ + a b c | a b + c ∗ |
3 | a ∗ (b + c) | ∗ a + b c | a b c + ∗ |
4 | a / b + c / d | + / a b / c d | a b / c d / + |
5 | (a + b) ∗ (c + d) | ∗ + a b + c d | a b + c d + ∗ |
6 | ((a + b) ∗ c) - d | - ∗ + a b c d | a b + c ∗ d - |
解析表达式
正如我们所讨论的,设计算法或程序来解析中缀表示法并不是一种非常有效的方法。相反,这些中缀表示法首先被转换为后缀或前缀表示法,然后进行计算。
要解析任何算术表达式,我们还需要考虑运算符的优先级和结合性。
优先级
当一个操作数位于两个不同的运算符之间时,哪个运算符将首先获取该操作数,这由一个运算符相对于其他运算符的优先级决定。例如:
由于乘法运算优先于加法运算,因此 b * c 将首先被计算。稍后将提供运算符优先级表。
结合性
结合性描述了在表达式中出现优先级相同的运算符时的规则。例如,在表达式 a + b - c 中,+ 和 - 具有相同的优先级,那么表达式的哪一部分将首先被计算,这由这些运算符的结合性决定。这里,+ 和 - 都是左结合的,因此表达式将被计算为(a + b) - c。
优先级和结合性决定了表达式的计算顺序。以下是运算符优先级和结合性表(从高到低):
序号 | 运算符 | 优先级 | 结合性 |
---|---|---|---|
1 | 指数 ^ | 最高 | 右结合 |
2 | 乘法 ( ∗ ) & 除法 ( / ) | 第二高 | 左结合 |
3 | 加法 ( + ) & 减法 ( − ) | 最低 | 左结合 |
上表显示了运算符的默认行为。在表达式计算的任何时间点,都可以使用括号更改顺序。例如:
在a + b*c中,表达式部分b*c将首先被计算,因为乘法的优先级高于加法。在这里,我们使用括号使a + b首先被计算,例如(a + b)*c。
后缀表达式计算算法
我们现在来看一下如何计算后缀表示法的算法:
Step 1 − scan the expression from left to right Step 2 − if it is an operand push it to stack Step 3 − if it is an operator pull operand from stack and perform operation Step 4 − store the output of step 3, back to stack Step 5 − scan the expression until all operands are consumed Step 6 − pop the stack and perform operation
完整实现
#include<stdio.h> #include<string.h> #include<ctype.h> //char stack char stack[25]; int top = -1; void push(char item) { stack[++top] = item; } char pop() { return stack[top--]; } //returns precedence of operators int precedence(char symbol) { switch(symbol) { case '+': case '-': return 2; break; case '*': case '/': return 3; break; case '^': return 4; break; case '(': case ')': case '#': return 1; break; } } //check whether the symbol is operator? int isOperator(char symbol) { switch(symbol) { case '+': case '-': case '*': case '/': case '^': case '(': case ')': return 1; break; default: return 0; } } //converts infix expression to postfix void convert(char infix[],char postfix[]) { int i,symbol,j = 0; stack[++top] = '#'; for(i = 0;i<strlen(infix);i++) { symbol = infix[i]; if(isOperator(symbol) == 0) { postfix[j] = symbol; j++; } else { if(symbol == '(') { push(symbol); } else { if(symbol == ')') { while(stack[top] != '(') { postfix[j] = pop(); j++; } pop(); //pop out (. } else { if(precedence(symbol)>precedence(stack[top])) { push(symbol); } else { while(precedence(symbol)<=precedence(stack[top])) { postfix[j] = pop(); j++; } push(symbol); } } } } } while(stack[top] != '#') { postfix[j] = pop(); j++; } postfix[j]='\0'; //null terminate string. } //int stack int stack_int[25]; int top_int = -1; void push_int(int item) { stack_int[++top_int] = item; } char pop_int() { return stack_int[top_int--]; } //evaluates postfix expression int evaluate(char *postfix){ char ch; int i = 0,operand1,operand2; while( (ch = postfix[i++]) != '\0') { if(isdigit(ch)) { push_int(ch-'0'); // Push the operand } else { //Operator,pop two operands operand2 = pop_int(); operand1 = pop_int(); switch(ch) { case '+': push_int(operand1+operand2); break; case '-': push_int(operand1-operand2); break; case '*': push_int(operand1*operand2); break; case '/': push_int(operand1/operand2); break; } } } return stack_int[top_int]; } void main() { char infix[25] = "1*(2+3)",postfix[25]; convert(infix,postfix); printf("Infix expression is: %s\n" , infix); printf("Postfix expression is: %s\n" , postfix); printf("Evaluated expression is: %d\n" , evaluate(postfix)); }
输出
Infix expression is: 1*(2+3) Postfix expression is: 123+* Evaluated expression is: 5
// C++ Code for Expression Parsing Using Stack #include <iostream> #include <string> #include <cctype> #include <stack> // char stack std::stack<char> stack; void push(char item) { stack.push(item); } char pop() { char top = stack.top(); stack.pop(); return top; } // returns precedence of operators int precedence(char symbol) { switch(symbol) { case '+': case '-': return 2; case '*': case '/': return 3; case '^': return 4; case '(': case ')': case '#': return 1; } return 0; } // check whether the symbol is an operator int isOperator(char symbol) { switch(symbol) { case '+': case '-': case '*': case '/': case '^': case '(': case ')': return 1; default: return 0; } } // converts infix expression to postfix void convert(const std::string& infix, std::string& postfix) { int j = 0; stack.push('#'); for (char symbol : infix) { if (isOperator(symbol) == 0) { postfix += symbol; j++; } else { if (symbol == '(') { push(symbol); } else { if (symbol == ')') { while (stack.top() != '(') { postfix += pop(); j++; } stack.pop(); // pop out '(' } else { if (precedence(symbol) > precedence(stack.top())) { push(symbol); } else { while (precedence(symbol) <= precedence(stack.top())) { postfix += pop(); j++; } push(symbol); } } } } } while (stack.top() != '#') { postfix += pop(); j++; } postfix[j] = '\0'; // null terminate string } // evaluates postfix expression int evaluate(const std::string& postfix) { std::stack<int> stack_int; int operand1, operand2; for (char ch : postfix) { if (std::isdigit(ch)) { stack_int.push(ch - '0'); // Push the operand } else { // Operator, pop two operands operand2 = stack_int.top(); stack_int.pop(); operand1 = stack_int.top(); stack_int.pop(); switch (ch) { case '+': stack_int.push(operand1 + operand2); break; case '-': stack_int.push(operand1 - operand2); break; case '*': stack_int.push(operand1 * operand2); break; case '/': stack_int.push(operand1 / operand2); break; } } } return stack_int.top(); } int main() { std::string infix = "1*(2+3)", postfix; convert(infix, postfix); std::cout << "Infix expression is: " << infix << std::endl; std::cout << "Postfix expression is: " << postfix << std::endl; std::cout << "Evaluated expression is: " << evaluate(postfix) << std::endl; return 0; }
输出
Infix expression is: 1*(2+3) Postfix expression is: 123+* Evaluated expression is: 5
// Java Code for Expression Parsing Using Stack import java.util.Stack; public class Main { // char stack static Stack<Character> stack = new Stack<>(); static void push(char item) { stack.push(item); } static char pop() { return stack.pop(); } // returns precedence of operators static int precedence(char symbol) { switch (symbol) { case '+': case '-': return 2; case '*': case '/': return 3; case '^': return 4; case '(': case ')': case '#': return 1; } return 0; } // check whether the symbol is an operator static int isOperator(char symbol) { switch (symbol) { case '+': case '-': case '*': case '/': case '^': case '(': case ')': return 1; default: return 0; } } // converts infix expression to postfix static void convert(String infix, StringBuilder postfix) { int j = 0; stack.push('#'); for (char symbol : infix.toCharArray()) { if (isOperator(symbol) == 0) { postfix.append(symbol); j++; } else { if (symbol == '(') { push(symbol); } else { if (symbol == ')') { while (stack.peek() != '(') { postfix.append(pop()); j++; } stack.pop(); // pop out '(' } else { if (precedence(symbol) > precedence(stack.peek())) { push(symbol); } else { while (precedence(symbol) <= precedence(stack.peek())) { postfix.append(pop()); j++; } push(symbol); } } } } } while (stack.peek() != '#') { postfix.append(pop()); j++; } } // evaluates postfix expression static int evaluate(String postfix) { Stack<Integer> stackInt = new Stack<>(); int operand1, operand2; for (char ch : postfix.toCharArray()) { if (Character.isDigit(ch)) { stackInt.push(ch - '0'); // Push the operand } else { // Operator, pop two operands operand2 = stackInt.pop(); operand1 = stackInt.pop(); switch (ch) { case '+': stackInt.push(operand1 + operand2); break; case '-': stackInt.push(operand1 - operand2); break; case '*': stackInt.push(operand1 * operand2); break; case '/': stackInt.push(operand1 / operand2); break; } } } return stackInt.peek(); } public static void main(String[] args) { String infix = "1*(2+3)"; StringBuilder postfix = new StringBuilder(); convert(infix, postfix); System.out.println("Infix expression is: " + infix); System.out.println("Postfix expression is: " + postfix); System.out.println("Evaluated expression is: " + evaluate(postfix.toString())); } }< h3>输出
Infix expression is: 1*(2+3) Postfix expression is: 123+* Evaluated expression is: 5
class Main: stack = [] @staticmethod def push(item): Main.stack.append(item) @staticmethod def pop(): return Main.stack.pop() #returns precedence of operators @staticmethod def precedence(symbol): if symbol in ['+', '-']: return 2 elif symbol in ['*', '/']: return 3 elif symbol == '^': return 4 elif symbol in ['(', ')', '#']: return 1 return 0 #check whether the symbol is an operator @staticmethod def is_operator(symbol): return symbol in ['+', '-', '*', '/', '^', '(', ')'] @staticmethod def convert(infix): postfix = "" j = 0 Main.push('#') for symbol in infix: if not Main.is_operator(symbol): postfix += symbol j += 1 else: if symbol == '(': Main.push(symbol) else: if symbol == ')': while Main.stack[-1] != '(': postfix += Main.pop() j += 1 Main.pop() # pop out '(' else: if Main.precedence(symbol) > Main.precedence(Main.stack[-1]): Main.push(symbol) else: while Main.precedence(symbol) <= Main.precedence(Main.stack[-1]): postfix += Main.pop() j += 1 Main.push(symbol) while Main.stack[-1] != '#': postfix += Main.pop() j += 1 return postfix @staticmethod def evaluate(postfix): stack_int = [] for ch in postfix: if ch.isdigit(): stack_int.append(int(ch)) else: operand2 = stack_int.pop() operand1 = stack_int.pop() if ch == '+': stack_int.append(operand1 + operand2) elif ch == '-': stack_int.append(operand1 - operand2) elif ch == '*': stack_int.append(operand1 * operand2) elif ch == '/': stack_int.append(operand1 / operand2) return stack_int[0] @staticmethod def main(): infix = "1*(2+3)" postfix = Main.convert(infix) print("Infix expression is:", infix) print("Postfix expression is:", postfix) print("Evaluated expression is:", Main.evaluate(postfix)) Main.main()
输出
Infix expression is: 1*(2+3) Postfix expression is: 123+* Evaluated expression is: 5
队列数据结构
队列与栈类似,也是一种抽象数据结构。使队列与栈不同的特点是队列的两端都是开放的。因此,它遵循 FIFO(先进先出)结构,即第一个插入的数据项也将被第一个访问。数据通过一端插入队列,并通过另一端删除。
队列的一个现实世界例子可以是一条单车道单行道,其中先进入的车辆先退出。更多现实世界的例子可以看作是售票窗口和公交车站的队伍。
队列的表示
与栈 ADT 类似,队列 ADT 也可以使用数组、链表或指针来实现。在本教程中的一个小例子中,我们使用一维数组来实现队列。
基本操作
队列操作还包括队列的初始化、使用以及永久地从内存中删除数据。
队列 ADT 中最基本的操作包括:enqueue()、dequeue()、peek()、isFull()、isEmpty()。这些都是内置操作,用于执行数据操作并检查队列的状态。
队列使用两个指针:front 和 rear。front 指针从前端访问数据(帮助入队),而 rear 指针从后端访问数据(帮助出队)。
插入操作:enqueue()
enqueue() 是一种数据操作,用于将元素插入栈。以下算法更简单地描述了 enqueue() 操作。
算法
1 − START 2 – Check if the queue is full. 3 − If the queue is full, produce overflow error and exit. 4 − If the queue is not full, increment rear pointer to point the next empty space. 5 − Add data element to the queue location, where the rear is pointing. 6 − return success. 7 – END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> #define MAX 6 int intArray[MAX]; int front = 0; int rear = -1; int itemCount = 0; bool isFull(){ return itemCount == MAX; } bool isEmpty(){ return itemCount == 0; } int removeData(){ int data = intArray[front++]; if(front == MAX) { front = 0; } itemCount--; return data; } void insert(int data){ if(!isFull()) { if(rear == MAX-1) { rear = -1; } intArray[++rear] = data; itemCount++; } } int main(){ insert(3); insert(5); insert(9); insert(1); insert(12); insert(15); printf("Queue: "); while(!isEmpty()) { int n = removeData(); printf("%d ",n); } }
输出
Queue: 3 5 9 1 12 15
#include <iostream> #include <string> #define MAX 6 int intArray[MAX]; int front = 0; int rear = -1; int itemCount = 0; bool isFull(){ return itemCount == MAX; } bool isEmpty(){ return itemCount == 0; } int removeData(){ int data = intArray[front++]; if(front == MAX) { front = 0; } itemCount--; return data; } void insert(int data){ if(!isFull()) { if(rear == MAX-1) { rear = -1; } intArray[++rear] = data; itemCount++; } } int main(){ insert(3); insert(5); insert(9); insert(1); insert(12); insert(15); printf("Queue: "); while(!isEmpty()) { int n = removeData(); printf("%d ",n); } }
输出
Queue: 3 5 9 1 12 15
import java.util.LinkedList; import java.util.Queue; public class QueueExample { public static void main(String[] args) { Queue<Integer> q = new LinkedList<>(); q.add(6); q.add(1); q.add(8); q.add(4); q.add(7); System.out.println("The queue is: " + q); } }
输出
The queue is: [6, 1, 8, 4, 7]
class Queue: def __init__(self): self.queue = list() def __str__(self): return str(self.queue) def addtoqueue(self,data): # Insert method to add element if data not in self.queue: self.queue.insert(0,data) return True return False q = Queue() q.addtoqueue("36") q.addtoqueue("24") q.addtoqueue("48") q.addtoqueue("12") q.addtoqueue("66") print("Queue:") print(q)
输出
Queue: ['66', '12', '48', '24', '36']
删除操作:dequeue()
dequeue() 是一种数据操作,用于从栈中删除元素。以下算法更简单地描述了 dequeue() 操作。
算法
1 – START 2 − Check if the queue is empty. 3 − If the queue is empty, produce underflow error and exit. 4 − If the queue is not empty, access the data where front is pointing. 5 − Increment front pointer to point to the next available data element. 6 − Return success. 7 – END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> #define MAX 6 int intArray[MAX]; int front = 0; int rear = -1; int itemCount = 0; bool isFull(){ return itemCount == MAX; } bool isEmpty(){ return itemCount == 0; } void insert(int data){ if(!isFull()) { if(rear == MAX-1) { rear = -1; } intArray[++rear] = data; itemCount++; } } int removeData(){ int data = intArray[front++]; if(front == MAX) { front = 0; } itemCount--; return data; } int main(){ int i; /* insert 5 items */ insert(3); insert(5); insert(9); insert(1); insert(12); insert(15); printf("Queue: "); for(i = 0; i < MAX; i++) printf("%d ", intArray[i]); // remove one item int num = removeData(); printf("\nElement removed: %d\n",num); printf("Updated Queue: "); while(!isEmpty()) { int n = removeData(); printf("%d ",n); } }
输出
Queue: 3 5 9 1 12 15 Element removed: 3 Updated Queue: 5 9 1 12 15
#include <iostream> #include <string> #define MAX 6 int intArray[MAX]; int front = 0; int rear = -1; int itemCount = 0; bool isFull(){ return itemCount == MAX; } bool isEmpty(){ return itemCount == 0; } void insert(int data){ if(!isFull()) { if(rear == MAX-1) { rear = -1; } intArray[++rear] = data; itemCount++; } } int removeData(){ int data = intArray[front++]; if(front == MAX) { front = 0; } itemCount--; return data; } int main(){ int i; /* insert 5 items */ insert(3); insert(5); insert(9); insert(1); insert(12); insert(15); printf("Queue: "); for(i = 0; i < MAX; i++) printf("%d ", intArray[i]); // remove one item int num = removeData(); printf("\nElement removed: %d\n",num); printf("Updated Queue: "); while(!isEmpty()) { int n = removeData(); printf("%d ",n); } }
输出
Queue: 3 5 9 1 12 15 Element removed: 3 Updated Queue: 5 9 1 12 15
import java.util.LinkedList; import java.util.Queue; public class QueueExample { public static void main(String[] args) { Queue<Integer> q = new LinkedList<>(); q.add(6); q.add(1); q.add(8); q.add(4); q.add(7); System.out.println("The queue is: " + q); int n = q.remove(); System.out.println("The element deleted is: " + n); System.out.println("Queue after deletion: " + q); } }
输出
The queue is: [6, 1, 8, 4, 7] The element deleted is: 6 Queue after deletion: [1, 8, 4, 7]
class Queue: def __init__(self): self.queue = list() def __str__(self): return str(self.queue) def addtoqueue(self,data): # Insert method to add element if data not in self.queue: self.queue.insert(0,data) return True return False def removefromqueue(self): if len(self.queue)>0: return self.queue.pop() return ("Queue is empty") q = Queue() q.addtoqueue("36") q.addtoqueue("24") q.addtoqueue("48") q.addtoqueue("12") q.addtoqueue("66") print("Queue:") print(q) print("Element deleted from queue: ",q.removefromqueue())
输出
Queue: ['66', '12', '48', '24', '36'] Element deleted from queue: 36
peek() 操作
peek() 是一种操作,用于检索队列中最前面的元素,而不会删除它。此操作用于借助指针检查队列的状态。
算法
1 – START 2 – Return the element at the front of the queue 3 – END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> #define MAX 6 int intArray[MAX]; int front = 0; int rear = -1; int itemCount = 0; int peek(){ return intArray[front]; } bool isFull(){ return itemCount == MAX; } void insert(int data){ if(!isFull()) { if(rear == MAX-1) { rear = -1; } intArray[++rear] = data; itemCount++; } } int main(){ int i; /* insert 5 items */ insert(3); insert(5); insert(9); insert(1); insert(12); insert(15); printf("Queue: "); for(i = 0; i < MAX; i++) printf("%d ", intArray[i]); printf("\nElement at front: %d\n",peek()); }
输出
Queue: 3 5 9 1 12 15 Element at front: 3
#include <iostream> #include <string> #define MAX 6 int intArray[MAX]; int front = 0; int rear = -1; int itemCount = 0; int peek(){ return intArray[front]; } bool isFull(){ return itemCount == MAX; } void insert(int data){ if(!isFull()) { if(rear == MAX-1) { rear = -1; } intArray[++rear] = data; itemCount++; } } int main(){ int i; /* insert 5 items */ insert(3); insert(5); insert(9); insert(1); insert(12); insert(15); printf("Queue: "); for(i = 0; i < MAX; i++) printf("%d ", intArray[i]); printf("\nElement at front: %d\n",peek()); }
输出
Queue: 3 5 9 1 12 15 Element at front: 3
import java.util.LinkedList; import java.util.Queue; public class QueueExample { public static void main(String[] args) { Queue<Integer> q = new LinkedList<>(); q.add(6); q.add(1); q.add(8); q.add(4); q.add(7); System.out.println("The queue is: " + q); } }
输出
The queue is: [6, 1, 8, 4, 7]
class Queue: def __init__(self): self.queue = list() def __str__(self): return str(self.queue) def addtoqueue(self,data): # Insert method to add element if data not in self.queue: self.queue.insert(0,data) return True return False def peek(self): return self.queue[-1] q = Queue() q.addtoqueue("36") q.addtoqueue("24") q.addtoqueue("48") q.addtoqueue("12") q.addtoqueue("66") print("Queue:") print(q) print("The frontmost element of the queue: ",q.peek())
输出
Queue: ['66', '12', '48', '24', '36'] The frontmost element of the queue: 36
isFull() 操作
isFull() 操作验证栈是否已满。
算法
1 – START 2 – If the count of queue elements equals the queue size, return true 3 – Otherwise, return false 4 – END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> #define MAX 6 int intArray[MAX]; int front = 0; int rear = -1; int itemCount = 0; bool isFull(){ return itemCount == MAX; } void insert(int data){ if(!isFull()) { if(rear == MAX-1) { rear = -1; } intArray[++rear] = data; itemCount++; } } int main(){ int i; /* insert 5 items */ insert(3); insert(5); insert(9); insert(1); insert(12); insert(15); printf("Queue: "); for(i = 0; i < MAX; i++) printf("%d ", intArray[i]); printf("\n"); if(isFull()) { printf("Queue is full!\n"); } }
输出
Queue: 3 5 9 1 12 15 Queue is full!
#include <iostream> #include <string> #define MAX 6 int intArray[MAX]; int front = 0; int rear = -1; int itemCount = 0; bool isFull(){ return itemCount == MAX; } void insert(int data){ if(!isFull()) { if(rear == MAX-1) { rear = -1; } intArray[++rear] = data; itemCount++; } } int main(){ int i; /* insert 5 items */ insert(3); insert(5); insert(9); insert(1); insert(12); insert(15); printf("Queue: "); for(i = 0; i < MAX; i++) printf("%d ", intArray[i]); printf("\n"); if(isFull()) { printf("Queue is full!\n"); } }
输出
Queue: 3 5 9 1 12 15 Queue is full!
import java.io.*; public class QueueExample { private int intArray[]; private int front; private int rear; private int itemCount; private int MAX; QueueExample(int size) { intArray = new int[size]; front = 0; rear = -1; MAX = size; itemCount = 0; } public boolean isFull() { return itemCount == MAX; } public void insert(int key) { if(!isFull()) { if(rear == MAX-1) { rear = -1; } intArray[++rear] = key; itemCount++; } } public static void main (String[] args) { QueueExample q = new QueueExample(5); q.insert(1); // inserting 1 in the stack q.insert(2); q.insert(3); q.insert(4); q.insert(5); System.out.println("Stack Full? " + q.isFull()); } }
输出
Stack Full? true
#python code for isFull in Queue MAX = 6 intArray = [None] * MAX front = 0 rear = -1 itemCount = 0 def isFull(): return itemCount == MAX def insert(data): global rear, itemCount if not isFull(): if rear == MAX-1: rear = -1 rear += 1 intArray[rear] = data itemCount += 1 #inserting 5 items into the Queue insert(3) insert(5) insert(9) insert(1) insert(12) insert(15) print("Queue: ", end="") for i in range(MAX): print(intArray[i], end=" ") print() if isFull(): print("Queue is full!")
输出
Queue: 3 5 9 1 12 15 Queue is full!
isEmpty() 操作
isEmpty() 操作验证栈是否为空。此操作用于借助顶部指针检查栈的状态。
算法
1 – START 2 – If the count of queue elements equals zero, return true 3 – Otherwise, return false 4 – END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> #define MAX 6 int intArray[MAX]; int front = 0; int rear = -1; int itemCount = 0; bool isEmpty(){ return itemCount == 0; } int main(){ int i; printf("Queue: "); for(i = 0; i < MAX; i++) printf("%d ", intArray[i]); printf("\n"); if(isEmpty()) { printf("Queue is Empty!\n"); } }
输出
Queue: 0 0 0 0 0 0 Queue is Empty!
#include <iostream> #include <string> #define MAX 6 int intArray[MAX]; int front = 0; int rear = -1; int itemCount = 0; bool isEmpty(){ return itemCount == 0; } int main(){ int i; printf("Queue: "); for(i = 0; i < MAX; i++) printf("%d ", intArray[i]); printf("\n"); if(isEmpty()) { printf("Queue is Empty!\n"); } }
输出
Queue: 0 0 0 0 0 0 Queue is Empty!
import java.io.*; public class QueueExample { private int intArray[]; private int front; private int rear; private int itemCount; private int MAX; QueueExample(int size) { intArray = new int[size]; front = 0; rear = -1; MAX = size; itemCount = 0; } public boolean isEmpty() { return itemCount == 0; } public static void main (String[] args) { QueueExample q = new QueueExample(5); System.out.println("Stack Empty? " + q.isEmpty()); } }
输出
Stack Empty? true
#python code for isFull in Queue MAX = 6 intArray = [None] * MAX front = 0 rear = -1 itemCount = 0 def isEmpty(): return itemCount == 0 print("Queue: ", end="") for i in range(MAX): print(intArray[i], end=" ") print() if isEmpty(): print("Queue is empty!")
输出
Queue: None None None None None None Queue is empty!
队列的实现
在本章中,队列数据结构的算法实现是在四种编程语言中进行的。
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> #define MAX 6 int intArray[MAX]; int front = 0; int rear = -1; int itemCount = 0; int peek(){ return intArray[front]; } bool isEmpty(){ return itemCount == 0; } bool isFull(){ return itemCount == MAX; } int size(){ return itemCount; } void insert(int data){ if(!isFull()) { if(rear == MAX-1) { rear = -1; } intArray[++rear] = data; itemCount++; } } int removeData(){ int data = intArray[front++]; if(front == MAX) { front = 0; } itemCount--; return data; } int main(){ /* insert 5 items */ insert(3); insert(5); insert(9); insert(1); insert(12); // front : 0 // rear : 4 // ------------------ // index : 0 1 2 3 4 // ------------------ // queue : 3 5 9 1 12 insert(15); // front : 0 // rear : 5 // --------------------- // index : 0 1 2 3 4 5 // --------------------- // queue : 3 5 9 1 12 15 if(isFull()) { printf("Queue is full!\n"); } // remove one item int num = removeData(); printf("Element removed: %d\n",num); // front : 1 // rear : 5 // ------------------- // index : 1 2 3 4 5 // ------------------- // queue : 5 9 1 12 15 // insert more items insert(16); // front : 1 // rear : -1 // ---------------------- // index : 0 1 2 3 4 5 // ---------------------- // queue : 16 5 9 1 12 15 // As queue is full, elements will not be inserted. insert(17); insert(18); // ---------------------- // index : 0 1 2 3 4 5 // ---------------------- // queue : 16 5 9 1 12 15 printf("Element at front: %d\n",peek()); printf("----------------------\n"); printf("index : 5 4 3 2 1 0\n"); printf("----------------------\n"); printf("Queue: "); while(!isEmpty()) { int n = removeData(); printf("%d ",n); } }
输出
Queue is full! Element removed: 3 Element at front: 5 ---------------------- index : 5 4 3 2 1 0 ---------------------- Queue: 5 9 1 12 15 16
#include <iostream> #include <string> #define MAX 6 int intArray[MAX]; int front = 0; int rear = -1; int itemCount = 0; int peek(){ return intArray[front]; } bool isEmpty(){ return itemCount == 0; } bool isFull(){ return itemCount == MAX; } int size(){ return itemCount; } void insert(int data){ if(!isFull()) { if(rear == MAX-1) { rear = -1; } intArray[++rear] = data; itemCount++; } } int removeData(){ int data = intArray[front++]; if(front == MAX) { front = 0; } itemCount--; return data; } int main(){ /* insert 5 items */ insert(3); insert(5); insert(9); insert(1); insert(12); // front : 0 // rear : 4 // ------------------ // index : 0 1 2 3 4 // ------------------ // queue : 3 5 9 1 12 insert(15); // front : 0 // rear : 5 // --------------------- // index : 0 1 2 3 4 5 // --------------------- // queue : 3 5 9 1 12 15 if(isFull()) { printf("Queue is full!\n"); } // remove one item int num = removeData(); printf("Element removed: %d\n",num); // front : 1 // rear : 5 // ------------------- // index : 1 2 3 4 5 // ------------------- // queue : 5 9 1 12 15 // insert more items insert(16); // front : 1 // rear : -1 // ---------------------- // index : 0 1 2 3 4 5 // ---------------------- // queue : 16 5 9 1 12 15 // As queue is full, elements will not be inserted. insert(17); insert(18); // ---------------------- // index : 0 1 2 3 4 5 // ---------------------- // queue : 16 5 9 1 12 15 printf("Element at front: %d\n",peek()); printf("----------------------\n"); printf("index : 5 4 3 2 1 0\n"); printf("----------------------\n"); printf("Queue: "); while(!isEmpty()) { int n = removeData(); printf("%d ",n); } }
输出
Queue is full! Element removed: 3 Element at front: 5 ---------------------- index : 5 4 3 2 1 0 ---------------------- Queue: 5 9 1 12 15 16
import java.util.LinkedList; import java.util.Queue; public class QueueExample { public static void main(String[] args) { Queue<Integer> q = new LinkedList<>(); q.add(6); q.add(1); q.add(8); q.add(4); q.add(7); System.out.println("The queue is: " + q); int n = q.remove(); System.out.println("The element deleted is: " + n); System.out.println("Queue after deletion: " + q); int size = q.size(); System.out.println("Size of the queue is: " + size); } }
输出
The queue is: [6, 1, 8, 4, 7]The element deleted is: 6 Queue after deletion: [1, 8, 4, 7] Size of the queue is: 4
class Queue: def __init__(self): self.queue = list() def addtoqueue(self,data): # Insert method to add element if data not in self.queue: self.queue.insert(0,data) return True return False def size(self): return len(self.queue) def removefromqueue(self): if len(self.queue)>0: return self.queue.pop() return ("Queue is empty") q = Queue() q.addtoqueue("36") q.addtoqueue("24") q.addtoqueue("48") q.addtoqueue("12") q.addtoqueue("66") print("size of the queue: ",q.size()) print("Element deleted from queue: ",q.removefromqueue()) print("size of the queue after deletion: ",q.size())
输出
size of the queue: 5 Element deleted from queue: 36 size of the queue after deletion: 4
图数据结构
图是一种抽象数据类型 (ADT),它由一组通过链接相互连接的对象组成。这些对象称为顶点,链接称为边。
通常,图表示为 G = {V, E},其中 G 是图空间,V 是顶点集,E 是边集。如果 E 为空,则该图称为森林。
在我们继续之前,让我们先熟悉一些重要的术语:
顶点 - 图的每个节点都表示为一个顶点。在下面的示例中,带标签的圆圈表示顶点。因此,A 到 G 是顶点。我们可以使用数组来表示它们,如下面的图像所示。这里 A 可以用索引 0 来识别。B 可以用索引 1 来识别,依此类推。
边 - 边表示两个顶点之间的路径或两个顶点之间的线。在下面的示例中,从 A 到 B、B 到 C 等的线表示边。我们可以使用二维数组来表示数组,如下面的图像所示。这里 AB 可以用第 0 行第 1 列的 1 来表示,BC 可以用第 1 行第 2 列的 1 来表示,依此类推,保持其他组合为 0。
邻接 - 如果两个节点或顶点通过边连接,则它们是邻接的。在下面的示例中,B 与 A 邻接,C 与 B 邻接,依此类推。
路径 - 路径表示两个顶点之间的一系列边。在下面的示例中,ABCD 表示从 A 到 D 的路径。
图的操作
图的主要操作包括创建具有顶点和边的图,以及显示所述图。但是,使用图执行的最常见和最流行的操作之一是遍历,即以特定顺序访问图的每个顶点。
图中有两种遍历方式:
深度优先搜索遍历
广度优先搜索遍历
深度优先搜索遍历
深度优先搜索是一种遍历算法,它按照节点深度的递减顺序访问图中的所有节点。在这个算法中,选择一个任意节点作为起始点,并通过标记未访问的相邻节点来回遍历图,直到所有节点都被标记。
DFS 遍历使用栈数据结构来跟踪未访问的节点。
广度优先搜索遍历
广度优先搜索是一种遍历算法,它在访问图中下一层节点之前,会访问同一深度层的所有节点。在这个算法中,选择一个任意节点作为起始点,并通过访问同一深度层上的相邻节点并标记它们来遍历图,直到没有剩余的节点。
BFS 遍历使用队列数据结构来跟踪未访问的节点。
图的表示
在表示图时,我们必须仔细描绘图中存在的元素(顶点和边)以及它们之间的关系。从图示上看,图由一组有限的节点和它们之间的连接线表示。但是,我们也可以使用其他最常用的方法来表示图,例如:
邻接矩阵
邻接表
邻接矩阵
邻接矩阵是一个 V×V 的矩阵,其值填充为 0 或 1。如果 Vi 和 Vj 之间存在连接,则记录为 1;否则为 0。
对于下面给定的图,让我们构建一个邻接矩阵:
邻接矩阵为:
邻接表
邻接表是图中直接连接到其他顶点的顶点的列表。
邻接表为:
图的类型
图主要有两种类型:
有向图
无向图
顾名思义,有向图包含具有方向的边,这些方向要么远离顶点,要么指向顶点。无向图的边没有任何方向。
有向图
无向图
生成树
生成树是无向图的一个子集,它包含图的所有顶点,并使用图中最小数量的边连接起来。准确地说,生成树的边是原始图中边的子集。
如果图中的所有顶点都连接在一起,则至少存在一棵生成树。在一个图中,可能存在多棵生成树。
特性
生成树不包含任何环。
任何顶点都可以从任何其他顶点到达。
示例
在下图中,突出显示的边构成一棵生成树。
最小生成树
最小生成树 (MST) 是连通加权无向图的边的子集,它以最小的总边权重将所有顶点连接在一起。要导出 MST,可以使用 Prim 算法或 Kruskal 算法。因此,我们将在本章中讨论 Prim 算法。
正如我们所讨论的,一个图可能有多棵生成树。如果存在 n 个顶点,则生成树应具有 𝒏−𝟏 条边。在这种情况下,如果图的每条边都与权重相关联,并且存在多棵生成树,我们需要找到图的最小生成树。
此外,如果存在任何重复的加权边,则图可能有多个最小生成树。
在上图中,我们展示了一棵生成树,尽管它不是最小生成树。这棵生成树的成本为(5+7+3+3+5+8+3+4)=38。
最短路径
图中最短路径定义为从一个顶点到另一个顶点的最小成本路径。这在加权有向图中最常见,但也适用于无向图。
在图中查找最短路径的一个流行的现实世界应用是地图。使用各种最短路径算法可以使导航变得更容易和更简单,其中目的地被视为图的顶点,路线被视为边。两种常见的最短路径算法是:
迪杰斯特拉最短路径算法
贝尔曼-福特最短路径算法
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include<stdlib.h> #include <stdlib.h> #define V 5 // Maximum number of vertices in the graph struct graph { // declaring graph data structure struct vertex *point[V]; }; struct vertex { // declaring vertices int end; struct vertex *next; }; struct Edge { // declaring edges int end, start; }; struct graph *create_graph (struct Edge edges[], int x){ int i; struct graph *graph = (struct graph *) malloc (sizeof (struct graph)); for (i = 0; i < V; i++) { graph->point[i] = NULL; } for (i = 0; i < x; i++) { int start = edges[i].start; int end = edges[i].end; struct vertex *v = (struct vertex *) malloc (sizeof (struct vertex)); v->end = end; v->next = graph->point[start]; graph->point[start] = v; } return graph; } int main (){ struct Edge edges[] = { {0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 4}, {2, 4}, {2, 3}, {3, 1} }; int n = sizeof (edges) / sizeof (edges[0]); struct graph *graph = create_graph (edges, n); int i; for (i = 0; i < V; i++) { struct vertex *ptr = graph->point[i]; while (ptr != NULL) { printf ("(%d -> %d)\t", i, ptr->end); ptr = ptr->next; } printf ("\n"); } return 0; }
输出
(1 -> 3) (1 -> 0) (2 -> 1) (2 -> 0) (3 -> 2) (3 -> 0) (4 -> 2) (4 -> 1)
#include <bits/stdc++.h> using namespace std; #define V 5 // Maximum number of vertices in the graph struct graph { // declaring graph data structure struct vertex *point[V]; }; struct vertex { // declaring vertices int end; struct vertex *next; }; struct Edge { // declaring edges int end, start; }; struct graph *create_graph (struct Edge edges[], int x){ int i; struct graph *graph = (struct graph *) malloc (sizeof (struct graph)); for (i = 0; i < V; i++) { graph->point[i] = NULL; } for (i = 0; i < x; i++) { int start = edges[i].start; int end = edges[i].end; struct vertex *v = (struct vertex *) malloc (sizeof (struct vertex)); v->end = end; v->next = graph->point[start]; graph->point[start] = v; } return graph; } int main (){ struct Edge edges[] = { {0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 4}, {2, 4}, {2, 3}, {3, 1} }; int n = sizeof (edges) / sizeof (edges[0]); struct graph *graph = create_graph (edges, n); int i; for (i = 0; i < V; i++) { struct vertex *ptr = graph->point[i]; while (ptr != NULL) { cout << "(" << i << " -> " << ptr->end << ")\t"; ptr = ptr->next; } cout << endl; } return 0; }
输出
(1 -> 3) (1 -> 0) (2 -> 1) (2 -> 0) (3 -> 2) (3 -> 0) (4 -> 2) (4 -> 1)
import java.util.*; //class to store edges of the graph class Edge { int src, dest; Edge(int src, int dest) { this.src = src; this.dest = dest; } } // Graph class public class Graph { // node of adjacency list static class vertex { int v; vertex(int v) { this.v = v; } }; // define adjacency list to represent the graph List<List<vertex>> adj_list = new ArrayList<>(); //Graph Constructor public Graph(List<Edge> edges){ // adjacency list memory allocation for (int i = 0; i < edges.size(); i++) adj_list.add(i, new ArrayList<>()); // add edges to the graph for (Edge e : edges){ // allocate new node in adjacency List from src to dest adj_list.get(e.src).add(new vertex(e.dest)); } } public static void main (String[] args) { // define edges of the graph List<Edge> edges = Arrays.asList(new Edge(0, 1),new Edge(0, 2), new Edge(0, 3),new Edge(1, 2), new Edge(1, 4), new Edge(2, 4), new Edge(2, 3),new Edge(3, 1)); // call graph class Constructor to construct a graph Graph graph = new Graph(edges); // print the graph as an adjacency list int src = 0; int lsize = graph.adj_list.size(); System.out.println("The graph created is:"); while (src < lsize) { //traverse through the adjacency list and print the edges for (vertex edge : graph.adj_list.get(src)) { System.out.print(src + " -> " + edge.v + "\t"); } System.out.println(); src++; } } }
输出
The graph created is: 0 -> 1 0 -> 2 0 -> 3 1 -> 2 1 -> 4 2 -> 4 2 -> 3 3 -> 1
#Python code for Graph Data Struture V = 5 #Maximum number of vertices in th graph #Declaring vertices class Vertex: def __init__(self, end): self.end = end self.next = None #Declaring Edges class Edge: def __init__(self, start, end): self.start = start self.end = end #Declaring graph data structure class Graph: def __init__(self): self.point = [None] * V def create_graph(edges, x): graph = Graph() for i in range(V): graph.point[i] = None for i in range(x): start = edges[i].start end = edges[i].end v = Vertex(end) v.next = graph.point[start] graph.point[start] = v return graph edges = [Edge(0, 1), Edge(0, 2), Edge(0, 3), Edge(1, 2), Edge(1, 4), Edge(2, 4), Edge(2, 3), Edge(3, 1)] n = len(edges) graph = create_graph(edges, n) #Range for i in range(V): ptr = graph.point[i] while ptr is not None: print("({} -> {})".format(i, ptr.end), end="\t") ptr = ptr.next print()
输出
(0 -> 3) (0 -> 2) (0 -> 1) (1 -> 4) (1 -> 2) (2 -> 3) (2 -> 4) (3 -> 1)
深度优先遍历
深度优先搜索 (DFS) 算法以深度优先的方式遍历图,并使用栈来记住在任何迭代中遇到死胡同时要开始搜索的下一个顶点。
如上例所示,DFS 算法首先从 S 遍历到 A、D、G、E、B,然后到 F,最后到 C。它采用以下规则。
规则 1 - 访问相邻的未访问顶点。将其标记为已访问。显示它。将其压入栈中。
规则 2 - 如果未找到相邻顶点,则从栈中弹出顶点。(它将弹出栈中所有没有相邻顶点的顶点。)
规则 3 - 重复规则 1 和规则 2,直到栈为空。
步骤 | 遍历 | 描述 |
---|---|---|
1 | 初始化栈。 | |
2 | 将S标记为已访问并将其压入栈中。探索S的任何未访问的相邻节点。我们有三个节点,我们可以选择其中的任何一个。在本例中,我们将按照字母顺序选择节点。 | |
3 | 将A标记为已访问并将其压入栈中。探索A的任何未访问的相邻节点。S和D都与A相邻,但我们只关心未访问的节点。 | |
4 | 访问D,将其标记为已访问并压入栈中。这里,我们有B和C节点,它们与D相邻,并且都未被访问。但是,我们将再次按照字母顺序选择。 | |
5 | 我们选择B,将其标记为已访问并压入栈中。这里B没有任何未访问的相邻节点。因此,我们从栈中弹出B。 | |
6 | 我们检查栈顶以返回到前一个节点,并检查它是否具有任何未访问的节点。在这里,我们发现D位于栈顶。 | |
7 | 现在,D唯一的未访问的相邻节点是C。因此,我们访问C,将其标记为已访问并压入栈中。 |
由于C没有任何未访问的相邻节点,因此我们不断弹出栈,直到找到一个具有未访问的相邻节点的节点。在本例中,没有这样的节点,我们一直弹出直到栈为空。
示例
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define MAX 5 struct Vertex { char label; bool visited; }; //stack variables int stack[MAX]; int top = -1; //graph variables //array of vertices struct Vertex* lstVertices[MAX]; //adjacency matrix int adjMatrix[MAX][MAX]; //vertex count int vertexCount = 0; //stack functions void push(int item) { stack[++top] = item; } int pop() { return stack[top--]; } int peek() { return stack[top]; } bool isStackEmpty() { return top == -1; } //graph functions //add vertex to the vertex list void addVertex(char label) { struct Vertex* vertex = (struct Vertex*) malloc(sizeof(struct Vertex)); vertex->label = label; vertex->visited = false; lstVertices[vertexCount++] = vertex; } //add edge to edge array void addEdge(int start,int end) { adjMatrix[start][end] = 1; adjMatrix[end][start] = 1; } //display the vertex void displayVertex(int vertexIndex) { printf("%c ",lstVertices[vertexIndex]->label); } //get the adjacent unvisited vertex int getAdjUnvisitedVertex(int vertexIndex) { int i; for(i = 0; i < vertexCount; i++) { if(adjMatrix[vertexIndex][i] == 1 && lstVertices[i]->visited == false) { return i; } } return -1; } void depthFirstSearch() { int i; //mark first node as visited lstVertices[0]->visited = true; //display the vertex displayVertex(0); //push vertex index in stack push(0); while(!isStackEmpty()) { //get the unvisited vertex of vertex which is at top of the stack int unvisitedVertex = getAdjUnvisitedVertex(peek()); //no adjacent vertex found if(unvisitedVertex == -1) { pop(); } else { lstVertices[unvisitedVertex]->visited = true; displayVertex(unvisitedVertex); push(unvisitedVertex); } } //stack is empty, search is complete, reset the visited flag for(i = 0;i < vertexCount;i++) { lstVertices[i]->visited = false; } } int main() { int i, j; for(i = 0; i < MAX; i++) { // set adjacency for(j = 0; j < MAX; j++) // matrix to 0 adjMatrix[i][j] = 0; } addVertex('S'); // 0 addVertex('A'); // 1 addVertex('B'); // 2 addVertex('C'); // 3 addVertex('D'); // 4 addEdge(0, 1); // S - A addEdge(0, 2); // S - B addEdge(0, 3); // S - C addEdge(1, 4); // A - D addEdge(2, 4); // B - D addEdge(3, 4); // C - D printf("Depth First Search: "); depthFirstSearch(); return 0; }
输出
Depth First Search: S A D B C
//C++ code for Depth First Traversal #include <iostream> #include <array> #include <vector> constexpr int MAX = 5; struct Vertex { char label; bool visited; }; //stack variables std::array<int, MAX> stack; int top = -1; //graph variables //array of vertices std::array<Vertex*, MAX> lstVertices; //adjacency matrix std::array<std::array<int, MAX>, MAX> adjMatrix; //vertex count int vertexCount = 0; //stack functions void push(int item) { stack[++top] = item; } int pop() { return stack[top--]; } int peek() { return stack[top]; } bool isStackEmpty() { return top == -1; } //graph functions //add vertex to the vertex list void addVertex(char label) { Vertex* vertex = new Vertex; vertex->label = label; vertex->visited = false; lstVertices[vertexCount++] = vertex; } //add edge to edge array void addEdge(int start, int end) { adjMatrix[start][end] = 1; adjMatrix[end][start] = 1; } //display the vertex void displayVertex(int vertexIndex) { std::cout << lstVertices[vertexIndex]->label << " "; } //get the adjacent unvisited vertex int getAdjUnvisitedVertex(int vertexIndex) { for (int i = 0; i < vertexCount; i++) { if (adjMatrix[vertexIndex][i] == 1 && !lstVertices[i]->visited) { return i; } } return -1; } //mark first node as visited void depthFirstSearch() { lstVertices[0]->visited = true; //display the vertex displayVertex(0); //push vertex index in stack push(0); while (!isStackEmpty()) { //get the unvisited vertex of vertex which is at top of the stack int unvisitedVertex = getAdjUnvisitedVertex(peek()); //no adjacent vertex found if (unvisitedVertex == -1) { pop(); } else { lstVertices[unvisitedVertex]->visited = true; displayVertex(unvisitedVertex); push(unvisitedVertex); } } //stack is empty, search is complete, reset the visited flag for (int i = 0; i < vertexCount; i++) { lstVertices[i]->visited = false; } } int main() { for (int i = 0; i < MAX; i++) { //set adjacency for (int j = 0; j < MAX; j++) { // matrix to 0 adjMatrix[i][j] = 0; } } addVertex('S'); addVertex('A'); addVertex('B'); addVertex('C'); addVertex('D'); addEdge(0, 1); addEdge(0, 2); addEdge(0, 3); addEdge(1, 4); addEdge(2, 4); addEdge(3, 4); std::cout << "Depth First Search: "; depthFirstSearch(); return 0; }
输出
Depth First Search: S A D B C
//Java program for Depth First Traversal public class DepthFirstSearch { private static final int MAX = 5; private static class Vertex { char label; boolean visited; } private static int[] stack = new int[MAX]; private static int top = -1; private static Vertex[] lstVertices = new Vertex[MAX]; private static int[][] adjMatrix = new int[MAX][MAX]; private static int vertexCount = 0; private static void push(int item) { stack[++top] = item; } private static int pop() { return stack[top--]; } private static int peek() { return stack[top]; } private static boolean isStackEmpty() { return top == -1; } private static void addVertex(char label) { Vertex vertex = new Vertex(); vertex.label = label; vertex.visited = false; lstVertices[vertexCount++] = vertex; } private static void addEdge(int start, int end) { adjMatrix[start][end] = 1; adjMatrix[end][start] = 1; } private static void displayVertex(int vertexIndex) { System.out.print(lstVertices[vertexIndex].label + " "); } private static int getAdjUnvisitedVertex(int vertexIndex) { for (int i = 0; i < vertexCount; i++) { if (adjMatrix[vertexIndex][i] == 1 && !lstVertices[i].visited) { return i; } } return -1; } private static void depthFirstSearch() { lstVertices[0].visited = true; displayVertex(0); push(0); while (!isStackEmpty()) { int unvisitedVertex = getAdjUnvisitedVertex(peek()); if (unvisitedVertex == -1) { pop(); } else { lstVertices[unvisitedVertex].visited = true; displayVertex(unvisitedVertex); push(unvisitedVertex); } } for (int i = 0; i < vertexCount; i++) { lstVertices[i].visited = false; } } public static void main(String[] args) { for (int i = 0; i < MAX; i++) { for (int j = 0; j < MAX; j++) { adjMatrix[i][j] = 0; } } addVertex('S'); // 0 addVertex('A'); // 1 addVertex('B'); // 2 addVertex('C'); // 3 addVertex('D'); // 4 addEdge(0, 1); // S - A addEdge(0, 2); // S - B addEdge(0, 3); // S - C addEdge(1, 4); // A - D addEdge(2, 4); // B - D addEdge(3, 4); // C - D System.out.print("Depth First Search: "); depthFirstSearch(); } }
输出
Depth First Search: S A D B C
#Python program for Depth First Traversal MAX = 5 class Vertex: def __init__(self, label): self.label = label self.visited = False #stack variables stack = [] top = -1 #graph variables #array of vertices lstVertices = [None] * MAX #adjacency matrix adjMatrix = [[0] * MAX for _ in range(MAX)] #vertex count vertexCount = 0 #stack functions def push(item): global top top += 1 stack.append(item) def pop(): global top item = stack[top] del stack[top] top -= 1 return item def peek(): return stack[top] def isStackEmpty(): return top == -1 #graph functions #add vertex to the vertex list def addVertex(label): global vertexCount vertex = Vertex(label) lstVertices[vertexCount] = vertex vertexCount += 1 #add edge to edge array def addEdge(start, end): adjMatrix[start][end] = 1 adjMatrix[end][start] = 1 #Display the Vertex def displayVertex(vertexIndex): print(lstVertices[vertexIndex].label, end=' ') def getAdjUnvisitedVertex(vertexIndex): for i in range(vertexCount): if adjMatrix[vertexIndex][i] == 1 and not lstVertices[i].visited: return i return -1 def depthFirstSearch(): lstVertices[0].visited = True displayVertex(0) push(0) while not isStackEmpty(): unvisitedVertex = getAdjUnvisitedVertex(peek()) if unvisitedVertex == -1: pop() else: lstVertices[unvisitedVertex].visited = True displayVertex(unvisitedVertex) push(unvisitedVertex) for i in range(vertexCount): lstVertices[i].visited = False for i in range(MAX): for j in range(MAX): adjMatrix[i][j] = 0 addVertex('S') # 0 addVertex('A') # 1 addVertex('B') # 2 addVertex('C') # 3 addVertex('D') # 4 addEdge(0, 1) # S - A addEdge(0, 2) # S - B addEdge(0, 3) # S - C addEdge(1, 4) # A - D addEdge(2, 4) # B - D addEdge(3, 4) # C - D print("Depth First Search:", end=' ') depthFirstSearch()
输出
Depth First Search: S A D B C
广度优先遍历
广度优先搜索 (BFS) 算法以广度优先的方式遍历图,并使用队列来记住在任何迭代中遇到死胡同时要开始搜索的下一个顶点。
如上例所示,BFS 算法首先从 A 遍历到 B、E、F,然后到 C 和 G,最后到 D。它采用以下规则。
规则 1 - 访问相邻的未访问顶点。将其标记为已访问。显示它。将其插入队列中。
规则 2 - 如果未找到相邻顶点,则从队列中删除第一个顶点。
规则 3 - 重复规则 1 和规则 2,直到队列为空。
步骤 | 遍历 | 描述 |
---|---|---|
1 | 初始化队列。 | |
2 | 我们从访问S(起始节点)开始,并将其标记为已访问。 | |
3 | 然后我们看到S的一个未访问的相邻节点。在本例中,我们有三个节点,但按照字母顺序我们选择A,将其标记为已访问并将其入队。 | |
4 | 接下来,S的未访问的相邻节点是B。我们将其标记为已访问并将其入队。 | |
5 | 接下来,S的未访问的相邻节点是C。我们将其标记为已访问并将其入队。 | |
6 | 现在,S没有未访问的相邻节点了。因此,我们出队并找到A。 | |
7 | 从A我们有D作为未访问的相邻节点。我们将其标记为已访问并将其入队。 |
在这个阶段,我们没有未标记(未访问)的节点了。但根据算法,我们继续出队以获取所有未访问的节点。当队列清空时,程序结束。
示例
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define MAX 5 struct Vertex { char label; bool visited; }; //queue variables int queue[MAX]; int rear = -1; int front = 0; int queueItemCount = 0; //graph variables //array of vertices struct Vertex* lstVertices[MAX]; //adjacency matrix int adjMatrix[MAX][MAX]; //vertex count int vertexCount = 0; //queue functions void insert(int data) { queue[++rear] = data; queueItemCount++; } int removeData() { queueItemCount--; return queue[front++]; } bool isQueueEmpty() { return queueItemCount == 0; } //graph functions //add vertex to the vertex list void addVertex(char label) { struct Vertex* vertex = (struct Vertex*) malloc(sizeof(struct Vertex)); vertex->label = label; vertex->visited = false; lstVertices[vertexCount++] = vertex; } //add edge to edge array void addEdge(int start,int end) { adjMatrix[start][end] = 1; adjMatrix[end][start] = 1; } //display the vertex void displayVertex(int vertexIndex) { printf("%c ",lstVertices[vertexIndex]->label); } //get the adjacent unvisited vertex int getAdjUnvisitedVertex(int vertexIndex) { int i; for(i = 0; i<vertexCount; i++) { if(adjMatrix[vertexIndex][i] == 1 && lstVertices[i]->visited == false) return i; } return -1; } void breadthFirstSearch() { int i; //mark first node as visited lstVertices[0]->visited = true; //display the vertex displayVertex(0); //insert vertex index in queue insert(0); int unvisitedVertex; while(!isQueueEmpty()) { //get the unvisited vertex of vertex which is at front of the queue int tempVertex = removeData(); //no adjacent vertex found while((unvisitedVertex = getAdjUnvisitedVertex(tempVertex)) != -1) { lstVertices[unvisitedVertex]->visited = true; displayVertex(unvisitedVertex); insert(unvisitedVertex); } } //queue is empty, search is complete, reset the visited flag for(i = 0;i<vertexCount;i++) { lstVertices[i]->visited = false; } } int main() { int i, j; for(i = 0; i<MAX; i++) { // set adjacency for(j = 0; j<MAX; j++) // matrix to 0 adjMatrix[i][j] = 0; } addVertex('S'); // 0 addVertex('A'); // 1 addVertex('B'); // 2 addVertex('C'); // 3 addVertex('D'); // 4 addEdge(0, 1); // S - A addEdge(0, 2); // S - B addEdge(0, 3); // S - C addEdge(1, 4); // A - D addEdge(2, 4); // B - D addEdge(3, 4); // C - D printf("\nBreadth First Search: "); breadthFirstSearch(); return 0; }
输出
Breadth First Search: S A B C D
//C++ code for Breadth First Traversal #include <iostream> #include <stdlib.h> #include <stdbool.h> #define MAX 5 struct Vertex { char label; bool visited; }; //queue variables int queue[MAX]; int rear = -1; int front = 0; int queueItemCount = 0; //graph variables //array of vertices struct Vertex* lstVertices[MAX]; //adjacency matrix int adjMatrix[MAX][MAX]; //vertex count int vertexCount = 0; //queue functions void insert(int data) { queue[++rear] = data; queueItemCount++; } int removeData() { queueItemCount--; return queue[front++]; } bool isQueueEmpty() { return queueItemCount == 0; } //graph functions //add vertex to the vertex list void addVertex(char label) { struct Vertex* vertex = (struct Vertex*) malloc(sizeof(struct Vertex)); vertex->label = label; vertex->visited = false; lstVertices[vertexCount++] = vertex; } //add edge to edge array void addEdge(int start,int end) { adjMatrix[start][end] = 1; adjMatrix[end][start] = 1; } //display the vertex void displayVertex(int vertexIndex) { std::cout << lstVertices[vertexIndex]->label << " "; } //get the adjacent unvisited vertex int getAdjUnvisitedVertex(int vertexIndex) { int i; for(i = 0; i<vertexCount; i++) { if(adjMatrix[vertexIndex][i] == 1 && lstVertices[i]->visited == false) return i; } return -1; } void breadthFirstSearch() { int i; //mark first node as visited lstVertices[0]->visited = true; //display the vertex displayVertex(0); //insert vertex index in queue insert(0); int unvisitedVertex; while(!isQueueEmpty()) { //get the unvisited vertex of vertex which is at front of the queue int tempVertex = removeData(); //no adjacent vertex found while((unvisitedVertex = getAdjUnvisitedVertex(tempVertex)) != -1) { lstVertices[unvisitedVertex]->visited = true; displayVertex(unvisitedVertex); insert(unvisitedVertex); } } //queue is empty, search is complete, reset the visited flag for(i = 0;i<vertexCount;i++) { lstVertices[i]->visited = false; } } int main() { int i, j; for(i = 0; i<MAX; i++) { // set adjacency for(j = 0; j<MAX; j++) // matrix to 0 adjMatrix[i][j] = 0; } addVertex('S'); // 0 addVertex('A'); // 1 addVertex('B'); // 2 addVertex('C'); // 3 addVertex('D'); // 4 addEdge(0, 1); // S - A addEdge(0, 2); // S - B addEdge(0, 3); // S - C addEdge(1, 4); // A - D addEdge(2, 4); // B - D addEdge(3, 4); // C - D std::cout << "Breadth First Search: "; breadthFirstSearch(); return 0; }
输出
Breadth First Search: S A B C D
//Java code for Breadth First Traversal import java.util.LinkedList; import java.util.Queue; class Vertex { char label; boolean visited; public Vertex(char label) { this.label = label; visited = false; } } public class Graph { private static final int MAX = 5; private Vertex[] lstVertices; private int[][] adjMatrix; private int vertexCount; public Graph() { lstVertices = new Vertex[MAX]; adjMatrix = new int[MAX][MAX]; vertexCount = 0; } private void addVertex(char label) { Vertex vertex = new Vertex(label); lstVertices[vertexCount++] = vertex; } private void addEdge(int start, int end) { adjMatrix[start][end] = 1; adjMatrix[end][start] = 1; } private void displayVertex(int vertexIndex) { System.out.print(lstVertices[vertexIndex].label + " "); } private int getAdjUnvisitedVertex(int vertexIndex) { for (int i = 0; i < vertexCount; i++) { if (adjMatrix[vertexIndex][i] == 1 && !lstVertices[i].visited) return i; } return -1; } private void breadthFirstSearch() { lstVertices[0].visited = true; displayVertex(0); Queue<Integer> queue = new LinkedList<>(); queue.add(0); while (!queue.isEmpty()) { int tempVertex = queue.poll(); int unvisitedVertex; while ((unvisitedVertex = getAdjUnvisitedVertex(tempVertex)) != -1) { lstVertices[unvisitedVertex].visited = true; displayVertex(unvisitedVertex); queue.add(unvisitedVertex); } } // Reset the visited flag for (int i = 0; i < vertexCount; i++) { lstVertices[i].visited = false; } } public static void main(String[] args) { Graph graph = new Graph(); for (int i = 0; i < MAX; i++) { for (int j = 0; j < MAX; j++) graph.adjMatrix[i][j] = 0; } graph.addVertex('S'); // 0 graph.addVertex('A'); // 1 graph.addVertex('B'); // 2 graph.addVertex('C'); // 3 graph.addVertex('D'); // 4 graph.addEdge(0, 1); // S - A graph.addEdge(0, 2); // S - B graph.addEdge(0, 3); // S - C graph.addEdge(1, 4); // A - D graph.addEdge(2, 4); // B - D graph.addEdge(3, 4); // C - D System.out.print("Breadth First Search: "); graph.breadthFirstSearch(); } }
输出
Breadth First Search: S A B C D
#Python program for Breadth First Search # defining MAX 5 MAX = 5 class Vertex: def __init__(self, label): self.label = label self.visited = False # queue variables queue = [0] * MAX rear = -1 front = 0 queueItemCount = 0 # graph variables #array of vertices lstVertices = [None] * MAX #adjacency matrix adjMatrix = [[0] * MAX for _ in range(MAX)] #vertex count vertexCount = 0 # queue functions def insert(data): global rear, queueItemCount rear += 1 queue[rear] = data queueItemCount += 1 def removeData(): global front, queueItemCount queueItemCount -= 1 data = queue[front] front += 1 return data def isQueueEmpty(): return queueItemCount == 0 # graph functions #add vertex to the vertex list def addVertex(label): global vertexCount vertex = Vertex(label) lstVertices[vertexCount] = vertex vertexCount += 1 #add edge to edge array def addEdge(start, end): adjMatrix[start][end] = 1 adjMatrix[end][start] = 1 #Display the vertex def displayVertex(vertexIndex): print(lstVertices[vertexIndex].label, end=" ") #Get the adjacent unvisited vertex def getAdjUnvisitedVertex(vertexIndex): for i in range(vertexCount): if adjMatrix[vertexIndex][i] == 1 and not lstVertices[i].visited: return i return -1 def breadthFirstSearch(): #mark first node as visited lstVertices[0].visited = True #Display the vertex displayVertex(0) #insert vertex index in queue insert(0) while not isQueueEmpty(): #get the unvisited vertex of vertex which is at front of the queue tempVertex = removeData() #no adjacent vertex found unvisitedVertex = getAdjUnvisitedVertex(tempVertex) while unvisitedVertex != -1: lstVertices[unvisitedVertex].visited = True displayVertex(unvisitedVertex) insert(unvisitedVertex) unvisitedVertex = getAdjUnvisitedVertex(tempVertex) #queue is empty, search is complete, reset the visited flag for i in range(vertexCount): lstVertices[i].visited = False # main function if __name__ == "__main__": #set adjacency for i in range(MAX): #matrix to 0 for j in range(MAX): adjMatrix[i][j] = 0 addVertex('S') addVertex('A') addVertex('B') addVertex('C') addVertex('D') addEdge(0, 1) addEdge(0, 2) addEdge(0, 3) addEdge(1, 4) addEdge(2, 4) addEdge(3, 4) print("Breadth First Search: ", end="") breadthFirstSearch()
输出
Breadth First Search: S A B C D
生成树
生成树是图 G 的一个子集,它覆盖了所有顶点,并且边数最少。因此,生成树不包含环,并且不能断开连接。
根据此定义,我们可以得出结论,每个连通的无向图 G 至少有一棵生成树。断开的图没有任何生成树,因为它无法扩展到其所有顶点。
我们发现了一个完整图的三棵生成树。一个完整的无向图最多可以有nn-2棵生成树,其中n是节点数。在上述示例中,n 为 3,因此33−2 = 3棵生成树是可能的。
生成树的一般性质
现在我们理解了一个图可以有多棵生成树。以下是与图 G 相连的生成树的一些属性:
一个连通图 G 可以有多棵生成树。
图 G 的所有可能的生成树都具有相同数量的边和顶点。
生成树不包含任何环(回路)。
从生成树中移除一条边将使图断开连接,即生成树是最小连通的。
向生成树中添加一条边将创建一个回路或环,即生成树是最大无环的。
生成树的数学性质
生成树有n-1条边,其中n是节点(顶点)的数量。
从一个完整图中,通过移除最多e - n + 1条边,我们可以构建一棵生成树。
一个完整图最多可以有nn-2棵生成树。
因此,我们可以得出结论,生成树是连通图 G 的子集,而断开的图没有生成树。
生成树的应用
生成树基本上用于查找连接图中所有节点的最小路径。生成树的常见应用包括:
民用网络规划
计算机网络路由协议
聚类分析
让我们通过一个小例子来理解这一点。假设,城市网络是一个巨大的图,现在计划以最少的线路部署电话线,以便连接到所有城市节点。这就是生成树发挥作用的地方。
最小生成树 (MST)
在加权图中,最小生成树是指权重小于同一图所有其他生成树的生成树。在现实世界中,该权重可以衡量为距离、拥塞、交通负荷或分配给边的任何任意值。
最小生成树算法
我们将在这里学习两种最重要的生成树算法:
两者都是贪心算法。
树数据结构
树是一种非线性抽象数据类型,具有基于层次结构的结构。它由节点(数据存储的地方)组成,这些节点通过链接连接。树数据结构源于一个称为根节点的单个节点,并且具有连接到根的子树。
重要术语
以下是关于树的一些重要术语。
路径 - 路径指的是沿着树的边上的节点序列。
根 - 树顶部的节点称为根。每棵树只有一个根,并且从根节点到任何节点只有一条路径。
父节点 - 除根节点之外的任何节点都有一条向上连接到称为父节点的节点的边。
子节点 - 下方通过其向下边连接的给定节点称为其子节点。
叶子节点 - 没有子节点的节点称为叶子节点。
子树 - 子树表示节点的后代。
访问 - 访问是指当控制权在节点上时检查节点的值。
遍历 - 遍历意味着按特定顺序穿过节点。
层级 - 节点的层级表示节点的代数。如果根节点在第 0 层,则其下一个子节点在第 1 层,其孙子节点在第 2 层,依此类推。
键 - 键表示节点的值,基于该值将对节点执行搜索操作。
树的类型
树有三种类型:
一般树
二叉树
二叉搜索树
一般树
一般树是无序的树形数据结构,其中根节点至少有 0 个或最多有 'n' 个子树。
一般树对它们的层次结构没有约束。因此,根节点充当所有其他子树的超集。
二叉树
二叉树是一般树,其中根节点最多只能包含 2 个子树:左子树和右子树。根据子节点的数量,二叉树分为三种类型。
满二叉树
满二叉树是一种二叉树类型,其中每个节点要么有 0 个,要么有 2 个子节点。
完全二叉树
完全二叉树是一种二叉树类型,其中所有叶子节点都必须在同一层级。但是,完全二叉树中的根节点和内部节点可以有 0、1 或 2 个子节点。
完美二叉树
完美二叉树是一种二叉树类型,其中所有叶子节点都在同一层级,并且除叶子节点之外的每个节点都有 2 个子节点。
二叉搜索树
二叉搜索树拥有二叉树的所有属性,包括一些基于某些约束的自身额外属性,使其比二叉树更有效率。
二叉搜索树 (BST) 中的数据始终以这样的方式存储:左子树中的值始终小于根节点中的值,而右子树中的值始终大于根节点中的值,即左子树 < 根节点 ≤ 右子树。
BST 的优点
二叉搜索树比二叉树更有效率,因为执行各种操作的时间复杂度降低了。
由于键的顺序仅基于父节点,因此搜索操作变得更简单。
BST 的对齐方式也有利于范围查询,范围查询用于查找两个键之间存在的值。这有助于数据库管理系统。
BST 的缺点
二叉搜索树的主要缺点是,如果节点中的所有元素都大于或小于根节点,树将变得倾斜。简单来说,树完全向一边倾斜。
这种倾斜将使树成为一个链表而不是 BST,因为搜索操作的最坏情况时间复杂度变为 O(n)。
为了克服二叉搜索树中倾斜的问题,引入了平衡二叉搜索树的概念。
平衡二叉搜索树
考虑一个二叉搜索树,其中左子树的高度为 'm',右子树的高度为 'n'。如果 (m-n) 的值等于 0、1 或 -1,则该树被称为平衡二叉搜索树。
树的设计方式是,一旦高度差超过 1,它们就会自动平衡。二叉搜索树使用旋转作为自动平衡算法。旋转有四种不同的类型:左左、右右、左右、右左。
有各种类型的自平衡二叉搜索树:
AVL 树
红黑树
B 树
B+ 树
伸展树
优先搜索树
树的遍历
遍历是一个访问树的所有节点并可能打印其值的流程。因为所有节点都通过边(链接)连接,所以我们始终从根(头部)节点开始。也就是说,我们不能随机访问树中的节点。我们使用三种方法来遍历树:
中序遍历
前序遍历
后序遍历
通常,我们遍历树是为了搜索或定位树中给定的项目或键,或者打印它包含的所有值。
中序遍历
在这种遍历方法中,首先访问左子树,然后访问根,最后访问右子树。我们应该始终记住,每个节点本身可能表示一个子树。
如果二叉树中序遍历,输出将产生按升序排序的键值。
我们从A开始,按照中序遍历,我们移动到它的左子树B。B也进行中序遍历。此过程一直持续到访问所有节点。这棵树的中序遍历输出将是:
D → B → E → A → F → C → G
算法
直到所有节点都被遍历:
步骤 1 - 递归遍历左子树。
步骤 2 - 访问根节点。
步骤 3 - 递归遍历右子树。
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <stdlib.h> struct node { int data; struct node *leftChild; struct node *rightChild; }; struct node *root = NULL; void insert(int data){ struct node *tempNode = (struct node*) malloc(sizeof(struct node)); struct node *current; struct node *parent; tempNode->data = data; tempNode->leftChild = NULL; tempNode->rightChild = NULL; //if tree is empty if(root == NULL) { root = tempNode; } else { current = root; parent = NULL; while(1) { parent = current; //go to left of the tree if(data < parent->data) { current = current->leftChild; //insert to the left if(current == NULL) { parent->leftChild = tempNode; return; } }//go to right of the tree else { current = current->rightChild; //insert to the right if(current == NULL) { parent->rightChild = tempNode; return; } } } } } void inorder_traversal(struct node* root){ if(root != NULL) { inorder_traversal(root->leftChild); printf("%d ",root->data); inorder_traversal(root->rightChild); } } int main(){ int i; int array[7] = { 27, 14, 35, 10, 19, 31, 42 }; for(i = 0; i < 7; i++) insert(array[i]); printf("\nInorder traversal: "); inorder_traversal(root); return 0; }
输出
Inorder traversal: 10 14 19 27 31 35 42
#include <iostream> struct node { int data; struct node *leftChild; struct node *rightChild; }; struct node *root = NULL; void insert(int data){ struct node *tempNode = (struct node*) malloc(sizeof(struct node)); struct node *current; struct node *parent; tempNode->data = data; tempNode->leftChild = NULL; tempNode->rightChild = NULL; //if tree is empty if(root == NULL) { root = tempNode; } else { current = root; parent = NULL; while(1) { parent = current; //go to left of the tree if(data < parent->data) { current = current->leftChild; //insert to the left if(current == NULL) { parent->leftChild = tempNode; return; } }//go to right of the tree else { current = current->rightChild; //insert to the right if(current == NULL) { parent->rightChild = tempNode; return; } } } } } void inorder_traversal(struct node* root){ if(root != NULL) { inorder_traversal(root->leftChild); printf("%d ",root->data); inorder_traversal(root->rightChild); } } int main(){ int i; int array[7] = { 27, 14, 35, 10, 19, 31, 42 }; for(i = 0; i < 7; i++) insert(array[i]); printf("\nInorder traversal: "); inorder_traversal(root); return 0; }
输出
Inorder traversal: 10 14 19 27 31 35 42
class Node { int data; Node leftChild; Node rightChild; public Node(int key) { data = key; leftChild = rightChild = null; } } public class TreeDataStructure { Node root = null; void inorder_traversal(Node node) { if(node != null) { inorder_traversal(node.leftChild); System.out.print(node.data + " "); inorder_traversal(node.rightChild); } } public static void main(String args[]) { TreeDataStructure tree = new TreeDataStructure(); tree.root = new Node(27); tree.root.leftChild = new Node(12); tree.root.rightChild = new Node(3); tree.root.leftChild.leftChild = new Node(44); tree.root.leftChild.rightChild = new Node(17); tree.root.rightChild.leftChild = new Node(56); System.out.println("\nInorder traversal: "); tree.inorder_traversal(tree.root); } }
输出
Inorder traversal: 44 12 17 27 56 3
class Node: def __init__(self, key): self.leftChild = None self.rightChild = None self.data = key # Create a function to perform inorder tree traversal def InorderTraversal(root): if root: InorderTraversal(root.leftChild) print(root.data) InorderTraversal(root.rightChild) # Main class if __name__ == "__main__": root = Node(3) root.leftChild = Node(26) root.rightChild = Node(42) root.leftChild.leftChild = Node(54) root.leftChild.rightChild = Node(65) root.rightChild.leftChild = Node(12) # Function call print("\nInorder traversal of binary tree is") InorderTraversal(root)
输出
Inorder traversal of binary tree is 54 26 65 3 12 42
前序遍历
在这种遍历方法中,首先访问根节点,然后访问左子树,最后访问右子树。
我们从A开始,按照前序遍历,我们首先访问A本身,然后移动到它的左子树B。B也进行前序遍历。此过程一直持续到访问所有节点。这棵树的前序遍历输出将是:
A → B → D → E → C → F → G
算法
直到所有节点都被遍历:
步骤 1 - 访问根节点。
步骤 2 - 递归遍历左子树。
步骤 3 - 递归遍历右子树。
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <stdlib.h> struct node { int data; struct node *leftChild; struct node *rightChild; }; struct node *root = NULL; void insert(int data){ struct node *tempNode = (struct node*) malloc(sizeof(struct node)); struct node *current; struct node *parent; tempNode->data = data; tempNode->leftChild = NULL; tempNode->rightChild = NULL; //if tree is empty if(root == NULL) { root = tempNode; } else { current = root; parent = NULL; while(1) { parent = current; //go to left of the tree if(data < parent->data) { current = current->leftChild; //insert to the left if(current == NULL) { parent->leftChild = tempNode; return; } }//go to right of the tree else { current = current->rightChild; //insert to the right if(current == NULL) { parent->rightChild = tempNode; return; } } } } } void pre_order_traversal(struct node* root){ if(root != NULL) { printf("%d ",root->data); pre_order_traversal(root->leftChild); pre_order_traversal(root->rightChild); } } int main(){ int i; int array[7] = { 27, 14, 35, 10, 19, 31, 42 }; for(i = 0; i < 7; i++) insert(array[i]); printf("\nPreorder traversal: "); pre_order_traversal(root); return 0; }
输出
Preorder traversal: 27 14 10 19 35 31 42
#include <iostream> struct node { int data; struct node *leftChild; struct node *rightChild; }; struct node *root = NULL; void insert(int data){ struct node *tempNode = (struct node*) malloc(sizeof(struct node)); struct node *current; struct node *parent; tempNode->data = data; tempNode->leftChild = NULL; tempNode->rightChild = NULL; //if tree is empty if(root == NULL) { root = tempNode; } else { current = root; parent = NULL; while(1) { parent = current; //go to left of the tree if(data < parent->data) { current = current->leftChild; //insert to the left if(current == NULL) { parent->leftChild = tempNode; return; } }//go to right of the tree else { current = current->rightChild; //insert to the right if(current == NULL) { parent->rightChild = tempNode; return; } } } } } void pre_order_traversal(struct node* root){ if(root != NULL) { printf("%d ",root->data); pre_order_traversal(root->leftChild); pre_order_traversal(root->rightChild); } } int main(){ int i; int array[7] = { 27, 14, 35, 10, 19, 31, 42 }; for(i = 0; i < 7; i++) insert(array[i]); printf("\nPreorder traversal: "); pre_order_traversal(root); return 0; }
输出
Preorder traversal: 27 14 10 19 35 31 42
class Node { int data; Node leftChild; Node rightChild; public Node(int key) { data = key; leftChild = rightChild = null; } } public class TreeDataStructure { Node root = null; void pre_order_traversal(Node node) { if(node != null) { System.out.print(node.data + " "); pre_order_traversal(node.leftChild); pre_order_traversal(node.rightChild); } } public static void main(String args[]) { TreeDataStructure tree = new TreeDataStructure(); tree.root = new Node(27); tree.root.leftChild = new Node(12); tree.root.rightChild = new Node(3); tree.root.leftChild.leftChild = new Node(44); tree.root.leftChild.rightChild = new Node(17); tree.root.rightChild.leftChild = new Node(56); System.out.println("\nPreorder traversal: "); tree.pre_order_traversal(tree.root); } }
输出
Preorder traversal: 27 12 44 17 3 56
class Node: def __init__(self, key): self.leftChild = None self.rightChild = None self.data = key # Create a function to perform postorder tree traversal def PreorderTraversal(root): if root: print(root.data) PreorderTraversal(root.leftChild) PreorderTraversal(root.rightChild) # Main class if __name__ == "__main__": root = Node(3) root.leftChild = Node(26) root.rightChild = Node(42) root.leftChild.leftChild = Node(54) root.leftChild.rightChild = Node(65) root.rightChild.leftChild = Node(12) print("\nPreorder traversal of binary tree is") PreorderTraversal(root)
输出
Preorder traversal of binary tree is 3 26 54 65 42 12
后序遍历
在这种遍历方法中,最后访问根节点,因此得名。我们首先遍历左子树,然后遍历右子树,最后遍历根节点。
我们从A开始,按照前序遍历,我们首先访问左子树B。B也进行后序遍历。此过程一直持续到访问所有节点。这棵树的后序遍历输出将是:
D → E → B → F → G → C → A
算法
直到所有节点都被遍历:
步骤 1 - 递归遍历左子树。
步骤 2 - 递归遍历右子树。
步骤 3 - 访问根节点。
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <stdlib.h> struct node { int data; struct node *leftChild; struct node *rightChild; }; struct node *root = NULL; void insert(int data){ struct node *tempNode = (struct node*) malloc(sizeof(struct node)); struct node *current; struct node *parent; tempNode->data = data; tempNode->leftChild = NULL; tempNode->rightChild = NULL; //if tree is empty if(root == NULL) { root = tempNode; } else { current = root; parent = NULL; while(1) { parent = current; //go to left of the tree if(data < parent->data) { current = current->leftChild; //insert to the left if(current == NULL) { parent->leftChild = tempNode; return; } }//go to right of the tree else { current = current->rightChild; //insert to the right if(current == NULL) { parent->rightChild = tempNode; return; } } } } } void post_order_traversal(struct node* root){ if(root != NULL) { post_order_traversal(root->leftChild); post_order_traversal(root->rightChild); printf("%d ", root->data); } } int main(){ int i; int array[7] = { 27, 14, 35, 10, 19, 31, 42 }; for(i = 0; i < 7; i++) insert(array[i]); printf("\nPost order traversal: "); post_order_traversal(root); return 0; }
输出
Post order traversal: 10 19 14 31 42 35 27
#include <iostream> struct node { int data; struct node *leftChild; struct node *rightChild; }; struct node *root = NULL; void insert(int data){ struct node *tempNode = (struct node*) malloc(sizeof(struct node)); struct node *current; struct node *parent; tempNode->data = data; tempNode->leftChild = NULL; tempNode->rightChild = NULL; //if tree is empty if(root == NULL) { root = tempNode; } else { current = root; parent = NULL; while(1) { parent = current; //go to left of the tree if(data < parent->data) { current = current->leftChild; //insert to the left if(current == NULL) { parent->leftChild = tempNode; return; } }//go to right of the tree else { current = current->rightChild; //insert to the right if(current == NULL) { parent->rightChild = tempNode; return; } } } } } void post_order_traversal(struct node* root){ if(root != NULL) { post_order_traversal(root->leftChild); post_order_traversal(root->rightChild); printf("%d ", root->data); } } int main(){ int i; int array[7] = { 27, 14, 35, 10, 19, 31, 42 }; for(i = 0; i < 7; i++) insert(array[i]); printf("\nPost order traversal: "); post_order_traversal(root); return 0; }
输出
Post order traversal: 10 19 14 31 42 35 27
class Node { int data; Node leftChild; Node rightChild; public Node(int key) { data = key; leftChild = rightChild = null; } } public class TreeDataStructure { Node root = null; void post_order_traversal(Node node) { if(node != null) { post_order_traversal(node.leftChild); post_order_traversal(node.rightChild); System.out.print(node.data + " "); } } public static void main(String args[]) { TreeDataStructure tree = new TreeDataStructure(); tree.root = new Node(27); tree.root.leftChild = new Node(12); tree.root.rightChild = new Node(3); tree.root.leftChild.leftChild = new Node(44); tree.root.leftChild.rightChild = new Node(17); tree.root.rightChild.leftChild = new Node(56); System.out.println("\nPost order traversal: "); tree.post_order_traversal(tree.root); } }
输出
Post order traversal: 44 17 12 56 3 27
class Node: def __init__(self, key): self.leftChild = None self.rightChild = None self.data = key # Create a function to perform preorder tree traversal def PostorderTraversal(root): if root: PostorderTraversal(root.leftChild) PostorderTraversal(root.rightChild) print(root.data) # Main class if __name__ == "__main__": root = Node(3) root.leftChild = Node(26) root.rightChild = Node(42) root.leftChild.leftChild = Node(54) root.leftChild.rightChild = Node(65) root.rightChild.leftChild = Node(12) print("\nPostorder traversal of binary tree is") PostorderTraversal(root)
输出
Postorder traversal of binary tree is 54 65 26 12 42 3
要检查树遍历的 C 语言实现,请点击此处
实现
遍历是一个访问树的所有节点并可能打印其值的流程。因为所有节点都通过边(链接)连接,所以我们始终从根(头部)节点开始。也就是说,我们不能随机访问树中的节点。我们使用三种方法来遍历树:
中序遍历
前序遍历
后序遍历
我们现在将在这里看到使用以下二叉树在 C 编程语言中实现树遍历:
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <stdlib.h> struct node { int data; struct node *leftChild; struct node *rightChild; }; struct node *root = NULL; void insert(int data){ struct node *tempNode = (struct node*) malloc(sizeof(struct node)); struct node *current; struct node *parent; tempNode->data = data; tempNode->leftChild = NULL; tempNode->rightChild = NULL; //if tree is empty if(root == NULL) { root = tempNode; } else { current = root; parent = NULL; while(1) { parent = current; //go to left of the tree if(data < parent->data) { current = current->leftChild; //insert to the left if(current == NULL) { parent->leftChild = tempNode; return; } }//go to right of the tree else { current = current->rightChild; //insert to the right if(current == NULL) { parent->rightChild = tempNode; return; } } } } } void pre_order_traversal(struct node* root){ if(root != NULL) { printf("%d ",root->data); pre_order_traversal(root->leftChild); pre_order_traversal(root->rightChild); } } void inorder_traversal(struct node* root){ if(root != NULL) { inorder_traversal(root->leftChild); printf("%d ",root->data); inorder_traversal(root->rightChild); } } void post_order_traversal(struct node* root){ if(root != NULL) { post_order_traversal(root->leftChild); post_order_traversal(root->rightChild); printf("%d ", root->data); } } int main(){ int i; int array[7] = { 27, 14, 35, 10, 19, 31, 42 }; for(i = 0; i < 7; i++) insert(array[i]); printf("\nPreorder traversal: "); pre_order_traversal(root); printf("\nInorder traversal: "); inorder_traversal(root); printf("\nPost order traversal: "); post_order_traversal(root); return 0; }
输出
Preorder traversal: 27 14 10 19 35 31 42 Inorder traversal: 10 14 19 27 31 35 42 Post order traversal: 10 19 14 31 42 35 27
#include <iostream> struct node { int data; struct node *leftChild; struct node *rightChild; }; struct node *root = NULL; void insert(int data){ struct node *tempNode = (struct node*) malloc(sizeof(struct node)); struct node *current; struct node *parent; tempNode->data = data; tempNode->leftChild = NULL; tempNode->rightChild = NULL; //if tree is empty if(root == NULL) { root = tempNode; } else { current = root; parent = NULL; while(1) { parent = current; //go to left of the tree if(data < parent->data) { current = current->leftChild; //insert to the left if(current == NULL) { parent->leftChild = tempNode; return; } }//go to right of the tree else { current = current->rightChild; //insert to the right if(current == NULL) { parent->rightChild = tempNode; return; } } } } } void pre_order_traversal(struct node* root){ if(root != NULL) { printf("%d ",root->data); pre_order_traversal(root->leftChild); pre_order_traversal(root->rightChild); } } void inorder_traversal(struct node* root){ if(root != NULL) { inorder_traversal(root->leftChild); printf("%d ",root->data); inorder_traversal(root->rightChild); } } void post_order_traversal(struct node* root){ if(root != NULL) { post_order_traversal(root->leftChild); post_order_traversal(root->rightChild); printf("%d ", root->data); } } int main(){ int i; int array[7] = { 27, 14, 35, 10, 19, 31, 42 }; for(i = 0; i < 7; i++) insert(array[i]); printf("\nPreorder traversal: "); pre_order_traversal(root); printf("\nInorder traversal: "); inorder_traversal(root); printf("\nPost order traversal: "); post_order_traversal(root); return 0; }
输出
Preorder traversal: 27 14 10 19 35 31 42 Inorder traversal: 10 14 19 27 31 35 42 Post order traversal: 10 19 14 31 42 35 27
class Node { int data; Node leftChild; Node rightChild; public Node(int key) { data = key; leftChild = rightChild = null; } } public class TreeDataStructure { Node root = null; void inorder_traversal(Node node) { if(node != null) { inorder_traversal(node.leftChild); System.out.print(node.data + " "); inorder_traversal(node.rightChild); } } void pre_order_traversal(Node node) { if(node != null) { System.out.print(node.data + " "); pre_order_traversal(node.leftChild); pre_order_traversal(node.rightChild); } } void post_order_traversal(Node node) { if(node != null) { post_order_traversal(node.leftChild); post_order_traversal(node.rightChild); System.out.print(node.data + " "); } } public static void main(String args[]) { TreeDataStructure tree = new TreeDataStructure(); tree.root = new Node(27); tree.root.leftChild = new Node(12); tree.root.rightChild = new Node(3); tree.root.leftChild.leftChild = new Node(44); tree.root.leftChild.rightChild = new Node(17); tree.root.rightChild.leftChild = new Node(56); System.out.println("\nInorder traversal: "); tree.inorder_traversal(tree.root); System.out.println("\nPreorder traversal: "); tree.pre_order_traversal(tree.root); System.out.println("\nPost order traversal: "); tree.post_order_traversal(tree.root); } }
输出
Inorder traversal: 44 12 17 27 56 3 Preorder traversal: 27 12 44 17 3 56 Post order traversal: 44 17 12 56 3 27
class Node: def __init__(self, key): self.leftChild = None self.rightChild = None self.data = key # Create a function to perform inorder tree traversal def InorderTraversal(root): if root: InorderTraversal(root.leftChild) print(root.data) InorderTraversal(root.rightChild) # Create a function to perform preorder tree traversal def PostorderTraversal(root): if root: PostorderTraversal(root.leftChild) PostorderTraversal(root.rightChild) print(root.data) # Create a function to perform postorder tree traversal def PreorderTraversal(root): if root: print(root.data) PreorderTraversal(root.leftChild) PreorderTraversal(root.rightChild) # Main class if __name__ == "__main__": root = Node(3) root.leftChild = Node(26) root.rightChild = Node(42) root.leftChild.leftChild = Node(54) root.leftChild.rightChild = Node(65) root.rightChild.leftChild = Node(12) # Function call print("\nInorder traversal of binary tree is") InorderTraversal(root) print("\nPreorder traversal of binary tree is") PreorderTraversal(root) print("\nPostorder traversal of binary tree is") PostorderTraversal(root)
输出
Inorder traversal of binary tree is 54 26 65 3 12 42 Preorder traversal of binary tree is 3 26 54 65 42 12 Postorder traversal of binary tree is 54 65 26 12 42 3
二叉搜索树
二叉搜索树 (BST) 是一棵树,其中所有节点都遵循以下属性:
节点的左子树的键小于或等于其父节点的键。
节点的右子树的键大于或等于其父节点的键。
因此,BST 将所有子树划分为两个部分:左子树和右子树,并且可以定义为:
left_subtree (keys) ≤ node (key) ≤ right_subtree (keys)
表示
BST 是一组以某种方式排列的节点,它们保持 BST 属性。每个节点都有一个键和一个关联的值。在搜索时,将所需的键与 BST 中的键进行比较,如果找到,则检索关联的值。
以下是 BST 的图形表示:
我们观察到根节点键 (27) 在左子树上具有所有较小值的键,在右子树上具有较高值的键。
基本操作
以下是树的基本操作:
搜索 - 在树中搜索元素。
插入 - 在树中插入元素。
前序遍历 - 以前序方式遍历树。
中序遍历 - 以中序方式遍历树。
后序遍历 - 以后序方式遍历树。
定义节点
定义一个节点,它存储一些数据,以及对其左右子节点的引用。
struct node { int data; struct node *leftChild; struct node *rightChild; };
搜索操作
每当要搜索元素时,都从根节点开始搜索。然后,如果数据小于键值,则在左子树中搜索元素。否则,在右子树中搜索元素。对每个节点遵循相同的算法。
算法
1. START 2. Check whether the tree is empty or not 3. If the tree is empty, search is not possible 4. Otherwise, first search the root of the tree. 5. If the key does not match with the value in the root, search its subtrees. 6. If the value of the key is less than the root value, search the left subtree 7. If the value of the key is greater than the root value, search the right subtree. 8. If the key is not found in the tree, return unsuccessful search. 9. END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <stdlib.h> struct node { int data; struct node *leftChild, *rightChild; }; struct node *root = NULL; struct node *newNode(int item){ struct node *temp = (struct node *)malloc(sizeof(struct node)); temp->data = item; temp->leftChild = temp->rightChild = NULL; return temp; } void insert(int data){ struct node *tempNode = (struct node*) malloc(sizeof(struct node)); struct node *current; struct node *parent; tempNode->data = data; tempNode->leftChild = NULL; tempNode->rightChild = NULL; //if tree is empty if(root == NULL) { root = tempNode; } else { current = root; parent = NULL; while(1) { parent = current; //go to left of the tree if(data < parent->data) { current = current->leftChild; //insert to the left if(current == NULL) { parent->leftChild = tempNode; return; } }//go to right of the tree else { current = current->rightChild; //insert to the right if(current == NULL) { parent->rightChild = tempNode; return; } } } } } struct node* search(int data){ struct node *current = root; printf("\nVisiting elements: "); while(current->data != data) { if(current != NULL) { printf("%d ",current->data); //go to left tree if(current->data > data) { current = current->leftChild; }//else go to right tree else { current = current->rightChild; } //not found if(current == NULL) { return NULL; } } } return current; } void printTree(struct node* Node){ if(Node == NULL) return; printTree(Node->leftChild); printf(" --%d", Node->data); printTree(Node->rightChild); } int main(){ insert(55); insert(20); insert(90); insert(50); insert(35); insert(15); insert(65); printf("Insertion done\n"); printTree(root); struct node* k; k = search(35); if(k != NULL) printf("\nElement %d found", k->data); else printf("\nElement not found"); return 0; }
输出
Insertion done --15 --20 --35 --50 --55 --65 --90 Visiting elements: 55 20 50 Element 35 found
#include <stdio.h> #include <stdlib.h> struct node { int data; struct node *leftChild, *rightChild; }; struct node *root = NULL; struct node *newNode(int item){ struct node *temp = (struct node *)malloc(sizeof(struct node)); temp->data = item; temp->leftChild = temp->rightChild = NULL; return temp; } void insert(int data){ struct node *tempNode = (struct node*) malloc(sizeof(struct node)); struct node *current; struct node *parent; tempNode->data = data; tempNode->leftChild = NULL; tempNode->rightChild = NULL; //if tree is empty if(root == NULL) { root = tempNode; } else { current = root; parent = NULL; while(1) { parent = current; //go to left of the tree if(data < parent->data) { current = current->leftChild; //insert to the left if(current == NULL) { parent->leftChild = tempNode; return; } }//go to right of the tree else { current = current->rightChild; //insert to the right if(current == NULL) { parent->rightChild = tempNode; return; } } } } } struct node* search(int data){ struct node *current = root; printf("\nVisiting elements: "); while(current->data != data) { if(current != NULL) { printf("%d ",current->data); //go to left tree if(current->data > data) { current = current->leftChild; }//else go to right tree else { current = current->rightChild; } //not found if(current == NULL) { return NULL; } } } return current; } void printTree(struct node* Node){ if(Node == NULL) return; printTree(Node->leftChild); printf(" --%d", Node->data); printTree(Node->rightChild); } int main(){ insert(55); insert(20); insert(90); insert(50); insert(35); insert(15); insert(65); printf("Insertion done\n"); printTree(root); struct node* k; k = search(35); if(k != NULL) printf("\nElement %d found", k->data); else printf("\nElement not found"); return 0; }
输出
Insertion done --15 --20 --35 --50 --55 --65 --90 Visiting elements: 55 20 50 Element 35 found
import java.util.Scanner; class BSTNode { BSTNode left, right; int data; public BSTNode(int n) { left = null; right = null; data = n; } } public class BST { static BSTNode root; public BST() { root = null; } private BSTNode insert(BSTNode node, int data) { if(node == null) node = new BSTNode(data); else { if(data <= node.data) node.left = insert(node.left, data); else node.right = insert(node.right, data); } return node; } private boolean search(BSTNode r, int val) { boolean found = false; while ((r != null) && !found) { int rval = r.data; if(val < rval) r = r.left; else if (val > rval) r = r.right; else { found = true; break; } found = search(r, val); } return found; } void printTree(BSTNode node, String prefix) { if(node == null) return; printTree(node.left , " " + prefix); System.out.println(prefix + "--" + node.data); printTree(node.right , prefix + " "); } public static void main(String args[]) { Scanner sc = new Scanner(System.in); BST bst = new BST(); root = bst.insert(root, 55); root = bst.insert(root, 20); root = bst.insert(root, 90); root = bst.insert(root, 80); root = bst.insert(root, 50); root = bst.insert(root, 35); root = bst.insert(root, 15); root = bst.insert(root, 65); bst.printTree(root, " "); System.out.println("Element found = " + bst.search(root, 80)); } }
输出
--15 --20--35 --50 --55 --65 --80 --90 Element found = true
class Node: def __init__(self, data): self.left = None self.right = None self.data = data # Insert method to create nodes def insert(self, data): if self.data: if data < self.data: if self.left is None: self.left = Node(data) else: self.left.insert(data) elif data > self.data: if self.right is None: self.right = Node(data) else: self.right.insert(data) else: self.data = data # search method to compare the value with nodes def search(self, key): if key < self.data: if self.left is None: return str(key)+" Not Found" return self.left.search(key) elif key > self.data: if self.right is None: return str(key)+" Not Found" return self.right.search(key) else: print(str(self.data) + ' is found') root = Node(54) root.insert(34) root.insert(46) root.insert(12) root.insert(23) root.insert(5) print(root.search(17)) print(root.search(12))
输出
17 Not Found 12 is found None
插入操作
每当要插入元素时,首先找到其正确的位置。从根节点开始搜索,然后,如果数据小于键值,则在左子树中搜索空位置并插入数据。否则,在右子树中搜索空位置并插入数据。
算法
1 – START 2 – If the tree is empty, insert the first element as the root node of the tree. The following elements are added as the leaf nodes. 3 – If an element is less than the root value, it is added into the left subtree as a leaf node. 4 – If an element is greater than the root value, it is added into the right subtree as a leaf node. 5 – The final leaf nodes of the tree point to NULL values as their child nodes. 6 – END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <stdlib.h> struct node { int data; struct node *leftChild, *rightChild; }; struct node *root = NULL; struct node *newNode(int item){ struct node *temp = (struct node *)malloc(sizeof(struct node)); temp->data = item; temp->leftChild = temp->rightChild = NULL; return temp; } void insert(int data){ struct node *tempNode = (struct node*) malloc(sizeof(struct node)); struct node *current; struct node *parent; tempNode->data = data; tempNode->leftChild = NULL; tempNode->rightChild = NULL; //if tree is empty if(root == NULL) { root = tempNode; } else { current = root; parent = NULL; while(1) { parent = current; //go to left of the tree if(data < parent->data) { current = current->leftChild; //insert to the left if(current == NULL) { parent->leftChild = tempNode; return; } }//go to right of the tree else { current = current->rightChild; //insert to the right if(current == NULL) { parent->rightChild = tempNode; return; } } } } } void printTree(struct node* Node){ if(Node == NULL) return; printTree(Node->leftChild); printf(" --%d", Node->data); printTree(Node->rightChild); } int main(){ insert(55); insert(20); insert(90); insert(50); insert(35); insert(15); insert(65); printf("Insertion done\n"); printTree(root); return 0; }
输出
Insertion done --15 --20 --35 --50 --55 --65 --90
#include <iostream> struct node { int data; struct node *leftChild, *rightChild; }; struct node *root = NULL; struct node *newNode(int item){ struct node *temp = (struct node *)malloc(sizeof(struct node)); temp->data = item; temp->leftChild = temp->rightChild = NULL; return temp; } void insert(int data){ struct node *tempNode = (struct node*) malloc(sizeof(struct node)); struct node *current; struct node *parent; tempNode->data = data; tempNode->leftChild = NULL; tempNode->rightChild = NULL; //if tree is empty if(root == NULL) { root = tempNode; } else { current = root; parent = NULL; while(1) { parent = current; //go to left of the tree if(data < parent->data) { current = current->leftChild; //insert to the left if(current == NULL) { parent->leftChild = tempNode; return; } }//go to right of the tree else { current = current->rightChild; //insert to the right if(current == NULL) { parent->rightChild = tempNode; return; } } } } } void printTree(struct node* Node){ if(Node == NULL) return; printTree(Node->leftChild); printf(" --%d", Node->data); printTree(Node->rightChild); } int main(){ insert(55); insert(20); insert(90); insert(50); insert(35); insert(15); insert(65); printf("Insertion done\n"); printTree(root); return 0; }
输出
Insertion done --15 --20 --35 --50 --55 --65 --90
import java.util.Scanner; class BSTNode { BSTNode left, right; int data; public BSTNode(int n) { left = null; right = null; data = n; } } public class BST { static BSTNode root; public BST() { root = null; } private BSTNode insert(BSTNode node, int data) { if(node == null) node = new BSTNode(data); else { if(data <= node.data) node.left = insert(node.left, data); else node.right = insert(node.right, data); } return node; } void printTree(BSTNode node, String prefix) { if(node == null) return; printTree(node.left , " " + prefix); System.out.println(prefix + "--" + node.data); printTree(node.right , prefix + " "); } public static void main(String args[]) { Scanner sc = new Scanner(System.in); BST bst = new BST(); root = bst.insert(root, 55); root = bst.insert(root, 20); root = bst.insert(root, 90); root = bst.insert(root, 80); root = bst.insert(root, 50); root = bst.insert(root, 35); root = bst.insert(root, 15); root = bst.insert(root, 65); bst.printTree(root, " "); } }
输出
--15 --20 --35 --50 --55 --65 --80 --90
class Node: def __init__(self, data): self.left = None self.right = None self.data = data # Insert method to create nodes def insert(self, data): if self.data: if data < self.data: if self.left is None: self.left = Node(data) else: self.left.insert(data) elif data > self.data: if self.right is None: self.right = Node(data) else: self.right.insert(data) else: self.data = data root = Node(54) root.insert(34) root.insert(46) root.insert(12) root.insert(23) root.insert(5) print("Insertion Done")
输出
Insertion Done
中序遍历
二叉搜索树中的中序遍历操作按以下顺序访问其所有节点:
首先,我们遍历根节点/当前节点的左子节点(如果有)。
接下来,遍历当前节点。
最后,遍历当前节点的右子节点(如果有)。
算法
1. START 2. Traverse the left subtree, recursively 3. Then, traverse the root node 4. Traverse the right subtree, recursively. 5. END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <stdlib.h> struct node { int key; struct node *left, *right; }; struct node *newNode(int item){ struct node *temp = (struct node *)malloc(sizeof(struct node)); temp->key = item; temp->left = temp->right = NULL; return temp; } // Inorder Traversal void inorder(struct node *root){ if (root != NULL) { inorder(root->left); printf("%d -> ", root->key); inorder(root->right); } } // Insertion operation struct node *insert(struct node *node, int key){ if (node == NULL) return newNode(key); if (key < node->key) node->left = insert(node->left, key); else node->right = insert(node->right, key); return node; } int main(){ struct node *root = NULL; root = insert(root, 55); root = insert(root, 20); root = insert(root, 90); root = insert(root, 50); root = insert(root, 35); root = insert(root, 15); root = insert(root, 65); printf("Inorder traversal: "); inorder(root); }
输出
Inorder traversal: 15 -> 20 -> 35 -> 50 -> 55 -> 65 -> 90 ->
#include <iostream> struct node { int key; struct node *left, *right; }; struct node *newNode(int item){ struct node *temp = (struct node *)malloc(sizeof(struct node)); temp->key = item; temp->left = temp->right = NULL; return temp; } // Inorder Traversal void inorder(struct node *root){ if (root != NULL) { inorder(root->left); printf("%d -> ", root->key); inorder(root->right); } } // Insertion operation struct node *insert(struct node *node, int key){ if (node == NULL) return newNode(key); if (key < node->key) node->left = insert(node->left, key); else node->right = insert(node->right, key); return node; } int main(){ struct node *root = NULL; root = insert(root, 55); root = insert(root, 20); root = insert(root, 90); root = insert(root, 50); root = insert(root, 35); root = insert(root, 15); root = insert(root, 65); printf("Inorder traversal: "); inorder(root); }
输出
Inorder traversal: 15 -> 20 -> 35 -> 50 -> 55 -> 65 -> 90 ->
class Node { int data; Node leftChild; Node rightChild; public Node(int key) { data = key; leftChild = rightChild = null; } } public class TreeDataStructure { Node root = null; void inorder_traversal(Node node) { if(node != null) { inorder_traversal(node.leftChild); System.out.print(node.data + " "); inorder_traversal(node.rightChild); } } public static void main(String args[]) { TreeDataStructure tree = new TreeDataStructure(); tree.root = new Node(27); tree.root.leftChild = new Node(12); tree.root.rightChild = new Node(30); tree.root.leftChild.leftChild = new Node(4); tree.root.leftChild.rightChild = new Node(17); tree.root.rightChild.leftChild = new Node(56); System.out.println("\nInorder traversal: "); tree.inorder_traversal(tree.root); } }
输出
Inorder traversal: 4 12 17 27 56 30
class Node: def __init__(self, data): self.left = None self.right = None self.data = data # Insert method to create nodes def insert(self, data): if self.data: if data < self.data: if self.left is None: self.left = Node(data) else: self.left.insert(data) elif data > self.data: if self.right is None: self.right = Node(data) else: self.right.insert(data) else: self.data = data # Print the tree def Inorder(self): if self.left: self.left.Inorder() print(self.data) if self.right: self.right.Inorder() root = Node(54) root.insert(34) root.insert(46) root.insert(12) root.insert(23) root.insert(5) print("Inorder Traversal of Binary Search Tree: ") root.Inorder()
输出
Inorder Traversal of Binary Search Tree: 12 34 54
前序遍历
二叉搜索树中的先序遍历操作会访问其所有节点。但是,它首先打印根节点,然后打印其左子树,最后打印其右子树。
算法
1. START 2. Traverse the root node first. 3. Then traverse the left subtree, recursively 4. Later, traverse the right subtree, recursively. 5. END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <stdlib.h> struct node { int key; struct node *left, *right; }; struct node *newNode(int item){ struct node *temp = (struct node *)malloc(sizeof(struct node)); temp->key = item; temp->left = temp->right = NULL; return temp; } // Preorder Traversal void preorder(struct node *root){ if (root != NULL) { printf("%d -> ", root->key); preorder(root->left); preorder(root->right); } } // Insertion operation struct node *insert(struct node *node, int key){ if (node == NULL) return newNode(key); if (key < node->key) node->left = insert(node->left, key); else node->right = insert(node->right, key); return node; } int main(){ struct node *root = NULL; root = insert(root, 55); root = insert(root, 20); root = insert(root, 90); root = insert(root, 50); root = insert(root, 35); root = insert(root, 15); root = insert(root, 65); printf("Preorder traversal: "); preorder(root); }
输出
Preorder traversal: 55 -> 20 -> 15 -> 50 -> 35 -> 90 -> 65 ->
#include <iostream> struct node { int key; struct node *left, *right; }; struct node *newNode(int item){ struct node *temp = (struct node *)malloc(sizeof(struct node)); temp->key = item; temp->left = temp->right = NULL; return temp; } // Preorder Traversal void preorder(struct node *root){ if (root != NULL) { printf("%d -> ", root->key); preorder(root->left); preorder(root->right); } } // Insertion operation struct node *insert(struct node *node, int key){ if (node == NULL) return newNode(key); if (key < node->key) node->left = insert(node->left, key); else node->right = insert(node->right, key); return node; } int main(){ struct node *root = NULL; root = insert(root, 55); root = insert(root, 20); root = insert(root, 90); root = insert(root, 50); root = insert(root, 35); root = insert(root, 15); root = insert(root, 65); printf("Preorder traversal: "); preorder(root); }
输出
Preorder traversal: 55 -> 20 -> 15 -> 50 -> 35 -> 90 -> 65 ->
class Node { int data; Node leftChild; Node rightChild; public Node(int key) { data = key; leftChild = rightChild = null; } } public class TreeDataStructure { Node root = null; void preorder_traversal(Node node) { if(node != null) { System.out.print(node.data + " "); preorder_traversal(node.leftChild); preorder_traversal(node.rightChild); } } public static void main(String args[]) { TreeDataStructure tree = new TreeDataStructure(); tree.root = new Node(27); tree.root.leftChild = new Node(12); tree.root.rightChild = new Node(30); tree.root.leftChild.leftChild = new Node(4); tree.root.leftChild.rightChild = new Node(17); tree.root.rightChild.leftChild = new Node(56); System.out.println("\nPreorder traversal: "); tree.preorder_traversal(tree.root); } }
输出
Preorder traversal: 27 12 4 17 30 56
class Node: def __init__(self, data): self.left = None self.right = None self.data = data # Insert method to create nodes def insert(self, data): if self.data: if data < self.data: if self.left is None: self.left = Node(data) else: self.left.insert(data) elif data > self.data: if self.right is None: self.right = Node(data) else: self.right.insert(data) else: self.data = data # Print the tree def Preorder(self): print(self.data) if self.left: self.left.Preorder() if self.right: self.right.Preorder() root = Node(54) root.insert(34) root.insert(46) root.insert(12) root.insert(23) root.insert(5) print("Preorder Traversal of Binary Search Tree: ") root.Preorder()
输出
Preorder Traversal of Binary Search Tree: 54 34 12 5 23 46
后序遍历
与其他遍历一样,后序遍历也会访问二叉搜索树中的所有节点并显示它们。但是,它首先打印左子树,然后打印右子树,最后打印根节点。
算法
1. START 2. Traverse the left subtree, recursively 3. Traverse the right subtree, recursively. 4. Then, traverse the root node 5. END
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <stdlib.h> struct node { int key; struct node *left, *right; }; struct node *newNode(int item){ struct node *temp = (struct node *)malloc(sizeof(struct node)); temp->key = item; temp->left = temp->right = NULL; return temp; } // Postorder Traversal void postorder(struct node *root){ if (root != NULL) { printf("%d -> ", root->key); postorder(root->left); postorder(root->right); } } // Insertion operation struct node *insert(struct node *node, int key){ if (node == NULL) return newNode(key); if (key < node->key) node->left = insert(node->left, key); else node->right = insert(node->right, key); return node; } int main(){ struct node *root = NULL; root = insert(root, 55); root = insert(root, 20); root = insert(root, 90); root = insert(root, 50); root = insert(root, 35); root = insert(root, 15); root = insert(root, 65); printf("Postorder traversal: "); postorder(root); }
输出
Postorder traversal: 55 -> 20 -> 15 -> 50 -> 35 -> 90 > 65 ->
#include <iostream> struct node { int key; struct node *left, *right; }; struct node *newNode(int item){ struct node *temp = (struct node *)malloc(sizeof(struct node)); temp->key = item; temp->left = temp->right = NULL; return temp; } // Postorder Traversal void postorder(struct node *root){ if (root != NULL) { printf("%d -> ", root->key); postorder(root->left); postorder(root->right); } } // Insertion operation struct node *insert(struct node *node, int key){ if (node == NULL) return newNode(key); if (key < node->key) node->left = insert(node->left, key); else node->right = insert(node->right, key); return node; } int main(){ struct node *root = NULL; root = insert(root, 55); root = insert(root, 20); root = insert(root, 90); root = insert(root, 50); root = insert(root, 35); root = insert(root, 15); root = insert(root, 65); printf("Postorder traversal: "); postorder(root); }
输出
Postorder traversal: 55 -> 20 -> 15 -> 50 -> 35 -> 90 -> 65 ->
class Node { int data; Node leftChild; Node rightChild; public Node(int key) { data = key; leftChild = rightChild = null; } } public class TreeDataStructure { Node root = null; void postorder_traversal(Node node) { if(node != null) { postorder_traversal(node.leftChild); postorder_traversal(node.rightChild); System.out.print(node.data + " "); } } public static void main(String args[]) { TreeDataStructure tree = new TreeDataStructure(); tree.root = new Node(27); tree.root.leftChild = new Node(12); tree.root.rightChild = new Node(30); tree.root.leftChild.leftChild = new Node(4); tree.root.leftChild.rightChild = new Node(17); tree.root.rightChild.leftChild = new Node(56); System.out.println("\nPostorder traversal: "); tree.postorder_traversal(tree.root); } }
输出
Postorder traversal: 4 17 12 56 30 27
class Node: def __init__(self, data): self.left = None self.right = None self.data = data # Insert method to create nodes def insert(self, data): if self.data: if data < self.data: if self.left is None: self.left = Node(data) else: self.left.insert(data) elif data > self.data: if self.right is None: self.right = Node(data) else: self.right.insert(data) else: self.data = data # Print the tree def Postorder(self): if self.left: self.left.Postorder() if self.right: self.right.Postorder() print(self.data) root = Node(54) root.insert(34) root.insert(46) root.insert(12) root.insert(23) root.insert(5) print("Postorder Traversal of Binary Search Tree: ") root.Postorder()
输出
Postorder Traversal of Binary Search Tree: 5 23 12 46 34 54
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <stdlib.h> struct node { int data; struct node *leftChild, *rightChild; }; struct node *root = NULL; struct node *newNode(int item){ struct node *temp = (struct node *)malloc(sizeof(struct node)); temp->data = item; temp->leftChild = temp->rightChild = NULL; return temp; } void insert(int data){ struct node *tempNode = (struct node*) malloc(sizeof(struct node)); struct node *current; struct node *parent; tempNode->data = data; tempNode->leftChild = NULL; tempNode->rightChild = NULL; //if tree is empty if(root == NULL) { root = tempNode; } else { current = root; parent = NULL; while(1) { parent = current; //go to left of the tree if(data < parent->data) { current = current->leftChild; //insert to the left if(current == NULL) { parent->leftChild = tempNode; return; } }//go to right of the tree else { current = current->rightChild; //insert to the right if(current == NULL) { parent->rightChild = tempNode; return; } } } } } struct node* search(int data){ struct node *current = root; printf("\n\nVisiting elements: "); while(current->data != data) { if(current != NULL) { printf("%d ",current->data); //go to left tree if(current->data > data) { current = current->leftChild; }//else go to right tree else { current = current->rightChild; } //not found if(current == NULL) { return NULL; } } } return current; } // Inorder Traversal void inorder(struct node *root){ if (root != NULL) { inorder(root->leftChild); printf("%d -> ", root->data); inorder(root->rightChild); } } // Preorder Traversal void preorder(struct node *root){ if (root != NULL) { printf("%d -> ", root->data); preorder(root->leftChild); preorder(root->rightChild); } } // Postorder Traversal void postorder(struct node *root){ if (root != NULL) { printf("%d -> ", root->data); postorder(root->leftChild); postorder(root->rightChild); } } int main(){ insert(55); insert(20); insert(90); insert(50); insert(35); insert(15); insert(65); printf("Insertion done\n"); printf("\nPreorder Traversal: "); preorder(root); printf("\nInorder Traversal: "); inorder(root); printf("\nPostorder Traversal: "); postorder(root); struct node* k; k = search(35); if(k != NULL) printf("\nElement %d found", k->data); else printf("\nElement not found"); return 0; }
输出
Insertion done Preorder Traversal: 55 -> 20 -> 15 -> 50 -> 35 -> 90 -> 65 -> Inorder Traversal: 15 -> 20 -> 35 -> 50 -> 55 -> 65 -> 90 -> Postorder Traversal: 55 -> 20 -> 15 -> 50 -> 35 -> 90 -> 65 -> Visiting elements: 55 20 50 Element 35 found
#include <iostream> struct node { int data; struct node *leftChild, *rightChild; }; struct node *root = NULL; struct node *newNode(int item){ struct node *temp = (struct node *)malloc(sizeof(struct node)); temp->data = item; temp->leftChild = temp->rightChild = NULL; return temp; } void insert(int data){ struct node *tempNode = (struct node*) malloc(sizeof(struct node)); struct node *current; struct node *parent; tempNode->data = data; tempNode->leftChild = NULL; tempNode->rightChild = NULL; //if tree is empty if(root == NULL) { root = tempNode; } else { current = root; parent = NULL; while(1) { parent = current; //go to left of the tree if(data < parent->data) { current = current->leftChild; //insert to the left if(current == NULL) { parent->leftChild = tempNode; return; } }//go to right of the tree else { current = current->rightChild; //insert to the right if(current == NULL) { parent->rightChild = tempNode; return; } } } } } struct node* search(int data){ struct node *current = root; printf("\n\nVisiting elements: "); while(current->data != data) { if(current != NULL) { printf("%d ",current->data); //go to left tree if(current->data > data) { current = current->leftChild; }//else go to right tree else { current = current->rightChild; } //not found if(current == NULL) { return NULL; } } } return current; } // Inorder Traversal void inorder(struct node *root){ if (root != NULL) { inorder(root->leftChild); printf("%d -> ", root->data); inorder(root->rightChild); } } // Preorder Traversal void preorder(struct node *root){ if (root != NULL) { printf("%d -> ", root->data); preorder(root->leftChild); preorder(root->rightChild); } } // Postorder Traversal void postorder(struct node *root){ if (root != NULL) { printf("%d -> ", root->data); postorder(root->leftChild); postorder(root->rightChild); } } int main(){ insert(55); insert(20); insert(90); insert(50); insert(35); insert(15); insert(65); printf("Insertion done\n"); printf("\nPreorder Traversal: "); preorder(root); printf("\nInorder Traversal: "); inorder(root); printf("\nPostorder Traversal: "); postorder(root); struct node* k; k = search(35); if(k != NULL) printf("\nElement %d found", k->data); else printf("\nElement not found"); return 0; }
输出
Insertion done Preorder Traversal: 55 -> 20 -> 15 -> 50 -> 35 -> 90 -> 65 -> Inorder Traversal: 15 -> 20 -> 35 -> 50 -> 55 -> 65 -> 90 -> Postorder Traversal: 55 -> 20 -> 15 -> 50 -> 35 -> 90 -> 65 -> Visiting elements: 55 20 50 Element 35 found
import java.util.Scanner; class BSTNode { BSTNode left, right; int data; public BSTNode(int n) { left = null; right = null; data = n; } } public class BST { static BSTNode root; public BST() { root = null; } public boolean isEmpty() { return root == null; } private BSTNode insert(BSTNode node, int data) { if(node == null) node = new BSTNode(data); else { if(data <= node.data) node.left = insert(node.left, data); else node.right = insert(node.right, data); } return node; } public void delete(int k) { if(isEmpty ()) System.out.println("TREE EMPTY"); else if(search (k) == false) System.out.println("SORRY " + k + " IS NOT PRESENT"); else { root=delete(root,k); System.out.println(k + " DELETED FROM THE TREE"); } } public BSTNode delete(BSTNode root, int k) { BSTNode p, p2, n; if(root.data == k) { BSTNode lt, rt; lt = root.left; rt = root.right; if(lt == null && rt == null) { return null; } else if(lt == null) { p = rt; return p; } else if(rt == null) { p = lt; return p; } else { p2 = rt; p = rt; while(p.left != null) p = p.left; p.left = lt; return p2; } } if (k < root.data) { n = delete(root.left, k); root.left = n; } else { n = delete(root.right, k); root.right = n; } return root; } public boolean search(int val) { return search(root, val); } private boolean search(BSTNode r, int val) { boolean found = false; while ((r != null) && !found) { int rval = r.data; if(val < rval) r = r.left; else if (val > rval) r = r.right; else { found = true; break; } found = search(r, val); } return found; } void printTree(BSTNode node, String prefix) { if(node == null) return; printTree(node.left , " " + prefix); System.out.println(prefix + "--" + node.data); printTree(node.right , prefix + " "); } public static void main(String args[]) { Scanner sc = new Scanner(System.in); BST bst = new BST(); root = bst.insert(root, 55); root = bst.insert(root, 20); root = bst.insert(root, 90); root = bst.insert(root, 80); root = bst.insert(root, 50); root = bst.insert(root, 35); root = bst.insert(root, 15); root = bst.insert(root, 65); bst.printTree(root, " "); bst.delete(55); System.out.println("Element found = " + bst.search(80)); System.out.println("Is Tree Empty? " + bst.isEmpty()); } }
输出
--15 --20--35 --50 --55 --65 --80 --90 55 DELETED FROM THE TREE Element found = true Is Tree Empty? false
class Node: def __init__(self, data): self.left = None self.right = None self.data = data # Insert method to create nodes def insert(self, data): if self.data: if data < self.data: if self.left is None: self.left = Node(data) else: self.left.insert(data) elif data > self.data: if self.right is None: self.right = Node(data) else: self.right.insert(data) else: self.data = data # search method to compare the value with nodes def search(self, key): if key < self.data: if self.left is None: return str(key)+" Not Found" return self.left.search(key) elif key > self.data: if self.right is None: return str(key)+" Not Found" return self.right.search(key) else: print(str(self.data) + ' is found') # Print the tree def Inorder(self): if self.left: self.left.Inorder() print(self.data) if self.right: self.right.Inorder() # Print the tree def Preorder(self): print(self.data) if self.left: self.left.Preorder() if self.right: self.right.Preorder() # Print the tree def Postorder(self): if self.left: self.left.Postorder() if self.right: self.right.Postorder() print(self.data) root = Node(54) root.insert(34) root.insert(46) root.insert(12) root.insert(23) root.insert(5) print("Preorder Traversal of Binary Search Tree: ") root.Preorder() print("Inorder Traversal of Binary Search Tree: ") root.Inorder() print("Postorder Traversal of Binary Search Tree: ") root.Postorder() print(root.search(17)) print(root.search(12))
输出
Preorder Traversal of Binary Search Tree: 54 34 12 5 23 46 Inorder Traversal of Binary Search Tree: 5 12 23 34 46 54 Postorder Traversal of Binary Search Tree: 5 23 12 46 34 54 17 Not Found 12 is found None
AVL 树
第一个被发明的自平衡二叉搜索树是 AVL 树。AVL 树的名字来源于其发明者的名字——Adelson-Velsky 和 Landis。
在 AVL 树中,左子树和右子树的高度差(称为**平衡因子**)必须最多为 1。一旦差异超过 1,树就会自动执行平衡算法,直到差异再次变为 1。
BALANCE FACTOR = HEIGHT(LEFT SUBTREE) – HEIGHT(RIGHT SUBTREE)
AVL 树的平衡算法中通常有四种旋转情况:LL、RR、LR、RL。
LL 旋转
当节点插入到右子树导致树不平衡时,执行 LL 旋转。这是一种单一的左旋转,用于使树再次平衡:
图:LL 旋转
发生不平衡的节点成为左子节点,新添加的节点成为右子节点,中间节点作为父节点。
RR 旋转
当节点插入到左子树导致树不平衡时,执行 RR 旋转。这是一种单一的右旋转,用于使树再次平衡:
图:RR 旋转
发生不平衡的节点成为右子节点,新添加的节点成为左子节点,中间节点作为父节点。
LR 旋转
LR 旋转是前面单旋转的扩展版本,也称为双旋转。当节点插入到左子树的右子树时执行。LR 旋转是左旋转后跟右旋转的组合。执行此操作需要遵循多个步骤。
考虑一个示例,其中“A”作为根节点,“B”作为“A”的左子节点,“C”作为“B”的右子节点。
由于不平衡发生在 A 处,因此对 A 的子节点(即 B 和 C)应用左旋转。
旋转后,C 节点成为 A 的左子节点,B 成为 C 的左子节点。
不平衡仍然存在,因此在根节点 A 和左子节点 C 处应用右旋转。
最终右旋转后,C 成为根节点,A 成为右子节点,B 成为左子节点。
图:LR 旋转
RL 旋转
RL 旋转也是前面单旋转的扩展版本,因此称为双旋转,如果节点插入到右子树的左子树中,则执行。RL 旋转是右旋转后跟左旋转的组合。执行此操作需要遵循多个步骤。
考虑一个示例,其中“A”作为根节点,“B”作为“A”的右子节点,“C”作为“B”的左子节点。
由于不平衡发生在 A 处,因此对 A 的子节点(即 B 和 C)应用右旋转。
旋转后,C 节点成为 A 的右子节点,B 成为 C 的右子节点。
不平衡仍然存在,因此在根节点 A 和右子节点 C 处应用左旋转。
最终左旋转后,C 成为根节点,A 成为左子节点,B 成为右子节点。
图:RL 旋转
AVL 树的基本操作
在 AVL 树结构上执行的基本操作包括在二叉搜索树上执行的所有操作,因为 AVL 树在其核心实际上只是一个保持其所有属性的二叉搜索树。因此,在 AVL 树上执行的基本操作是——**插入**和**删除**。
插入
通过遵循二叉搜索树的插入属性将数据插入 AVL 树,即左子树必须包含小于根值的元素,右子树必须包含所有大于的元素。但是,在 AVL 树中,在插入每个元素后,会检查树的平衡因子;如果它不超过 1,则树保持不变。但如果平衡因子超过 1,则会应用平衡算法重新调整树,使平衡因子再次小于或等于 1。
算法
执行 AVL 树的插入操作涉及以下步骤:
**步骤 1**——创建节点
**步骤 2**——检查树是否为空
**步骤 3**——如果树为空,则创建的新节点将成为 AVL 树的根节点。
**步骤 4**——如果树不为空,我们执行二叉搜索树插入操作并检查树中节点的平衡因子。
**步骤 5**——假设平衡因子超过 ±1,我们对该节点应用合适的旋转并从步骤 4 恢复插入。
START if node == null then: return new node if key < node.key then: node.left = insert (node.left, key) else if (key > node.key) then: node.right = insert (node.right, key) else return node node.height = 1 + max (height (node.left), height (node.right)) balance = getBalance (node) if balance > 1 and key < node.left.key then: rightRotate if balance < -1 and key > node.right.key then: leftRotate if balance > 1 and key > node.left.key then: node.left = leftRotate (node.left) rightRotate if balance < -1 and key < node.right.key then: node.right = rightRotate (node.right) leftRotate (node) return node END
插入示例
让我们通过构建一个包含 1 到 7 个整数的 AVL 树示例来了解插入操作。
从第一个元素 1 开始,我们创建一个节点并测量平衡,即 0。
由于二叉搜索属性和平衡因子都满足,因此我们将另一个元素插入到树中。
计算两个节点的平衡因子,发现为 -1(左子树的高度为 0,右子树的高度为 1)。由于它不超过 1,因此我们将另一个元素添加到树中。
现在,添加第三个元素后,平衡因子超过 1 并变为 2。因此,应用旋转。在这种情况下,应用 RR 旋转,因为不平衡发生在两个右节点上。
树重新排列为:
类似地,使用这些旋转插入和重新排列后续元素。重新排列后,我们得到如下树:
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <stdlib.h> struct Node { int data; struct Node *leftChild; struct Node *rightChild; int height; }; int max(int a, int b); int height(struct Node *N){ if (N == NULL) return 0; return N->height; } int max(int a, int b){ return (a > b) ? a : b; } struct Node *newNode(int data){ struct Node *node = (struct Node *) malloc(sizeof(struct Node)); node->data = data; node->leftChild = NULL; node->rightChild = NULL; node->height = 1; return (node); } struct Node *rightRotate(struct Node *y){ struct Node *x = y->leftChild; struct Node *T2 = x->rightChild; x->rightChild = y; y->leftChild = T2; y->height = max(height(y->leftChild), height(y->rightChild)) + 1; x->height = max(height(x->leftChild), height(x->rightChild)) + 1; return x; } struct Node *leftRotate(struct Node *x){ struct Node *y = x->rightChild; struct Node *T2 = y->leftChild; y->leftChild = x; x->rightChild = T2; x->height = max(height(x->leftChild), height(x->rightChild)) + 1; y->height = max(height(y->leftChild), height(y->rightChild)) + 1; return y; } int getBalance(struct Node *N){ if (N == NULL) return 0; return height(N->leftChild) - height(N->rightChild); } struct Node *insertNode(struct Node *node, int data){ if (node == NULL) return (newNode(data)); if (data < node->data) node->leftChild = insertNode(node->leftChild, data); else if (data > node->data) node->rightChild = insertNode(node->rightChild, data); else return node; node->height = 1 + max(height(node->leftChild), height(node->rightChild)); int balance = getBalance(node); if (balance > 1 && data < node->leftChild->data) return rightRotate(node); if (balance < -1 && data > node->rightChild->data) return leftRotate(node); if (balance > 1 && data > node->leftChild->data) { node->leftChild = leftRotate(node->leftChild); return rightRotate(node); } if (balance < -1 && data < node->rightChild->data) { node->rightChild = rightRotate(node->rightChild); return leftRotate(node); } return node; } struct Node *minValueNode(struct Node *node){ struct Node *current = node; while (current->leftChild != NULL) current = current->leftChild; return current; } void printTree(struct Node *root){ if (root == NULL) return; if (root != NULL) { printTree(root->leftChild); printf("%d ", root->data); printTree(root->rightChild); } } int main(){ struct Node *root = NULL; root = insertNode(root, 22); root = insertNode(root, 14); root = insertNode(root, 72); root = insertNode(root, 44); root = insertNode(root, 25); root = insertNode(root, 63); root = insertNode(root, 98); printf("AVL Tree: "); printTree(root); return 0; }
输出
AVL Tree: 14 22 25 44 63 72 98
#include <iostream> struct Node { int data; struct Node *leftChild; struct Node *rightChild; int height; }; int max(int a, int b); int height(struct Node *N){ if (N == NULL) return 0; return N->height; } int max(int a, int b){ return (a > b) ? a : b; } struct Node *newNode(int data){ struct Node *node = (struct Node *) malloc(sizeof(struct Node)); node->data = data; node->leftChild = NULL; node->rightChild = NULL; node->height = 1; return (node); } struct Node *rightRotate(struct Node *y){ struct Node *x = y->leftChild; struct Node *T2 = x->rightChild; x->rightChild = y; y->leftChild = T2; y->height = max(height(y->leftChild), height(y->rightChild)) + 1; x->height = max(height(x->leftChild), height(x->rightChild)) + 1; return x; } struct Node *leftRotate(struct Node *x){ struct Node *y = x->rightChild; struct Node *T2 = y->leftChild; y->leftChild = x; x->rightChild = T2; x->height = max(height(x->leftChild), height(x->rightChild)) + 1; y->height = max(height(y->leftChild), height(y->rightChild)) + 1; return y; } int getBalance(struct Node *N){ if (N == NULL) return 0; return height(N->leftChild) - height(N->rightChild); } struct Node *insertNode(struct Node *node, int data){ if (node == NULL) return (newNode(data)); if (data < node->data) node->leftChild = insertNode(node->leftChild, data); else if (data > node->data) node->rightChild = insertNode(node->rightChild, data); else return node; node->height = 1 + max(height(node->leftChild), height(node->rightChild)); int balance = getBalance(node); if (balance > 1 && data < node->leftChild->data) return rightRotate(node); if (balance < -1 && data > node->rightChild->data) return leftRotate(node); if (balance > 1 && data > node->leftChild->data) { node->leftChild = leftRotate(node->leftChild); return rightRotate(node); } if (balance < -1 && data < node->rightChild->data) { node->rightChild = rightRotate(node->rightChild); return leftRotate(node); } return node; } struct Node *minValueNode(struct Node *node){ struct Node *current = node; while (current->leftChild != NULL) current = current->leftChild; return current; } void printTree(struct Node *root){ if (root == NULL) return; if (root != NULL) { printTree(root->leftChild); printf("%d ", root->data); printTree(root->leftChild); } } int main(){ struct Node *root = NULL; root = insertNode(root, 22); root = insertNode(root, 14); root = insertNode(root, 72); root = insertNode(root, 44); root = insertNode(root, 25); root = insertNode(root, 63); root = insertNode(root, 98); printf("AVL Tree: "); printTree(root); return 0; }
输出
AVL Tree: 14 22 14 44 14 22 14
import java.util.*; import java.io.*; class Node { int key, height; Node left, right; Node (int d) { key = d; height = 1; } } public class AVLTree { Node root; int height (Node N) { if (N == null) return 0; return N.height; } int max (int a, int b) { return (a > b) ? a : b; } Node rightRotate (Node y) { Node x = y.left; Node T2 = x.right; x.right = y; y.left = T2; y.height = max (height (y.left), height (y.right)) + 1; x.height = max (height (x.left), height (x.right)) + 1; return x; } Node leftRotate (Node x) { Node y = x.right; Node T2 = y.left; y.left = x; x.right = T2; x.height = max (height (x.left), height (x.right)) + 1; y.height = max (height (y.left), height (y.right)) + 1; return y; } int getBalance (Node N) { if (N == null) return 0; return height (N.left) - height (N.right); } Node insert (Node node, int key) { if (node == null) return (new Node (key)); if (key < node.key) node.left = insert (node.left, key); else if (key > node.key) node.right = insert (node.right, key); else return node; node.height = 1 + max (height (node.left), height (node.right)); int balance = getBalance (node); if (balance > 1 && key < node.left.key) return rightRotate (node); if (balance < -1 && key > node.right.key) return leftRotate (node); if (balance > 1 && key > node.left.key) { node.left = leftRotate (node.left); return rightRotate (node); } if (balance < -1 && key < node.right.key) { node.right = rightRotate (node.right); return leftRotate (node); } return node; } void printTree(Node root){ if (root == null) return; if (root != null) { printTree(root.left); System.out.print(root.key + " "); printTree(root.left); } } public static void main(String args[]) { AVLTree tree = new AVLTree(); tree.root = tree.insert(tree.root, 10); tree.root = tree.insert(tree.root, 11); tree.root = tree.insert(tree.root, 12); tree.root = tree.insert(tree.root, 13); tree.root = tree.insert(tree.root, 14); tree.root = tree.insert(tree.root, 15); System.out.println("AVL Tree: "); tree.printTree(tree.root); } }
输出
AVL Tree: 10 11 10 13 10 11 10
class Node(object): def __init__(self, data): self.data = data self.left = None self.right = None self.height = 1 class AVLTree(object): def insert(self, root, key): if not root: return Node(key) elif key < root.data: root.left = self.insert(root.left, key) else: root.right = self.insert(root.right, key) root.h = 1 + max(self.getHeight(root.left), self.getHeight(root.right)) b = self.getBalance(root) if b > 1 and key < root.left.data: return self.rightRotate(root) if b < -1 and key > root.right.data: return self.leftRotate(root) if b > 1 and key > root.left.data: root.left = self.lefttRotate(root.left) return self.rightRotate(root) if b < -1 and key < root.right.data: root.right = self.rightRotate(root.right) return self.leftRotate(root) return root def leftRotate(self, z): y = z.right T2 = y.left y.left = z z.right = T2 z.height = 1 + max(self.getHeight(z.left), self.getHeight(z.right)) y.height = 1 + max(self.getHeight(y.left), self.getHeight(y.right)) return y def rightRotate(self, z): y = z.left T3 = y.right y.right = z z.left = T3 z.height = 1 + max(self.getHeight(z.left), self.getHeight(z.right)) y.height = 1 + max(self.getHeight(y.left), self.getHeight(y.right)) return y def getHeight(self, root): if not root: return 0 return root.height def getBalance(self, root): if not root: return 0 return self.getHeight(root.left) - self.getHeight(root.right) def Inorder(self, root): if root.left: self.Inorder(root.left) print(root.data) if root.right: self.Inorder(root.right) Tree = AVLTree() root = None root = Tree.insert(root, 10) root = Tree.insert(root, 13) root = Tree.insert(root, 11) root = Tree.insert(root, 14) root = Tree.insert(root, 12) root = Tree.insert(root, 15) # Inorder Traversal print("Inorder traversal of the AVL tree is") Tree.Inorder(root)
输出
Inorder traversal of the AVL tree is 10 11 12 13 14 15
删除
AVL 树中的删除发生在三种不同的场景中:
**场景 1(删除叶子节点)**——如果要删除的节点是叶子节点,则无需替换即可删除它,因为它不会干扰二叉搜索树属性。但是,平衡因子可能会受到干扰,因此会应用旋转以恢复它。
**场景 2(删除只有一个子节点的节点)**——如果要删除的节点只有一个子节点,则用其子节点中的值替换该节点中的值。然后删除子节点。如果平衡因子受到干扰,则应用旋转。
**场景 3(删除有两个子节点的节点)**——如果要删除的节点有两个子节点,则找到该节点的中序后继并将其值替换为中序后继值。然后尝试删除中序后继节点。如果删除后平衡因子超过 1,则应用平衡算法。
START if root == null: return root if key < root.key: root.left = delete Node else if key > root.key: root.right = delete Node else: if root.left == null or root.right == null then: Node temp = null if (temp == root.left) temp = root.right else temp = root.left if temp == null then: temp = root root = null else root = temp else: temp = minimum valued node root.key = temp.key root.right = delete Node if (root == null) then: return root root.height = max (height (root.left), height (root.right)) + 1 balance = getBalance if balance > 1 and getBalance (root.left) >= 0: rightRotate if balance > 1 and getBalance (root.left) < 0: root.left = leftRotate (root.left); rightRotate if balance < -1 and getBalance (root.right) <= 0: leftRotate if balance < -1 and getBalance (root.right) > 0: root.right = rightRotate (root.right); leftRotate return root END
删除示例
使用上面给出的相同树,让我们在三种场景中执行删除:
从上面的树中删除元素 7:
由于元素 7 是叶子节点,因此我们通常删除该元素而不会干扰树中的任何其他节点
从获得的输出树中删除元素 6:
但是,元素 6 不是叶子节点,并且有一个子节点附加到它。在这种情况下,我们将节点 6 替换为其子节点:节点 5。
树的平衡变为 1,并且由于它不超过 1,因此树保持不变。如果我们进一步删除元素 5,则需要应用左旋转;要么 LL 要么 LR,因为不平衡发生在 1-2-4 和 3-2-4 处。
删除元素 5 后,平衡因子受到干扰,因此我们应用 LL 旋转(我们也可以在此处应用 LR 旋转)。
在 1-2-4 路径上应用 LL 旋转后,节点 3 保持原样,因为它应该成为节点 2 的右子节点(现在由节点 4 占据)。因此,将节点添加到节点 2 的右子树中,并作为节点 4 的左子节点。
从剩余的树中删除元素 2:
如场景 3 中所述,此节点有两个子节点。因此,我们找到它的中序后继(例如,3)并将其值替换为中序后继。
树的平衡仍然保持 1,因此我们保持树不变,不执行任何旋转。
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <stdlib.h> struct Node { int data; struct Node *leftChild; struct Node *rightChild; int height; }; int max(int a, int b); int height(struct Node *N){ if (N == NULL) return 0; return N->height; } int max(int a, int b){ return (a > b) ? a : b; } struct Node *newNode(int data){ struct Node *node = (struct Node *) malloc(sizeof(struct Node)); node->data = data; node->leftChild = NULL; node->rightChild = NULL; node->height = 1; return (node); } struct Node *rightRotate(struct Node *y){ struct Node *x = y->leftChild; struct Node *T2 = x->rightChild; x->rightChild = y; y->leftChild = T2; y->height = max(height(y->leftChild), height(y->rightChild)) + 1; x->height = max(height(x->leftChild), height(x->rightChild)) + 1; return x; } struct Node *leftRotate(struct Node *x){ struct Node *y = x->rightChild; struct Node *T2 = y->leftChild; y->leftChild = x; x->rightChild = T2; x->height = max(height(x->leftChild), height(x->rightChild)) + 1; y->height = max(height(y->leftChild), height(y->rightChild)) + 1; return y; } int getBalance(struct Node *N){ if (N == NULL) return 0; return height(N->leftChild) - height(N->rightChild); } struct Node *insertNode(struct Node *node, int data){ if (node == NULL) return (newNode(data)); if (data < node->data) node->leftChild = insertNode(node->leftChild, data); else if (data > node->data) node->rightChild = insertNode(node->rightChild, data); else return node; node->height = 1 + max(height(node->leftChild), height(node->rightChild)); int balance = getBalance(node); if (balance > 1 && data < node->leftChild->data) return rightRotate(node); if (balance < -1 && data > node->rightChild->data) return leftRotate(node); if (balance > 1 && data > node->leftChild->data) { node->leftChild = leftRotate(node->leftChild); return rightRotate(node); } if (balance < -1 && data < node->rightChild->data) { node->rightChild = rightRotate(node->rightChild); return leftRotate(node); } return node; } struct Node *minValueNode(struct Node *node){ struct Node *current = node; while (current->leftChild != NULL) current = current->leftChild; return current; } struct Node *deleteNode(struct Node *root, int data){ if (root == NULL) return root; if (data < root->data) root->leftChild = deleteNode(root->leftChild, data); else if (data > root->data) root->rightChild = deleteNode(root->rightChild, data); else { if ((root->leftChild == NULL) || (root->rightChild == NULL)) { struct Node *temp = root->leftChild ? root->leftChild : root->rightChild; if (temp == NULL) { temp = root; root = NULL; } else *root = *temp; free(temp); } else { struct Node *temp = minValueNode(root->rightChild); root->data = temp->data; root->rightChild = deleteNode(root->rightChild, temp->data); } } if (root == NULL) return root; root->height = 1 + max(height(root->leftChild), height(root->rightChild)); int balance = getBalance(root); if (balance > 1 && getBalance(root->leftChild) >= 0) return rightRotate(root); if (balance > 1 && getBalance(root->leftChild) < 0) { root->leftChild = leftRotate(root->leftChild); return rightRotate(root); } if (balance < -1 && getBalance(root->rightChild) <= 0) return leftRotate(root); if (balance < -1 && getBalance(root->rightChild) > 0) { root->rightChild = rightRotate(root->rightChild); return leftRotate(root); } return root; } // Print the tree void printTree(struct Node *root){ if (root != NULL) { printTree(root->leftChild); printf("%d ", root->data); printTree(root->rightChild); } } int main(){ struct Node *root = NULL; root = insertNode(root, 22); root = insertNode(root, 14); root = insertNode(root, 72); root = insertNode(root, 44); root = insertNode(root, 25); root = insertNode(root, 63); root = insertNode(root, 98); printf("AVL Tree: "); printTree(root); root = deleteNode(root, 25); printf("\nAfter deletion: "); printTree(root); return 0; }
输出
AVL Tree: 14 22 25 44 63 72 98 After deletion: 14 22 44 63 72 98
#include <iostream> struct Node { int data; struct Node *leftChild; struct Node *rightChild; int height; }; int max(int a, int b); int height(struct Node *N){ if (N == NULL) return 0; return N->height; } int max(int a, int b){ return (a > b) ? a : b; } struct Node *newNode(int data){ struct Node *node = (struct Node *) malloc(sizeof(struct Node)); node->data = data; node->leftChild = NULL; node->rightChild = NULL; node->height = 1; return (node); } struct Node *rightRotate(struct Node *y){ struct Node *x = y->leftChild; struct Node *T2 = x->rightChild; x->rightChild = y; y->leftChild = T2; y->height = max(height(y->leftChild), height(y->rightChild)) + 1; x->height = max(height(x->leftChild), height(x->rightChild)) + 1; return x; } struct Node *leftRotate(struct Node *x){ struct Node *y = x->rightChild; struct Node *T2 = y->leftChild; y->leftChild = x; x->rightChild = T2; x->height = max(height(x->leftChild), height(x->rightChild)) + 1; y->height = max(height(y->leftChild), height(y->rightChild)) + 1; return y; } int getBalance(struct Node *N){ if (N == NULL) return 0; return height(N->leftChild) - height(N->rightChild); } struct Node *insertNode(struct Node *node, int data){ if (node == NULL) return (newNode(data)); if (data < node->data) node->leftChild = insertNode(node->leftChild, data); else if (data > node->data) node->rightChild = insertNode(node->rightChild, data); else return node; node->height = 1 + max(height(node->leftChild), height(node->rightChild)); int balance = getBalance(node); if (balance > 1 && data < node->leftChild->data) return rightRotate(node); if (balance < -1 && data > node->rightChild->data) return leftRotate(node); if (balance > 1 && data > node->leftChild->data) { node->leftChild = leftRotate(node->leftChild); return rightRotate(node); } if (balance < -1 && data < node->rightChild->data) { node->rightChild = rightRotate(node->rightChild); return leftRotate(node); } return node; } struct Node *minValueNode(struct Node *node){ struct Node *current = node; while (current->leftChild != NULL) current = current->leftChild; return current; } struct Node *deleteNode(struct Node *root, int data){ if (root == NULL) return root; if (data < root->data) root->leftChild = deleteNode(root->leftChild, data); else if (data > root->data) root->rightChild = deleteNode(root->rightChild, data); else { if ((root->leftChild == NULL) || (root->rightChild == NULL)) { struct Node *temp = root->leftChild ? root->leftChild : root->rightChild; if (temp == NULL) { temp = root; root = NULL; } else *root = *temp; free(temp); } else { struct Node *temp = minValueNode(root->rightChild); root->data = temp->data; root->rightChild = deleteNode(root->rightChild, temp->data); } } if (root == NULL) return root; root->height = 1 + max(height(root->leftChild), height(root->rightChild)); int balance = getBalance(root); if (balance > 1 && getBalance(root->leftChild) >= 0) return rightRotate(root); if (balance > 1 && getBalance(root->leftChild) < 0) { root->leftChild = leftRotate(root->leftChild); return rightRotate(root); } if (balance < -1 && getBalance(root->rightChild) <= 0) return leftRotate(root); if (balance < -1 && getBalance(root->rightChild) > 0) { root->rightChild = rightRotate(root->rightChild); return leftRotate(root); } return root; } // Print the tree void printTree(struct Node *root){ if (root != NULL) { printTree(root->leftChild); printf("%d ", root->data); printTree(root->rightChild); } } int main(){ struct Node *root = NULL; root = insertNode(root, 22); root = insertNode(root, 14); root = insertNode(root, 72); root = insertNode(root, 44); root = insertNode(root, 25); root = insertNode(root, 63); root = insertNode(root, 98); printf("AVL Tree: "); printTree(root); root = deleteNode(root, 25); printf("\nAfter deletion: "); printTree(root); return 0; }
输出
AVL Tree: 14 22 25 44 63 72 98 After deletion: 14 22 44 63 72 98
import java.util.*; import java.io.*; class Node { int key, height; Node left, right; Node (int d) { key = d; height = 1; } } public class AVLTree { Node root; int height (Node N) { if (N == null) return 0; return N.height; } int max (int a, int b) { return (a > b) ? a : b; } Node rightRotate (Node y) { Node x = y.left; Node T2 = x.right; x.right = y; y.left = T2; y.height = max (height (y.left), height (y.right)) + 1; x.height = max (height (x.left), height (x.right)) + 1; return x; } Node leftRotate (Node x) { Node y = x.right; Node T2 = y.left; y.left = x; x.right = T2; x.height = max (height (x.left), height (x.right)) + 1; y.height = max (height (y.left), height (y.right)) + 1; return y; } int getBalance (Node N) { if (N == null) return 0; return height (N.left) - height (N.right); } Node minValueNode (Node node) { Node current = node; while (current.left != null) current = current.left; return current; } Node deleteNode (Node root, int key) { if (root == null) return root; if (key < root.key) root.left = deleteNode (root.left, key); else if (key > root.key) root.right = deleteNode (root.right, key); else { if ((root.left == null) || (root.right == null)) { Node temp = null; if (temp == root.left) temp = root.right; else temp = root.left; if (temp == null) { temp = root; root = null; } else root = temp; } else { Node temp = minValueNode (root.right); root.key = temp.key; root.right = deleteNode (root.right, temp.key); } } if (root == null) return root; root.height = max (height (root.left), height (root.right)) + 1; int balance = getBalance (root); if (balance > 1 && getBalance (root.left) >= 0) return rightRotate (root); if (balance > 1 && getBalance (root.left) < 0) { root.left = leftRotate (root.left); return rightRotate (root); } if (balance < -1 && getBalance (root.right) <= 0) return leftRotate (root); if (balance < -1 && getBalance (root.right) > 0) { root.right = rightRotate (root.right); return leftRotate (root); } return root; } public void printTree(Node root) { if (root == null) return; printTree(root.left); System.out.print(root.key + " "); printTree(root.right); } public static void main (String[]args) { AVLTree tree = new AVLTree(); tree.root = new Node(13); tree.root.left = new Node(12); tree.root.left.left = new Node(11); tree.root.left.left.left = new Node(10); tree.root.right = new Node(14); tree.root.right.right = new Node(15); System.out.println("The AVL Tree is: "); tree.printTree(tree.root); tree.root = tree.deleteNode (tree.root, 10); System.out.println("\n----------------------------------------------\n"); System.out.println("The AVL Tree after deleting 10 is: "); tree.printTree(tree.root); System.out.println (""); } }
输出
The AVL Tree is: 10 11 12 13 14 15 ---------------------------------------------- The AVL Tree after deleting 10 is: 11 12 13 14 15
class Node(object): def __init__(self, data): self.data = data self.left = None self.right = None self.height = 1 class AVLTree(object): def insert(self, root, key): if not root: return Node(key) elif key < root.data: root.left = self.insert(root.left, key) else: root.right = self.insert(root.right, key) root.h = 1 + max(self.getHeight(root.left), self.getHeight(root.right)) b = self.getBalance(root) if b > 1 and key < root.left.data: return self.rightRotate(root) if b < -1 and key > root.right.data: return self.leftRotate(root) if b > 1 and key > root.left.data: root.left = self.lefttRotate(root.left) return self.rightRotate(root) if b < -1 and key < root.right.data: root.right = self.rightRotate(root.right) return self.leftRotate(root) return root def delete(self, root, key): if not root: return root elif key < root.data: root.left = self.delete(root.left, key) elif key > root.data: root.right = self.delete(root.right, key) else: if root.left is None: temp = root.right root = None return temp elif root.right is None: temp = root.left root = None return temp temp = self.getMindataueNode(root.right) root.data = temp.data root.right = self.delete(root.right, temp.data) if root is None: return root root.height = 1 + max(self.getHeight(root.left), self.getHeight(root.right)) balance = self.getBalance(root) if balance > 1 and self.getBalance(root.left) >= 0: return self.rightRotate(root) if balance < -1 and self.getBalance(root.right) <= 0: return self.leftRotate(root) if balance > 1 and self.getBalance(root.left) < 0: root.left = self.leftRotate(root.left) return self.rightRotate(root) if balance < -1 and self.getBalance(root.right) > 0: root.right = self.rightRotate(root.right) return self.leftRotate(root) return root def leftRotate(self, z): y = z.right T2 = y.left y.left = z z.right = T2 z.height = 1 + max(self.getHeight(z.left), self.getHeight(z.right)) y.height = 1 + max(self.getHeight(y.left), self.getHeight(y.right)) return y def rightRotate(self, z): y = z.left T3 = y.right y.right = z z.left = T3 z.height = 1 + max(self.getHeight(z.left), self.getHeight(z.right)) y.height = 1 + max(self.getHeight(y.left), self.getHeight(y.right)) return y def getHeight(self, root): if not root: return 0 return root.height def getBalance(self, root): if not root: return 0 return self.getHeight(root.left) - self.getHeight(root.right) def Inorder(self, root): if root.left: self.Inorder(root.left) print(root.data) if root.right: self.Inorder(root.right) Tree = AVLTree() root = None root = Tree.insert(root, 10) root = Tree.insert(root, 13) root = Tree.insert(root, 11) root = Tree.insert(root, 14) root = Tree.insert(root, 12) root = Tree.insert(root, 15) # Inorder Traversal print("Inorder traversal of the AVL tree is") Tree.Inorder(root) root = Tree.delete(root, 14) print("Inorder traversal of the modified AVL tree is") Tree.Inorder(root)
输出
Inorder traversal of the AVL tree is 10 11 12 13 14 15 Inorder traversal of the modified AVL tree is 10 11 12 13 15
AVL 树的实现
在以下实现中,我们考虑按升序排列的输入,并通过计算平衡因子和应用旋转将其存储在 AVL 树中。
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <stdlib.h> struct Node { int data; struct Node *leftChild; struct Node *rightChild; int height; }; int max(int a, int b); int height(struct Node *N){ if (N == NULL) return 0; return N->height; } int max(int a, int b){ return (a > b) ? a : b; } struct Node *newNode(int data){ struct Node *node = (struct Node *) malloc(sizeof(struct Node)); node->data = data; node->leftChild = NULL; node->rightChild = NULL; node->height = 1; return (node); } struct Node *rightRotate(struct Node *y){ struct Node *x = y->leftChild; struct Node *T2 = x->rightChild; x->rightChild = y; y->leftChild = T2; y->height = max(height(y->leftChild), height(y->rightChild)) + 1; x->height = max(height(x->leftChild), height(x->rightChild)) + 1; return x; } struct Node *leftRotate(struct Node *x){ struct Node *y = x->rightChild; struct Node *T2 = y->leftChild; y->leftChild = x; x->rightChild = T2; x->height = max(height(x->leftChild), height(x->rightChild)) + 1; y->height = max(height(y->leftChild), height(y->rightChild)) + 1; return y; } int getBalance(struct Node *N){ if (N == NULL) return 0; return height(N->leftChild) - height(N->rightChild); } struct Node *insertNode(struct Node *node, int data){ if (node == NULL) return (newNode(data)); if (data < node->data) node->leftChild = insertNode(node->leftChild, data); else if (data > node->data) node->rightChild = insertNode(node->rightChild, data); else return node; node->height = 1 + max(height(node->leftChild), height(node->rightChild)); int balance = getBalance(node); if (balance > 1 && data < node->leftChild->data) return rightRotate(node); if (balance < -1 && data > node->rightChild->data) return leftRotate(node); if (balance > 1 && data > node->leftChild->data) { node->leftChild = leftRotate(node->leftChild); return rightRotate(node); } if (balance < -1 && data < node->rightChild->data) { node->rightChild = rightRotate(node->rightChild); return leftRotate(node); } return node; } struct Node *minValueNode(struct Node *node){ struct Node *current = node; while (current->leftChild != NULL) current = current->leftChild; return current; } struct Node *deleteNode(struct Node *root, int data){ if (root == NULL) return root; if (data < root->data) root->leftChild = deleteNode(root->leftChild, data); else if (data > root->data) root->rightChild = deleteNode(root->rightChild, data); else { if ((root->leftChild == NULL) || (root->rightChild == NULL)) { struct Node *temp = root->leftChild ? root->leftChild : root->rightChild; if (temp == NULL) { temp = root; root = NULL; } else *root = *temp; free(temp); } else { struct Node *temp = minValueNode(root->rightChild); root->data = temp->data; root->rightChild = deleteNode(root->rightChild, temp->data); } } if (root == NULL) return root; root->height = 1 + max(height(root->leftChild), height(root->rightChild)); int balance = getBalance(root); if (balance > 1 && getBalance(root->leftChild) >= 0) return rightRotate(root); if (balance > 1 && getBalance(root->leftChild) < 0) { root->leftChild = leftRotate(root->leftChild); return rightRotate(root); } if (balance < -1 && getBalance(root->rightChild) <= 0) return leftRotate(root); if (balance < -1 && getBalance(root->rightChild) > 0) { root->rightChild = rightRotate(root->rightChild); return leftRotate(root); } return root; } // Print the tree void printTree(struct Node *root){ if (root != NULL) { printTree(root->leftChild); printf("%d ", root->data); printTree(root->rightChild); } } int main(){ struct Node *root = NULL; root = insertNode(root, 22); root = insertNode(root, 14); root = insertNode(root, 72); root = insertNode(root, 44); root = insertNode(root, 25); root = insertNode(root, 63); root = insertNode(root, 98); printf("AVL Tree: "); printTree(root); root = deleteNode(root, 25); printf("\nAfter deletion: "); printTree(root); return 0; }
输出
AVL Tree: 14 22 25 44 63 72 98 After deletion: 14 22 44 63 72 98
#include <iostream> struct Node { int data; struct Node *leftChild; struct Node *rightChild; int height; }; int max(int a, int b); int height(struct Node *N){ if (N == NULL) return 0; return N->height; } int max(int a, int b){ return (a > b) ? a : b; } struct Node *newNode(int data){ struct Node *node = (struct Node *) malloc(sizeof(struct Node)); node->data = data; node->leftChild = NULL; node->rightChild = NULL; node->height = 1; return (node); } struct Node *rightRotate(struct Node *y){ struct Node *x = y->leftChild; struct Node *T2 = x->rightChild; x->rightChild = y; y->leftChild = T2; y->height = max(height(y->leftChild), height(y->rightChild)) + 1; x->height = max(height(x->leftChild), height(x->rightChild)) + 1; return x; } struct Node *leftRotate(struct Node *x){ struct Node *y = x->rightChild; struct Node *T2 = y->leftChild; y->leftChild = x; x->rightChild = T2; x->height = max(height(x->leftChild), height(x->rightChild)) + 1; y->height = max(height(y->leftChild), height(y->rightChild)) + 1; return y; } int getBalance(struct Node *N){ if (N == NULL) return 0; return height(N->leftChild) - height(N->rightChild); } struct Node *insertNode(struct Node *node, int data){ if (node == NULL) return (newNode(data)); if (data < node->data) node->leftChild = insertNode(node->leftChild, data); else if (data > node->data) node->rightChild = insertNode(node->rightChild, data); else return node; node->height = 1 + max(height(node->leftChild), height(node->rightChild)); int balance = getBalance(node); if (balance > 1 && data < node->leftChild->data) return rightRotate(node); if (balance < -1 && data > node->rightChild->data) return leftRotate(node); if (balance > 1 && data > node->leftChild->data) { node->leftChild = leftRotate(node->leftChild); return rightRotate(node); } if (balance < -1 && data < node->rightChild->data) { node->rightChild = rightRotate(node->rightChild); return leftRotate(node); } return node; } struct Node *minValueNode(struct Node *node){ struct Node *current = node; while (current->leftChild != NULL) current = current->leftChild; return current; } struct Node *deleteNode(struct Node *root, int data){ if (root == NULL) return root; if (data < root->data) root->leftChild = deleteNode(root->leftChild, data); else if (data > root->data) root->rightChild = deleteNode(root->rightChild, data); else { if ((root->leftChild == NULL) || (root->rightChild == NULL)) { struct Node *temp = root->leftChild ? root->leftChild : root->rightChild; if (temp == NULL) { temp = root; root = NULL; } else *root = *temp; free(temp); } else { struct Node *temp = minValueNode(root->rightChild); root->data = temp->data; root->rightChild = deleteNode(root->rightChild, temp->data); } } if (root == NULL) return root; root->height = 1 + max(height(root->leftChild), height(root->rightChild)); int balance = getBalance(root); if (balance > 1 && getBalance(root->leftChild) >= 0) return rightRotate(root); if (balance > 1 && getBalance(root->leftChild) < 0) { root->leftChild = leftRotate(root->leftChild); return rightRotate(root); } if (balance < -1 && getBalance(root->rightChild) <= 0) return leftRotate(root); if (balance < -1 && getBalance(root->rightChild) > 0) { root->rightChild = rightRotate(root->rightChild); return leftRotate(root); } return root; } // Print the tree void printTree(struct Node *root){ if (root != NULL) { printTree(root->leftChild); printf("%d ", root->data); printTree(root->rightChild); } } int main(){ struct Node *root = NULL; root = insertNode(root, 22); root = insertNode(root, 14); root = insertNode(root, 72); root = insertNode(root, 44); root = insertNode(root, 25); root = insertNode(root, 63); root = insertNode(root, 98); printf("AVL Tree: "); printTree(root); root = deleteNode(root, 25); printf("\nAfter deletion: "); printTree(root); return 0; }
输出
AVL Tree: 14 22 25 44 63 72 98 After deletion: 14 22 44 63 72 98
import java.util.*; import java.io.*; class Node { int key, height; Node left, right; Node (int d) { key = d; height = 1; } } public class AVLTree { Node root; int height (Node N) { if (N == null) return 0; return N.height; } int max (int a, int b) { return (a > b) ? a : b; } Node rightRotate (Node y) { Node x = y.left; Node T2 = x.right; x.right = y; y.left = T2; y.height = max (height (y.left), height (y.right)) + 1; x.height = max (height (x.left), height (x.right)) + 1; return x; } Node leftRotate (Node x) { Node y = x.right; Node T2 = y.left; y.left = x; x.right = T2; x.height = max (height (x.left), height (x.right)) + 1; y.height = max (height (y.left), height (y.right)) + 1; return y; } int getBalance (Node N) { if (N == null) return 0; return height (N.left) - height (N.right); } Node insert (Node node, int key) { if (node == null) return (new Node (key)); if (key < node.key) node.left = insert (node.left, key); else if (key > node.key) node.right = insert (node.right, key); else return node; node.height = 1 + max (height (node.left), height (node.right)); int balance = getBalance (node); if (balance > 1 && key < node.left.key) return rightRotate (node); if (balance < -1 && key > node.right.key) return leftRotate (node); if (balance > 1 && key > node.left.key) { node.left = leftRotate (node.left); return rightRotate (node); } if (balance < -1 && key < node.right.key) { node.right = rightRotate (node.right); return leftRotate (node); } return node; } Node minValueNode (Node node) { Node current = node; while (current.left != null) current = current.left; return current; } Node deleteNode (Node root, int key) { if (root == null) return root; if (key < root.key) root.left = deleteNode (root.left, key); else if (key > root.key) root.right = deleteNode (root.right, key); else { if ((root.left == null) || (root.right == null)) { Node temp = null; if (temp == root.left) temp = root.right; else temp = root.left; if (temp == null) { temp = root; root = null; } else root = temp; } else { Node temp = minValueNode (root.right); root.key = temp.key; root.right = deleteNode (root.right, temp.key); } } if (root == null) return root; root.height = max (height (root.left), height (root.right)) + 1; int balance = getBalance (root); if (balance > 1 && getBalance (root.left) >= 0) return rightRotate (root); if (balance > 1 && getBalance (root.left) < 0) { root.left = leftRotate (root.left); return rightRotate (root); } if (balance < -1 && getBalance (root.right) <= 0) return leftRotate (root); if (balance < -1 && getBalance (root.right) > 0) { root.right = rightRotate (root.right); return leftRotate (root); } return root; } public void printTree(Node root) { if (root == null) return; printTree(root.left); System.out.println(root.key); printTree(root.right); } public static void main (String[]args) { AVLTree tree = new AVLTree(); tree.root = tree.insert (tree.root, 10); tree.root = tree.insert (tree.root, 11); tree.root = tree.insert (tree.root, 12); tree.root = tree.insert (tree.root, 13); tree.root = tree.insert (tree.root, 14); tree.root = tree.insert (tree.root, 15); System.out.println("The AVL Tree is: "); tree.printTree(tree.root); tree.root = tree.deleteNode (tree.root, 10); System.out.println("\n----------------------------------------------\n"); System.out.println("The AVL Tree after deleting 10 is: "); tree.printTree(tree.root); System.out.println (""); } }
输出
The AVL Tree is: 10 11 12 13 14 15 ---------------------------------------------- The AVL Tree after deleting 10 is: 11 12 13 14 15
class Node(object): def __init__(self, data): self.data = data self.left = None self.right = None self.height = 1 class AVLTree(object): def insert(self, root, key): if not root: return Node(key) elif key < root.data: root.left = self.insert(root.left, key) else: root.right = self.insert(root.right, key) root.h = 1 + max(self.getHeight(root.left), self.getHeight(root.right)) b = self.getBalance(root) if b > 1 and key < root.left.data: return self.rightRotate(root) if b < -1 and key > root.right.data: return self.leftRotate(root) if b > 1 and key > root.left.data: root.left = self.lefttRotate(root.left) return self.rightRotate(root) if b < -1 and key < root.right.data: root.right = self.rightRotate(root.right) return self.leftRotate(root) return root def delete(self, root, key): if not root: return root elif key < root.data: root.left = self.delete(root.left, key) elif key > root.data: root.right = self.delete(root.right, key) else: if root.left is None: temp = root.right root = None return temp elif root.right is None: temp = root.left root = None return temp temp = self.getMindataueNode(root.right) root.data = temp.data root.right = self.delete(root.right, temp.data) if root is None: return root root.height = 1 + max(self.getHeight(root.left), self.getHeight(root.right)) balance = self.getBalance(root) if balance > 1 and self.getBalance(root.left) >= 0: return self.rightRotate(root) if balance < -1 and self.getBalance(root.right) <= 0: return self.leftRotate(root) if balance > 1 and self.getBalance(root.left) < 0: root.left = self.leftRotate(root.left) return self.rightRotate(root) if balance < -1 and self.getBalance(root.right) > 0: root.right = self.rightRotate(root.right) return self.leftRotate(root) return root def leftRotate(self, z): y = z.right T2 = y.left y.left = z z.right = T2 z.height = 1 + max(self.getHeight(z.left), self.getHeight(z.right)) y.height = 1 + max(self.getHeight(y.left), self.getHeight(y.right)) return y def rightRotate(self, z): y = z.left T3 = y.right y.right = z z.left = T3 z.height = 1 + max(self.getHeight(z.left), self.getHeight(z.right)) y.height = 1 + max(self.getHeight(y.left), self.getHeight(y.right)) return y def getHeight(self, root): if not root: return 0 return root.height def getBalance(self, root): if not root: return 0 return self.getHeight(root.left) - self.getHeight(root.right) def Inorder(self, root): if root.left: self.Inorder(root.left) print(root.data) if root.right: self.Inorder(root.right) Tree = AVLTree() root = None root = Tree.insert(root, 10) root = Tree.insert(root, 13) root = Tree.insert(root, 11) root = Tree.insert(root, 14) root = Tree.insert(root, 12) root = Tree.insert(root, 15) # Inorder Traversal print("Inorder traversal of the AVL tree is") Tree.Inorder(root) root = Tree.delete(root, 14) print("Inorder traversal of the modified AVL tree is") Tree.Inorder(root)
输出
Inorder traversal of the AVL tree is 10 11 12 13 14 15 Inorder traversal of the modified AVL tree is 10 11 12 13 15
红黑树
红黑树是另一种类型的平衡二叉搜索树,它有两个颜色的节点:红色和黑色。它是一种自平衡二叉搜索树,利用这些颜色在插入和删除操作期间保持平衡因子。因此,在红黑树操作期间,内存使用 1 位存储来容纳每个节点的颜色信息
在红黑树(也称为 RB 树)中,在为节点分配颜色时需要遵循不同的条件。
根节点始终为黑色。
不允许两个相邻节点都是红色。
树中的每条路径(从根节点到叶子节点)必须具有相同数量的黑色节点。
尽管 AVL 树比 RB 树更平衡,并且 AVL 树中的平衡算法比 RB 树更严格,但通过 RB 树可以使多次和更快的插入和删除操作效率更高。
图:RB 树
红黑树的基本操作
红黑树上的操作包括通常在二叉搜索树上执行的所有基本操作。RB 树的一些基本操作包括:
插入
删除
搜索
红黑树的插入操作遵循与二叉搜索树相同的插入算法。元素按照二叉搜索属性插入,并且作为补充,节点被颜色编码为红色和黑色,以根据红黑树属性平衡树。
按照以下步骤,通过维护二叉搜索树和红黑树属性,将元素插入红黑树。
**情况 1**——检查树是否为空;如果为空,则将当前节点设为根节点并将其颜色设置为黑色。
**情况 2**——但如果树不为空,我们创建一个新节点并将其颜色设置为红色。这里我们面临两种不同的情况:
如果新节点的父节点是黑色节点,则退出操作,树保持不变。
如果新节点的父节点是红色,并且父节点的兄弟节点的颜色为黑色或不存在,则应用合适的旋转并相应地重新着色。
如果新节点的父节点是红色,并且父节点的兄弟节点的颜色是红色,则将父节点、兄弟节点和祖父母节点重新着色为黑色。仅当祖父母节点**不是**根节点时才重新着色;如果是根节点,则仅重新着色父节点和兄弟节点。
插入示例
让我们为前 7 个整数构建一个 RB 树,以便详细了解插入操作:
检查树是否为空,因此添加的第一个节点是根节点,颜色为黑色。
现在,树不为空,因此我们创建一个新节点并添加下一个整数,颜色为红色,
节点不违反二叉搜索树和 RB 树属性,因此我们继续添加另一个节点。
树不为空;我们创建一个新的红色节点,并将其与下一个整数连接。但是,新节点的父节点不是黑色节点,
当前这棵树违反了二叉搜索树和红黑树的性质;由于父节点的兄弟节点为NULL,我们应用合适的旋转并重新着色节点。
现在红黑树的性质已经恢复,我们向树中添加另一个节点 -
这棵树再次违反了红黑树的平衡性质,所以我们检查父节点的兄弟节点颜色,在本例中为红色,所以我们只需重新着色父节点和兄弟节点。
接下来我们插入元素5,这使得树再次违反了红黑树的平衡性质。
并且由于兄弟节点为NULL,我们应用合适的旋转和重新着色。
现在,我们插入元素6,但红黑树的性质被违反,需要应用插入情况之一 -
父节点的兄弟节点为红色,所以我们重新着色父节点、父节点的兄弟节点和祖父母节点,因为祖父母节点不是根节点。
现在,我们添加最后一个元素7,但这个新节点的父节点为红色。
由于父节点的兄弟节点为NULL,我们应用合适的旋转(RR旋转)
最终得到了红黑树。
删除
红黑树上的删除操作必须以这样一种方式执行,即它必须恢复二叉搜索树和红黑树的所有性质。按照以下步骤在红黑树上执行删除操作 -
首先,我们根据二叉搜索树的性质执行删除操作。
情况1 - 如果要删除的节点或节点的父节点为红色,则直接删除它。
情况2 - 如果节点为双黑节点,则只需移除双黑节点(当要删除的节点是黑色叶子节点时,会发生双黑节点,因为它累加了被认为是黑色节点的NULL节点)
情况3 - 如果双黑节点的兄弟节点也是黑色节点,并且它的子节点也是黑色,则按照以下步骤 -
移除双黑节点
将其父节点重新着色为黑色(如果父节点是红色节点,则变为黑色;如果父节点已经是黑色节点,则变为双黑节点)
将父节点的兄弟节点重新着色为红色
如果双黑节点仍然存在,则应用其他情况。
情况4 - 如果双黑节点的兄弟节点为红色,则执行以下步骤 -
交换父节点和父节点的兄弟节点的颜色。
朝双黑节点的方向旋转父节点
重新应用其他合适的情况。
情况5 - 如果双黑节点的兄弟节点是黑色节点,但兄弟节点中距离双黑节点最近的子节点是红色,则按照以下步骤 -
交换双黑节点的兄弟节点和该兄弟节点的子节点的颜色
朝与双黑节点相反的方向旋转兄弟节点(即如果双黑节点是右孩子,则应用左旋转,反之亦然)
应用情况6。
情况6 - 如果双黑节点的兄弟节点是黑色节点,但兄弟节点中距离双黑节点较远的子节点是红色,则按照以下步骤 -
交换双黑节点的父节点和兄弟节点的颜色
朝双黑节点的方向旋转父节点(即如果双黑节点是右孩子,则应用右旋转,反之亦然)
移除双黑节点
将红色子节点的颜色改为黑色。
删除示例
考虑上面构建的相同的红黑树,让我们从树中删除一些元素。
从树中删除元素4、5、3。
要删除元素4,让我们首先执行二叉搜索删除。
执行二叉搜索删除后,红黑树的性质没有受到干扰,因此树保持不变。
然后,我们使用二叉搜索删除来删除元素5
但是执行二叉搜索删除后,红黑树的性质被破坏了,即树中所有路径不包含相同数量的黑色节点;所以我们交换颜色来平衡树。
然后,我们从得到的树中删除节点3 -
应用二叉搜索删除,我们正常删除节点3,因为它是一个叶子节点。并且我们得到一个双节点,因为3是一个黑色节点。
我们应用情况3删除,因为双黑节点的兄弟节点是黑色,并且它的子节点也是黑色。在这里,我们移除双黑节点,重新着色双黑节点的父节点和兄弟节点。
所有需要的节点都被删除,并且红黑树的性质得以维护。
搜索
红黑树中的搜索操作遵循与二叉搜索树相同的算法。遍历树,并将每个节点与要搜索的关键元素进行比较;如果找到,则返回成功搜索。否则,返回不成功搜索。
完整实现
输出
// C++ program for Red black trees algorithmn #include <iostream> using namespace std; struct Node { int data; Node *parent; Node *left; Node *right; int color; }; typedef Node *NodePtr; class RedBlackTree { private: NodePtr root; NodePtr TNULL; void initializeNULLNode(NodePtr node, NodePtr parent) { node->data = 0; node->parent = parent; node->left = nullptr; node->right = nullptr; node->color = 0; } // Preorder void preOrderHelper(NodePtr node) { if (node != TNULL) { cout << node->data << " "; preOrderHelper(node->left); preOrderHelper(node->right); } } // Inorder void inOrderHelper(NodePtr node) { if (node != TNULL) { inOrderHelper(node->left); cout << node->data << " "; inOrderHelper(node->right); } } // Post order void postOrderHelper(NodePtr node) { if (node != TNULL) { postOrderHelper(node->left); postOrderHelper(node->right); cout << node->data << " "; } } NodePtr searchTreeHelper(NodePtr node, int key) { if (node == TNULL || key == node->data) { return node; } if (key < node->data) { return searchTreeHelper(node->left, key); } return searchTreeHelper(node->right, key); } // For balancing the tree after deletion void deleteFix(NodePtr x) { NodePtr s; while (x != root && x->color == 0) { if (x == x->parent->left) { s = x->parent->right; if (s->color == 1) { s->color = 0; x->parent->color = 1; leftRotate(x->parent); s = x->parent->right; } if (s->left->color == 0 && s->right->color == 0) { s->color = 1; x = x->parent; } else { if (s->right->color == 0) { s->left->color = 0; s->color = 1; rightRotate(s); s = x->parent->right; } s->color = x->parent->color; x->parent->color = 0; s->right->color = 0; leftRotate(x->parent); x = root; } } else { s = x->parent->left; if (s->color == 1) { s->color = 0; x->parent->color = 1; rightRotate(x->parent); s = x->parent->left; } if (s->right->color == 0 && s->right->color == 0) { s->color = 1; x = x->parent; } else { if (s->left->color == 0) { s->right->color = 0; s->color = 1; leftRotate(s); s = x->parent->left; } s->color = x->parent->color; x->parent->color = 0; s->left->color = 0; rightRotate(x->parent); x = root; } } } x->color = 0; } void rbTransplant(NodePtr u, NodePtr v) { if (u->parent == nullptr) { root = v; } else if (u == u->parent->left) { u->parent->left = v; } else { u->parent->right = v; } v->parent = u->parent; } void deleteNodeHelper(NodePtr node, int key) { NodePtr z = TNULL; NodePtr x, y; while (node != TNULL) { if (node->data == key) { z = node; } if (node->data <= key) { node = node->right; } else { node = node->left; } } if (z == TNULL) { cout << "Key not found in the tree" << endl; return; } y = z; int y_original_color = y->color; if (z->left == TNULL) { x = z->right; rbTransplant(z, z->right); } else if (z->right == TNULL) { x = z->left; rbTransplant(z, z->left); } else { y = minimum(z->right); y_original_color = y->color; x = y->right; if (y->parent == z) { x->parent = y; } else { rbTransplant(y, y->right); y->right = z->right; y->right->parent = y; } rbTransplant(z, y); y->left = z->left; y->left->parent = y; y->color = z->color; } delete z; if (y_original_color == 0) { deleteFix(x); } } // For balancing the tree after insertion void insertFix(NodePtr k) { NodePtr u; while (k->parent->color == 1) { if (k->parent == k->parent->parent->right) { u = k->parent->parent->left; if (u->color == 1) { u->color = 0; k->parent->color = 0; k->parent->parent->color = 1; k = k->parent->parent; } else { if (k == k->parent->left) { k = k->parent; rightRotate(k); } k->parent->color = 0; k->parent->parent->color = 1; leftRotate(k->parent->parent); } } else { u = k->parent->parent->right; if (u->color == 1) { u->color = 0; k->parent->color = 0; k->parent->parent->color = 1; k = k->parent->parent; } else { if (k == k->parent->right) { k = k->parent; leftRotate(k); } k->parent->color = 0; k->parent->parent->color = 1; rightRotate(k->parent->parent); } } if (k == root) { break; } } root->color = 0; } void printHelper(NodePtr root, string indent, bool last) { if (root != TNULL) { cout << indent; if (last) { cout << "R----"; indent += " "; } else { cout << "L----"; indent += "| "; } string sColor = root->color ? "RED" : "BLACK"; cout << root->data << "(" << sColor << ")" << endl; printHelper(root->left, indent, false); printHelper(root->right, indent, true); } } public: RedBlackTree() { TNULL = new Node; TNULL->color = 0; TNULL->left = nullptr; TNULL->right = nullptr; root = TNULL; } void preorder() { preOrderHelper(this->root); } void inorder() { inOrderHelper(this->root); } void postorder() { postOrderHelper(this->root); } NodePtr searchTree(int k) { return searchTreeHelper(this->root, k); } NodePtr minimum(NodePtr node) { while (node->left != TNULL) { node = node->left; } return node; } NodePtr maximum(NodePtr node) { while (node->right != TNULL) { node = node->right; } return node; } NodePtr successor(NodePtr x) { if (x->right != TNULL) { return minimum(x->right); } NodePtr y = x->parent; while (y != TNULL && x == y->right) { x = y; y = y->parent; } return y; } NodePtr predecessor(NodePtr x) { if (x->left != TNULL) { return maximum(x->left); } NodePtr y = x->parent; while (y != TNULL && x == y->left) { x = y; y = y->parent; } return y; } void leftRotate(NodePtr x) { NodePtr y = x->right; x->right = y->left; if (y->left != TNULL) { y->left->parent = x; } y->parent = x->parent; if (x->parent == nullptr) { this->root = y; } else if (x == x->parent->left) { x->parent->left = y; } else { x->parent->right = y; } y->left = x; x->parent = y; } void rightRotate(NodePtr x) { NodePtr y = x->left; x->left = y->right; if (y->right != TNULL) { y->right->parent = x; } y->parent = x->parent; if (x->parent == nullptr) { this->root = y; } else if (x == x->parent->right) { x->parent->right = y; } else { x->parent->left = y; } y->right = x; x->parent = y; } // Inserting a node void insert(int key) { NodePtr node = new Node; node->parent = nullptr; node->data = key; node->left = TNULL; node->right = TNULL; node->color = 1; NodePtr y = nullptr; NodePtr x = this->root; while (x != TNULL) { y = x; if (node->data < x->data) { x = x->left; } else { x = x->right; } } node->parent = y; if (y == nullptr) { root = node; } else if (node->data < y->data) { y->left = node; } else { y->right = node; } if (node->parent == nullptr) { node->color = 0; return; } if (node->parent->parent == nullptr) { return; } insertFix(node); } NodePtr getRoot() { return this->root; } void deleteNode(int data) { deleteNodeHelper(this->root, data); } void printTree() { if (root) { printHelper(this->root, "", true); } } }; int main() { RedBlackTree V; V.insert(24); V.insert(33); V.insert(42); V.insert(51); V.insert(60); V.insert(40); V.insert(22); V.printTree(); cout << endl << "After deleting an element" << endl; V.deleteNode(40); V.printTree(); }
输出
R----33(BLACK) L----24(BLACK) | L----22(RED) R----51(RED) L----42(BLACK) | L----40(RED) R----60(BLACK) After deleting an element R----33(BLACK) L----24(BLACK) | L----22(RED) R----51(RED) L----42(BLACK) R----60(BLACK)
// Implementing Red-Black Tree in Java class Node { int data; Node parent; Node left; Node right; int color; } public class RedBlackTree { private Node root; private Node TNULL; // Preorder private void preOrderHelper(Node node) { if (node != TNULL) { System.out.print(node.data + " "); preOrderHelper(node.left); preOrderHelper(node.right); } } // Inorder private void inOrderHelper(Node node) { if (node != TNULL) { inOrderHelper(node.left); System.out.print(node.data + " "); inOrderHelper(node.right); } } // Post order private void postOrderHelper(Node node) { if (node != TNULL) { postOrderHelper(node.left); postOrderHelper(node.right); System.out.print(node.data + " "); } } // Search the tree private Node searchTreeHelper(Node node, int key) { if (node == TNULL || key == node.data) { return node; } if (key < node.data) { return searchTreeHelper(node.left, key); } return searchTreeHelper(node.right, key); } // Balance the tree after deletion of a node private void fixDelete(Node x) { Node s; while (x != root && x.color == 0) { if (x == x.parent.left) { s = x.parent.right; if (s.color == 1) { s.color = 0; x.parent.color = 1; leftRotate(x.parent); s = x.parent.right; } if (s.left.color == 0 && s.right.color == 0) { s.color = 1; x = x.parent; } else { if (s.right.color == 0) { s.left.color = 0; s.color = 1; rightRotate(s); s = x.parent.right; } s.color = x.parent.color; x.parent.color = 0; s.right.color = 0; leftRotate(x.parent); x = root; } } else { s = x.parent.left; if (s.color == 1) { s.color = 0; x.parent.color = 1; rightRotate(x.parent); s = x.parent.left; } if (s.right.color == 0 && s.right.color == 0) { s.color = 1; x = x.parent; } else { if (s.left.color == 0) { s.right.color = 0; s.color = 1; leftRotate(s); s = x.parent.left; } s.color = x.parent.color; x.parent.color = 0; s.left.color = 0; rightRotate(x.parent); x = root; } } } x.color = 0; } private void rbTransplant(Node u, Node v) { if (u.parent == null) { root = v; } else if (u == u.parent.left) { u.parent.left = v; } else { u.parent.right = v; } v.parent = u.parent; } private void deleteNodeHelper(Node node, int key) { Node z = TNULL; Node x, y; while (node != TNULL) { if (node.data == key) { z = node; } if (node.data <= key) { node = node.right; } else { node = node.left; } } if (z == TNULL) { System.out.println("Couldn't find key in the tree"); return; } y = z; int yOriginalColor = y.color; if (z.left == TNULL) { x = z.right; rbTransplant(z, z.right); } else if (z.right == TNULL) { x = z.left; rbTransplant(z, z.left); } else { y = minimum(z.right); yOriginalColor = y.color; x = y.right; if (y.parent == z) { x.parent = y; } else { rbTransplant(y, y.right); y.right = z.right; y.right.parent = y; } rbTransplant(z, y); y.left = z.left; y.left.parent = y; y.color = z.color; } if (yOriginalColor == 0) { fixDelete(x); } } // Balance the node after insertion private void fixInsert(Node k) { Node u; while (k.parent.color == 1) { if (k.parent == k.parent.parent.right) { u = k.parent.parent.left; if (u.color == 1) { u.color = 0; k.parent.color = 0; k.parent.parent.color = 1; k = k.parent.parent; } else { if (k == k.parent.left) { k = k.parent; rightRotate(k); } k.parent.color = 0; k.parent.parent.color = 1; leftRotate(k.parent.parent); } } else { u = k.parent.parent.right; if (u.color == 1) { u.color = 0; k.parent.color = 0; k.parent.parent.color = 1; k = k.parent.parent; } else { if (k == k.parent.right) { k = k.parent; leftRotate(k); } k.parent.color = 0; k.parent.parent.color = 1; rightRotate(k.parent.parent); } } if (k == root) { break; } } root.color = 0; } private void printHelper(Node root, String indent, boolean last) { if (root != TNULL) { System.out.print(indent); if (last) { System.out.print("R----"); indent += " "; } else { System.out.print("L----"); indent += "| "; } String sColor = root.color == 1 ? "RED" : "BLACK"; System.out.println(root.data + "(" + sColor + ")"); printHelper(root.left, indent, false); printHelper(root.right, indent, true); } } public RedBlackTree() { TNULL = new Node(); TNULL.color = 0; TNULL.left = null; TNULL.right = null; root = TNULL; } public void preorder() { preOrderHelper(this.root); } public void inorder() { inOrderHelper(this.root); } public void postorder() { postOrderHelper(this.root); } public Node searchTree(int k) { return searchTreeHelper(this.root, k); } public Node minimum(Node node) { while (node.left != TNULL) { node = node.left; } return node; } public Node maximum(Node node) { while (node.right != TNULL) { node = node.right; } return node; } public Node successor(Node x) { if (x.right != TNULL) { return minimum(x.right); } Node y = x.parent; while (y != TNULL && x == y.right) { x = y; y = y.parent; } return y; } public Node predecessor(Node x) { if (x.left != TNULL) { return maximum(x.left); } Node y = x.parent; while (y != TNULL && x == y.left) { x = y; y = y.parent; } return y; } public void leftRotate(Node x) { Node y = x.right; x.right = y.left; if (y.left != TNULL) { y.left.parent = x; } y.parent = x.parent; if (x.parent == null) { this.root = y; } else if (x == x.parent.left) { x.parent.left = y; } else { x.parent.right = y; } y.left = x; x.parent = y; } public void rightRotate(Node x) { Node y = x.left; x.left = y.right; if (y.right != TNULL) { y.right.parent = x; } y.parent = x.parent; if (x.parent == null) { this.root = y; } else if (x == x.parent.right) { x.parent.right = y; } else { x.parent.left = y; } y.right = x; x.parent = y; } public void insert(int key) { Node node = new Node(); node.parent = null; node.data = key; node.left = TNULL; node.right = TNULL; node.color = 1; Node y = null; Node x = this.root; while (x != TNULL) { y = x; if (node.data < x.data) { x = x.left; } else { x = x.right; } } node.parent = y; if (y == null) { root = node; } else if (node.data < y.data) { y.left = node; } else { y.right = node; } if (node.parent == null) { node.color = 0; return; } if (node.parent.parent == null) { return; } fixInsert(node); } public Node getRoot() { return this.root; } public void deleteNode(int data) { deleteNodeHelper(this.root, data); } public void printTree() { printHelper(this.root, "", true); } public static void main(String[] args) { RedBlackTree V = new RedBlackTree(); V.insert(24); V.insert(33); V.insert(42); V.insert(51); V.insert(60); V.insert(40); V.insert(22); V.printTree(); System.out.println("\nAfter deleting an element:"); V.deleteNode(40); V.printTree(); } }
输出
R----33(BLACK) L----24(BLACK) | L----22(RED) R----51(RED) L----42(BLACK) | L----40(RED) R----60(BLACK) After deleting an element: R----33(BLACK) L----24(BLACK) | L----22(RED) R----51(RED) L----42(BLACK) R----60(BLACK)
#python program for Red black trees import sys # Node creation class Node(): def __init__(self, item): self.item = item self.parent = None self.left = None self.right = None self.color = 1 class RedBlackTree(): def __init__(self): self.TNULL = Node(0) self.TNULL.color = 0 self.TNULL.left = None self.TNULL.right = None self.root = self.TNULL # Preorder def pre_order_helper(self, node): if node != TNULL: sys.stdout.write(node.item + " ") self.pre_order_helper(node.left) self.pre_order_helper(node.right) # Inorder def in_order_helper(self, node): if node != TNULL: self.in_order_helper(node.left) sys.stdout.write(node.item + " ") self.in_order_helper(node.right) # Postorder def post_order_helper(self, node): if node != TNULL: self.post_order_helper(node.left) self.post_order_helper(node.right) sys.stdout.write(node.item + " ") # Search the tree def search_tree_helper(self, node, key): if node == TNULL or key == node.item: return node if key < node.item: return self.search_tree_helper(node.left, key) return self.search_tree_helper(node.right, key) # Balancing the tree after deletion def delete_fix(self, x): while x != self.root and x.color == 0: if x == x.parent.left: s = x.parent.right if s.color == 1: s.color = 0 x.parent.color = 1 self.left_rotate(x.parent) s = x.parent.right if s.left.color == 0 and s.right.color == 0: s.color = 1 x = x.parent else: if s.right.color == 0: s.left.color = 0 s.color = 1 self.right_rotate(s) s = x.parent.right s.color = x.parent.color x.parent.color = 0 s.right.color = 0 self.left_rotate(x.parent) x = self.root else: s = x.parent.left if s.color == 1: s.color = 0 x.parent.color = 1 self.right_rotate(x.parent) s = x.parent.left if s.right.color == 0 and s.right.color == 0: s.color = 1 x = x.parent else: if s.left.color == 0: s.right.color = 0 s.color = 1 self.left_rotate(s) s = x.parent.left s.color = x.parent.color x.parent.color = 0 s.left.color = 0 self.right_rotate(x.parent) x = self.root x.color = 0 def __rb_transplant(self, u, v): if u.parent == None: self.root = v elif u == u.parent.left: u.parent.left = v else: u.parent.right = v v.parent = u.parent # Node deletion def delete_node_helper(self, node, key): z = self.TNULL while node != self.TNULL: if node.item == key: z = node if node.item <= key: node = node.right else: node = node.left if z == self.TNULL: print("Cannot find key in the tree") return y = z y_original_color = y.color if z.left == self.TNULL: x = z.right self.__rb_transplant(z, z.right) elif (z.right == self.TNULL): x = z.left self.__rb_transplant(z, z.left) else: y = self.minimum(z.right) y_original_color = y.color x = y.right if y.parent == z: x.parent = y else: self.__rb_transplant(y, y.right) y.right = z.right y.right.parent = y self.__rb_transplant(z, y) y.left = z.left y.left.parent = y y.color = z.color if y_original_color == 0: self.delete_fix(x) # Balance the tree after insertion def fix_insert(self, k): while k.parent.color == 1: if k.parent == k.parent.parent.right: u = k.parent.parent.left if u.color == 1: u.color = 0 k.parent.color = 0 k.parent.parent.color = 1 k = k.parent.parent else: if k == k.parent.left: k = k.parent self.right_rotate(k) k.parent.color = 0 k.parent.parent.color = 1 self.left_rotate(k.parent.parent) else: u = k.parent.parent.right if u.color == 1: u.color = 0 k.parent.color = 0 k.parent.parent.color = 1 k = k.parent.parent else: if k == k.parent.right: k = k.parent self.left_rotate(k) k.parent.color = 0 k.parent.parent.color = 1 self.right_rotate(k.parent.parent) if k == self.root: break self.root.color = 0 # Printing the tree def __print_helper(self, node, indent, last): if node != self.TNULL: sys.stdout.write(indent) if last: sys.stdout.write("R----") indent += " " else: sys.stdout.write("L----") indent += "| " s_color = "RED" if node.color == 1 else "BLACK" print(str(node.item) + "(" + s_color + ")") self.__print_helper(node.left, indent, False) self.__print_helper(node.right, indent, True) def preorder(self): self.pre_order_helper(self.root) def inorder(self): self.in_order_helper(self.root) def postorder(self): self.post_order_helper(self.root) def searchTree(self, k): return self.search_tree_helper(self.root, k) def minimum(self, node): while node.left != self.TNULL: node = node.left return node def maximum(self, node): while node.right != self.TNULL: node = node.right return node def successor(self, x): if x.right != self.TNULL: return self.minimum(x.right) y = x.parent while y != self.TNULL and x == y.right: x = y y = y.parent return y def predecessor(self, x): if (x.left != self.TNULL): return self.maximum(x.left) y = x.parent while y != self.TNULL and x == y.left: x = y y = y.parent return y def left_rotate(self, x): y = x.right x.right = y.left if y.left != self.TNULL: y.left.parent = x y.parent = x.parent if x.parent == None: self.root = y elif x == x.parent.left: x.parent.left = y else: x.parent.right = y y.left = x x.parent = y def right_rotate(self, x): y = x.left x.left = y.right if y.right != self.TNULL: y.right.parent = x y.parent = x.parent if x.parent == None: self.root = y elif x == x.parent.right: x.parent.right = y else: x.parent.left = y y.right = x x.parent = y def insert(self, key): node = Node(key) node.parent = None node.item = key node.left = self.TNULL node.right = self.TNULL node.color = 1 y = None x = self.root while x != self.TNULL: y = x if node.item < x.item: x = x.left else: x = x.right node.parent = y if y == None: self.root = node elif node.item < y.item: y.left = node else: y.right = node if node.parent == None: node.color = 0 return if node.parent.parent == None: return self.fix_insert(node) def get_root(self): return self.root def delete_node(self, item): self.delete_node_helper(self.root, item) def print_tree(self): self.__print_helper(self.root, "", True) if __name__ == "__main__": V = RedBlackTree() V.insert(24) V.insert(33) V.insert(42) V.insert(51) V.insert(60) V.insert(40) V.insert(22) V.print_tree() print("\nAfter deleting an element") V.delete_node(40) V.print_tree()
输出
R----33(BLACK) L----24(BLACK) | L----22(RED) R----51(RED) L----42(BLACK) | L----40(RED) R----60(BLACK) After deleting an element R----33(BLACK) L----24(BLACK) | L----22(RED) R----51(RED) L----42(BLACK) R----60(BLACK)
B 树
B树是扩展的二叉搜索树,专门用于m路搜索,因为B树的阶数为'm'。树的阶数定义为一个节点可以容纳的最大子节点数。因此,B树的高度相对小于AVL树和红黑树的高度。
它们是二叉搜索树的一般形式,因为它可以保存多个键和两个子节点。
B树的各种性质包括 -
B树中的每个节点最多包含m个子节点和(m-1)个键,因为树的阶数为m。
B树中除根节点和叶子节点外的每个节点至少包含m/2个子节点
根节点必须至少有两个子节点。
B树中的所有路径必须在同一级别结束,即叶子节点必须在同一级别。
B树始终保持数据排序。
B树也广泛用于磁盘访问,最大限度地减少磁盘访问时间,因为B树的高度较低。
注意 - 磁盘访问是访问存储信息的计算机磁盘的内存访问,磁盘访问时间是系统访问磁盘内存所需的时间。
B树的基本操作
B树支持的操作包括插入、删除和搜索,每个操作的时间复杂度为O(log n)。
插入
B树的插入操作类似于二叉搜索树,但元素被插入到同一个节点,直到达到最大键数。插入使用以下过程完成 -
步骤1 - 计算节点可以容纳的最大$\mathrm{\left ( m-1 \right )}$和最小$\mathrm{\left ( \left \lceil \frac{m}{2}\right \rceil-1 \right )}$键数,其中m表示B树的阶数。
步骤2 - 使用二叉搜索插入将数据插入到树中,一旦键达到最大数量,节点就被分成两半,中间键成为内部节点,而左右键成为其子节点。
步骤3 - 所有叶子节点必须在同一级别。
键5、3、21、9、13都根据二叉搜索属性添加到节点中,但如果我们添加键22,它将违反最大键属性。因此,节点被分成两半,中间键被移到父节点,然后继续插入。
在插入11时发生另一个问题,因此节点被分割,中间键被移到父节点。
在插入16时,即使节点被分成两部分,父节点也会溢出,因为它达到了最大键数。因此,父节点首先被分割,中间键成为根节点。然后,叶子节点被分成两半,叶子节点的中值被移到其父节点。
插入所有元素后的最终B树。
示例
// Insert the value void insertion(int item) { int flag, i; struct btreeNode *child; flag = setNodeValue(item, &i, root, &child); if (flag) root = createNode(i, child); }
删除
B树中的删除操作与二叉搜索树的删除操作略有不同。从B树中删除节点的过程如下 -
情况1 - 如果要删除的键位于叶子节点中,并且删除不会违反最小键属性,则只需删除该节点。
情况2 - 如果要删除的键位于叶子节点中,但删除违反了最小键属性,则从其左兄弟节点或右兄弟节点借用一个键。如果两个兄弟节点都恰好具有最少的键数,则将该节点合并到其中一个中。
情况3 - 如果要删除的键位于内部节点中,则将其替换为左子节点或右子节点中的一个键,具体取决于哪个子节点具有更多键。但如果两个子节点都具有最少的键数,则将它们合并在一起。
情况4 - 如果要删除的键位于内部节点中,违反了最小键属性,并且其两个子节点和兄弟节点都具有最少的键数,则合并子节点。然后将其兄弟节点与其父节点合并。
以下是B树中删除操作的功能性C++代码片段 -
// Deletion operation void deletion(int key){ int index = searchkey(key); if (index < n && keys[index] == key) { if (leaf) deletion_at_leaf(index); else deletion_at_nonleaf(index); } else { if (leaf) { cout << "key " << key << " does not exist in the tree\n"; return; } bool flag = ((index == n) ? true : false); if (C[index]->n < t) fill(index); if (flag && index > n) C[index - 1]->deletion(key); else C[index]->deletion(key); } return; } // Deletion at the leaf nodes void deletion_at_leaf(int index){ for (int i = index + 1; i < n; ++i) keys[i - 1] = keys[i]; n--; return; } // Deletion at the non leaf node void deletion_at_nonleaf(int index){ int key = keys[index]; if (C[index]->n >= t) { int pred = get_Predecessor(index); keys[index] = pred; C[index]->deletion(pred); } else if (C[index + 1]->n >= t) { int successor = copysuccessoressor(index); keys[index] = successor; C[index + 1]->deletion(successor); } else { merge(index); C[index]->deletion(key); } return; }
示例
// C Program for B trees #include <stdio.h> #include <stdlib.h> struct BTree { //node declaration int *d; struct BTree **child_ptr; int l; int n; }; struct BTree *r = NULL; struct BTree *np = NULL; struct BTree *x = NULL; //creation of node struct BTree* init() { int i; np = (struct BTree*)malloc(sizeof(struct BTree)); //order 6 np->d = (int*)malloc(6 * sizeof(int)); np->child_ptr = (struct BTree**)malloc(7 * sizeof(struct BTree*)); np->l = 1; np->n = 0; for (i = 0; i < 7; i++) { np->child_ptr[i] = NULL; } return np; } //traverse the tree void traverse(struct BTree *p) { printf("\n"); int i; for (i = 0; i < p->n; i++) { if (p->l == 0) { traverse(p->child_ptr[i]); } printf(" %d", p->d[i]); } if (p->l == 0) { traverse(p->child_ptr[i]); } printf("\n"); } //sort the tree void sort(int *p, int n) { int i, j, t; for (i = 0; i < n; i++) { for (j = i; j <= n; j++) { if (p[i] > p[j]) { t = p[i]; p[i] = p[j]; p[j] = t; } } } } int split_child(struct BTree *x, int i) { int j, mid; struct BTree *np1, *np3, *y; np3 = init(); //create new node np3->l = 1; if (i == -1) { mid = x->d[2]; //find mid x->d[2] = 0; x->n--; np1 = init(); np1->l = 0; x->l = 1; for (j = 3; j < 6; j++) { np3->d[j - 3] = x->d[j]; np3->child_ptr[j - 3] = x->child_ptr[j]; np3->n++; x->d[j] = 0; x->n--; } for (j = 0; j < 6; j++) { x->child_ptr[j] = NULL; } np1->d[0] = mid; np1->child_ptr[np1->n] = x; np1->child_ptr[np1->n + 1] = np3; np1->n++; r = np1; } else { y = x->child_ptr[i]; mid = y->d[2]; y->d[2] = 0; y->n--; for (j = 3; j < 6; j++) { np3->d[j - 3] = y->d[j]; np3->n++; y->d[j] = 0; y->n--; } x->child_ptr[i + 1] = y; x->child_ptr[i + 1] = np3; } return mid; } void insert(int a) { int i, t; x = r; if (x == NULL) { r = init(); x = r; } else { if (x->l == 1 && x->n == 6) { t = split_child(x, -1); x = r; for (i = 0; i < x->n; i++) { if (a > x->d[i] && a < x->d[i + 1]) { i++; break; } else if (a < x->d[0]) { break; } else { continue; } } x = x->child_ptr[i]; } else { while (x->l == 0) { for (i = 0; i < x->n; i++) { if (a > x->d[i] && a < x->d[i + 1]) { i++; break; } else if (a < x->d[0]) { break; } else { continue; } } if (x->child_ptr[i]->n == 6) { t = split_child(x, i); x->d[x->n] = t; x->n++; continue; } else { x = x->child_ptr[i]; } } } } x->d[x->n] = a; sort(x->d, x->n); x->n++; } int main() { int i, n, t; insert(10); insert(20); insert(30); insert(40); insert(50); printf("B tree:\n"); traverse(r); return 0; }
输出
B tree: 10 20 30 40 50
#include<iostream> using namespace std; struct BTree {//node declaration int *d; BTree **child_ptr; bool l; int n; }*r = NULL, *np = NULL, *x = NULL; BTree* init() {//creation of node int i; np = new BTree; np->d = new int[6];//order 6 np->child_ptr = new BTree *[7]; np->l = true; np->n = 0; for (i = 0; i < 7; i++) { np->child_ptr[i] = NULL; } return np; } void traverse(BTree *p) { //traverse the tree cout<<endl; int i; for (i = 0; i < p->n; i++) { if (p->l == false) { traverse(p->child_ptr[i]); } cout << " " << p->d[i]; } if (p->l == false) { traverse(p->child_ptr[i]); } cout<<endl; } void sort(int *p, int n){ //sort the tree int i, j, t; for (i = 0; i < n; i++) { for (j = i; j <= n; j++) { if (p[i] >p[j]) { t = p[i]; p[i] = p[j]; p[j] = t; } } } } int split_child(BTree *x, int i) { int j, mid; BTree *np1, *np3, *y; np3 = init();//create new node np3->l = true; if (i == -1) { mid = x->d[2];//find mid x->d[2] = 0; x->n--; np1 = init(); np1->l= false; x->l= true; for (j = 3; j < 6; j++) { np3->d[j - 3] = x->d[j]; np3->child_ptr[j - 3] = x->child_ptr[j]; np3->n++; x->d[j] = 0; x->n--; } for (j = 0; j < 6; j++) { x->child_ptr[j] = NULL; } np1->d[0] = mid; np1->child_ptr[np1->n] = x; np1->child_ptr[np1->n + 1] = np3; np1->n++; r = np1; } else { y = x->child_ptr[i]; mid = y->d[2]; y->d[2] = 0; y->n--; for (j = 3; j <6 ; j++) { np3->d[j - 3] = y->d[j]; np3->n++; y->d[j] = 0; y->n--; } x->child_ptr[i + 1] = y; x->child_ptr[i + 1] = np3; } return mid; } void insert(int a) { int i, t; x = r; if (x == NULL) { r = init(); x = r; } else { if (x->l== true && x->n == 6) { t = split_child(x, -1); x = r; for (i = 0; i < (x->n); i++) { if ((a >x->d[i]) && (a < x->d[i + 1])) { i++; break; } else if (a < x->d[0]) { break; } else { continue; } } x = x->child_ptr[i]; } else { while (x->l == false) { for (i = 0; i < (x->n); i++) { if ((a >x->d[i]) && (a < x->d[i + 1])) { i++; break; } else if (a < x->d[0]) { break; } else { continue; } } if ((x->child_ptr[i])->n == 6) { t = split_child(x, i); x->d[x->n] = t; x->n++; continue; } else { x = x->child_ptr[i]; } } } } x->d[x->n] = a; sort(x->d, x->n); x->n++; } int main() { int i, n, t; insert(10); insert(20); insert(30); insert(40); insert(50); cout<<"B tree:\n"; traverse(r); }
输出
B tree: 10 20 30 40 50
//Java code for B trees import java.util.Arrays; class BTree { private int[] d; private BTree[] child_ptr; private boolean l; private int n; public BTree() { d = new int[6]; // order 6 child_ptr = new BTree[7]; l = true; n = 0; Arrays.fill(child_ptr, null); } public void traverse() { System.out.println("B tree: "); for (int i = 0; i < n; i++) { if (!l) { child_ptr[i].traverse(); } System.out.print(d[i] + " "); } if (!l) { child_ptr[n].traverse(); } System.out.println(); } public void sort() { Arrays.sort(d, 0, n); } public int splitChild(int i) { int j, mid; BTree np1, np3, y; np3 = new BTree(); np3.l = true; if (i == -1) { mid = d[2]; d[2] = 0; n--; np1 = new BTree(); np1.l = false; l = true; for (j = 3; j < 6; j++) { np3.d[j - 3] = d[j]; np3.n++; d[j] = 0; n--; } for (j = 0; j < 6; j++) { np3.child_ptr[j] = child_ptr[j + 3]; child_ptr[j + 3] = null; } np1.d[0] = mid; np1.child_ptr[0] = this; np1.child_ptr[1] = np3; np1.n++; return mid; } else { y = child_ptr[i]; mid = y.d[2]; y.d[2] = 0; y.n--; for (j = 3; j < 6; j++) { np3.d[j - 3] = y.d[j]; np3.n++; y.d[j] = 0; y.n--; } child_ptr[i + 1] = y; child_ptr[i + 2] = np3; return mid; } } public void insert(int a) { int i, t; BTree x = this; if (x.l && x.n == 6) { t = x.splitChild(-1); x = this; for (i = 0; i > x.n; i++) { if (a > x.d[i] && a < x.d[i + 1]) { i++; break; } else if (a < x.d[0]) { break; } } x = x.child_ptr[i]; } else { while (!x.l) { for (i = 0; i < x.n; i++) { if (a > x.d[i] && a < x.d[i + 1]) { i++; break; } else if (a < x.d[0]) { break; } } if (x.child_ptr[i].n == 6) { t = x.splitChild(i); x.d[x.n] = t; x.n++; continue; } x = x.child_ptr[i]; } } x.d[x.n] = a; x.sort(); x.n++; } } public class Main { public static void main(String[] args) { BTree bTree = new BTree(); bTree.insert(20); bTree.insert(10); bTree.insert(40); bTree.insert(30); bTree.insert(50); // Duplicate value, ignored //call the traverse method bTree.traverse(); } }
输出
B tree: 10 20 30 40 50
#python program for B treesa class BTree: def __init__(self): #node declartion self.d = [0] * 6 self.child_ptr = [None] * 7 self.l = True self.n = 0 #creation of node def init(): np = BTree() np.l = True np.n = 0 return np #traverse the tree def traverse(p): if p is not None: for i in range(p.n): if not p.l: traverse(p.child_ptr[i]) print(p.d[i], end=" ") if not p.l: traverse(p.child_ptr[p.n]) #sort the tree def sort(p, n): for i in range(n): for j in range(i, n+1): if p[i] > p[j]: p[i], p[j] = p[j], p[i] def split_child(x, i): np3 = init() #create new node np3.l = True if i == -1: mid = x.d[2] #find mid x.d[2] = 0 x.n -= 1 np1 = init() np1.l = False x.l = True for j in range(3, 6): np3.d[j-3] = x.d[j] np3.child_ptr[j-3] = x.child_ptr[j] np3.n += 1 x.d[j] = 0 x.n -= 1 for j in range(6): x.child_ptr[j] = None np1.d[0] = mid np1.child_ptr[np1.n] = x np1.child_ptr[np1.n + 1] = np3 np1.n += 1 return np1 else: y = x.child_ptr[i] mid = y.d[2] y.d[2] = 0 y.n -= 1 for j in range(3, 6): np3.d[j-3] = y.d[j] np3.n += 1 y.d[j] = 0 y.n -= 1 x.child_ptr[i + 1] = y x.child_ptr[i + 1] = np3 return mid def insert(a): global r, x if r is None: r = init() x = r else: if x.l and x.n == 6: t = split_child(x, -1) x = r for i in range(x.n): if a > x.d[i] and a < x.d[i + 1]: i += 1 break elif a < x.d[0]: break else: continue x = x.child_ptr[i] else: while not x.l: for i in range(x.n): if a > x.d[i] and a < x.d[i + 1]: i += 1 break elif a < x.d[0]: break else: continue if x.child_ptr[i].n == 6: t = split_child(x, i) x.d[x.n] = t x.n += 1 continue else: x = x.child_ptr[i] x.d[x.n] = a sort(x.d, x.n) x.n += 1 if __name__ == '__main__': r = None x = None insert(10) insert(20) insert(30) insert(40) insert(50) print("B tree:") traverse(r)
输出
B tree: 10 20 30 40 50
B+ 树
B+树是B树的扩展,旨在使插入、删除和搜索操作更有效率。
B+树的性质与B树的性质相似,不同之处在于B树可以在所有内部节点和叶子节点中存储键和记录,而B+树在叶子节点中存储记录,在内部节点中存储键。B+树的一个显著性质是所有叶子节点都以单个链接列表格式相互连接,并且有一个数据指针可用于指向磁盘文件中存在的数据。这有助于以相同数量的磁盘访问次数获取记录。
由于主存储器的容量有限,B+树充当无法存储在主存储器中的记录的数据存储。为此,内部节点存储在主存储器中,叶子节点存储在辅助存储器中。
B+树的性质
B+树中除根节点外的每个节点最多包含m个子节点和(m-1)个键,最少包含$\mathrm{\left \lceil \frac{m}{2}\right \rceil}$个子节点和$\mathrm{\left \lceil \frac{m-1}{2}\right \rceil}$个键,因为树的阶数为m。
根节点必须至少有两个子节点和至少一个搜索键。
B树中的所有路径必须在同一级别结束,即叶子节点必须在同一级别。
B+树始终保持数据排序。
B+树的基本操作
B+树支持的操作包括插入、删除和查找,每种操作的时间复杂度均为O(log n)。
它们与B树的操作非常相似,因为这两种数据结构存储数据的基本思想相同。但是,不同之处在于,B+树的数据仅存储在叶子节点中,而B树则不是。
插入
向B+树插入数据从叶子节点开始。
步骤1 - 计算要添加到B+树节点中的键的最大值和最小值。
步骤2 - 将元素逐个插入到叶子节点中,直到超过最大键数。
步骤3 - 将节点分成两半,左子节点包含最小数量的键,其余键存储在右子节点中。
步骤4 - 但是,如果内部节点也超过了最大键数,则将节点分成两半,左子节点包含最小数量的键,其余键存储在右子节点中。但是,右子节点中最小的数字将成为父节点。
步骤5 - 如果叶子节点和内部节点都具有最大数量的键,则两者都以类似的方式进行分割,并将右子节点中最小的键添加到父节点中。
删除
在B+树中进行删除操作时,我们需要考虑数据结构中的冗余性。
情况1 - 如果键存在于叶子节点中,并且该节点的键数超过最小数量,并且其副本不存在于内部节点中,则直接将其删除。
情况2 - 如果键存在于叶子节点中,并且该节点的键数正好为最小数量,并且其副本不存在于内部节点中,则从其兄弟节点借用一个键,然后删除所需的键。
情况3 - 如果叶子节点中的键在内部节点中存在副本,则可能有多种情况 -
叶子节点和内部节点中都存在超过最小数量的键:只需删除键并将中序后继添加到内部节点中即可。
叶子节点中存在正好为最小数量的键:删除节点并从其直接兄弟节点借用一个节点,并将其值替换为内部节点的值。
如果要删除的叶子节点的副本在其祖父母节点中,则删除该节点并移除空位。祖父母节点将填充已删除节点的中序后继。
情况4 - 如果要删除的键所在的节点违反了最小键数属性,并且其父节点和兄弟节点的键数都为最小数量,则删除该键并将其兄弟节点与其父节点合并。
示例
// C program for Bplus tree #include <stdio.h> #include <stdlib.h> struct BplusTree { int *d; struct BplusTree **child_ptr; int l; int n; }; struct BplusTree *r = NULL, *np = NULL, *x = NULL; struct BplusTree* init() { //to create nodes int i; np = (struct BplusTree*)malloc(sizeof(struct BplusTree)); np->d = (int*)malloc(6 * sizeof(int)); // order 6 np->child_ptr = (struct BplusTree**)malloc(7 * sizeof(struct BplusTree*)); np->l = 1; np->n = 0; for (i = 0; i < 7; i++) { np->child_ptr[i] = NULL; } return np; } void traverse(struct BplusTree *p) { //traverse tree printf("\n"); int i; for (i = 0; i < p->n; i++) { if (p->l == 0) { traverse(p->child_ptr[i]); } printf(" %d", p->d[i]); } if (p->l == 0) { traverse(p->child_ptr[i]); } printf("\n"); } void sort(int *p, int n) { int i, j, t; for (i = 0; i < n; i++) { for (j = i; j <= n; j++) { if (p[i] > p[j]) { t = p[i]; p[i] = p[j]; p[j] = t; } } } } int split_child(struct BplusTree *x, int i) { int j, mid; struct BplusTree *np1, *np3, *y; np3 = init(); np3->l = 1; if (i == -1) { mid = x->d[2]; x->d[2] = 0; x->n--; np1 = init(); np1->l = 0; x->l = 1; for (j = 3; j < 6; j++) { np3->d[j - 3] = x->d[j]; np3->child_ptr[j - 3] = x->child_ptr[j]; np3->n++; x->d[j] = 0; x->n--; } for (j = 0; j < 6; j++) { x->child_ptr[j] = NULL; } np1->d[0] = mid; np1->child_ptr[np1->n] = x; np1->child_ptr[np1->n + 1] = np3; np1->n++; r = np1; } else { y = x->child_ptr[i]; mid = y->d[2]; y->d[2] = 0; y->n--; for (j = 3; j < 6; j++) { np3->d[j - 3] = y->d[j]; np3->n++; y->d[j] = 0; y->n--; } x->child_ptr[i + 1] = y; x->child_ptr[i + 1] = np3; } return mid; } void insert(int a) { int i, t; x = r; if (x == NULL) { r = init(); x = r; } else { if (x->l == 1 && x->n == 6) { t = split_child(x, -1); x = r; for (i = 0; i < x->n; i++) { if (a > x->d[i] && a < x->d[i + 1]) { i++; break; } else if (a < x->d[0]) { break; } else { continue; } } x = x->child_ptr[i]; } else { while (x->l == 0) { for (i = 0; i < x->n; i++) { if (a > x->d[i] && a < x->d[i + 1]) { i++; break; } else if (a < x->d[0]) { break; } else { continue; } } if (x->child_ptr[i]->n == 6) { t = split_child(x, i); x->d[x->n] = t; x->n++; continue; } else { x = x->child_ptr[i]; } } } } x->d[x->n] = a; sort(x->d, x->n); x->n++; } int main() { int i, n, t; insert(10); insert(20); insert(30); insert(40); insert(50); printf("B+ tree:\n"); traverse(r); return 0; }
输出
B+ tree: 10 20 30 40 50
#include<iostream> using namespace std; struct BplusTree { int *d; BplusTree **child_ptr; bool l; int n; } *r = NULL, *np = NULL, *x = NULL; BplusTree* init() { //to create nodes int i; np = new BplusTree; np->d = new int[6];//order 6 np->child_ptr = new BplusTree *[7]; np->l = true; np->n = 0; for (i = 0; i < 7; i++) { np->child_ptr[i] = NULL; } return np; } void traverse(BplusTree *p) { //traverse tree cout<<endl; int i; for (i = 0; i < p->n; i++) { if (p->l == false) { traverse(p->child_ptr[i]); } cout << " " << p->d[i]; } if (p->l == false) { traverse(p->child_ptr[i]); } cout<<endl; } void sort(int *p, int n) { //sort the tree int i, j, t; for (i = 0; i < n; i++) { for (j = i; j <= n; j++) { if (p[i] >p[j]) { t = p[i]; p[i] = p[j]; p[j] = t; } } } } int split_child(BplusTree *x, int i) { int j, mid; BplusTree *np1, *np3, *y; np3 = init(); np3->l = true; if (i == -1) { mid = x->d[2]; x->d[2] = 0; x->n--; np1 = init(); np1->l = false; x->l = true; for (j = 3; j < 6; j++) { np3->d[j - 3] = x->d[j]; np3->child_ptr[j - 3] = x->child_ptr[j]; np3->n++; x->d[j] = 0; x->n--; } for (j = 0; j < 6; j++) { x->child_ptr[j] = NULL; } np1->d[0] = mid; np1->child_ptr[np1->n] = x; np1->child_ptr[np1->n + 1] = np3; np1->n++; r = np1; } else { y = x->child_ptr[i]; mid = y->d[2]; y->d[2] = 0; y->n--; for (j = 3; j <6 ; j++) { np3->d[j - 3] = y->d[j]; np3->n++; y->d[j] = 0; y->n--; } x->child_ptr[i + 1] = y; x->child_ptr[i + 1] = np3; } return mid; } void insert(int a) { int i, t; x = r; if (x == NULL) { r = init(); x = r; } else { if (x->l== true && x->n == 6) { t = split_child(x, -1); x = r; for (i = 0; i < (x->n); i++) { if ((a >x->d[i]) && (a < x->d[i + 1])) { i++; break; } else if (a < x->d[0]) { break; } else { continue; } } x = x->child_ptr[i]; } else { while (x->l == false) { for (i = 0; i < (x->n); i++) { if ((a >x->d[i]) && (a < x->d[i + 1])) { i++; break; } else if (a < x->d[0]) { break; } else { continue; } } if ((x->child_ptr[i])->n == 6) { t = split_child(x, i); x->d[x->n] = t; x->n++; continue; } else { x = x->child_ptr[i]; } } } } x->d[x->n] = a; sort(x->d, x->n); x->n++; } int main() { int i, n, t; insert(10); insert(20); insert(30); insert(40); insert(50); cout<<"B+ tree:\n"; traverse(r); }
输出
B+ tree: 10 20 30 40 50
//Java program for Bplus code import java.util.*; class BplusTree { int[] d; BplusTree[] child_ptr; boolean l; int n; } public class Main { static BplusTree r = null, np = null, x = null; static BplusTree init() { // to create nodes int i; np = new BplusTree(); np.d = new int[6]; // order 6 np.child_ptr = new BplusTree[7]; np.l = true; np.n = 0; for (i = 0; i < 7; i++) { np.child_ptr[i] = null; } return np; } static void traverse(BplusTree p) { // traverse tree System.out.println(); int i; for (i = 0; i < p.n; i++) { if (p.l == false) { traverse(p.child_ptr[i]); } System.out.print(" " + p.d[i]); } if (p.l == false) { traverse(p.child_ptr[i]); } System.out.println(); } static void sort(int[] p, int n) { // sort the tree int i, j, t; for (i = 0; i < n; i++) { for (j = i; j <= n; j++) { if (p[i] > p[j]) { t = p[i]; p[i] = p[j]; p[j] = t; } } } } static int split_child(BplusTree x, int i) { int j, mid; BplusTree np1, np3, y; np3 = init(); np3.l = true; if (i == -1) { mid = x.d[2]; x.d[2] = 0; x.n--; np1 = init(); np1.l = false; x.l = true; for (j = 3; j < 6; j++) { np3.d[j - 3] = x.d[j]; np3.child_ptr[j - 3] = x.child_ptr[j]; np3.n++; x.d[j] = 0; x.n--; } for (j = 0; j < 6; j++) { x.child_ptr[j] = null; } np1.d[0] = mid; np1.child_ptr[np1.n] = x; np1.child_ptr[np1.n + 1] = np3; np1.n++; r = np1; } else { y = x.child_ptr[i]; mid = y.d[2]; y.d[2] = 0; y.n--; for (j = 3; j < 6; j++) { np3.d[j - 3] = y.d[j]; np3.n++; y.d[j] = 0; y.n--; } x.child_ptr[i + 1] = y; x.child_ptr[i + 1] = np3; } return mid; } static void insert(int a) { int i, t; x = r; if (x == null) { r = init(); x = r; } else { if (x.l == true && x.n == 6) { t = split_child(x, -1); x = r; for (i = 0; i < x.n; i++) { if (a > x.d[i] && a < x.d[i + 1]) { i++; break; } else if (a < x.d[0]) { break; } else { continue; } } x = x.child_ptr[i]; } else { while (x.l == false) { for (i = 0; i < x.n; i++) { if (a > x.d[i] && a < x.d[i + 1]) { i++; break; } else if (a < x.d[0]) { break; } else { continue; } } if (x.child_ptr[i].n == 6) { t = split_child(x, i); x.d[x.n] = t; x.n++; continue; } else { x = x.child_ptr[i]; } } } } x.d[x.n] = a; sort(x.d, x.n); x.n++; } public static void main(String[] args) { int i, n, t; insert(10); insert(20); insert(30); insert(40); insert(50); System.out.println("B+ tree:"); traverse(r); } }
输出
B+ tree: 10 20 30 40 50
#Python Program for Bplus tree #to create nodes class BplusTree: def __init__(self): self.d = [0] * 6 # order 6 self.child_ptr = [None] * 7 self.l = True self.n = 0 def init(): np = BplusTree() np.l = True np.n = 0 return np #traverse tree def traverse(p): print() for i in range(p.n): if not p.l: traverse(p.child_ptr[i]) print(" ", p.d[i], end="") if not p.l: traverse(p.child_ptr[p.n]) print() #sort the tree def sort(p, n): for i in range(n): for j in range(i, n + 1): if p[i] > p[j]: p[i], p[j] = p[j], p[i] def split_child(x, i): np3 = init() np3.l = True if i == -1: mid = x.d[2] x.d[2] = 0 x.n -= 1 np1 = init() np1.l = False x.l = True for j in range(3, 6): np3.d[j - 3] = x.d[j] np3.child_ptr[j - 3] = x.child_ptr[j] np3.n += 1 x.d[j] = 0 x.n -= 1 for j in range(6): x.child_ptr[j] = None np1.d[0] = mid np1.child_ptr[np1.n] = x np1.child_ptr[np1.n + 1] = np3 np1.n += 1 r = np1 else: y = x.child_ptr[i] mid = y.d[2] y.d[2] = 0 y.n -= 1 for j in range(3, 6): np3.d[j - 3] = y.d[j] np3.n += 1 y.d[j] = 0 y.n -= 1 x.child_ptr[i + 1] = y x.child_ptr[i + 1] = np3 return mid def insert(a): global r, x x = r if x is None: r = init() x = r else: if x.l and x.n == 6: t = split_child(x, -1) x = r for i in range(x.n): if a > x.d[i] and a < x.d[i + 1]: i += 1 break elif a < x.d[0]: break else: continue x = x.child_ptr[i] else: while not x.l: for i in range(x.n): if a > x.d[i] and a < x.d[i + 1]: i += 1 break elif a < x.d[0]: break else: continue if x.child_ptr[i].n == 6: t = split_child(x, i) x.d[x.n] = t x.n += 1 continue else: x = x.child_ptr[i] x.d[x.n] = a sort(x.d, x.n) x.n += 1 r = None x = None insert(10) insert(20) insert(30) insert(40) insert(50) print("B+ tree:") traverse(r)
输出
B+ tree: 10 20 30 40 50
伸展树
伸展树是二叉搜索树的修改版本,因为它包含BST的所有操作,如插入、删除和查找,以及另一个扩展操作,称为伸展。
例如,假设要将值“A”插入到树中。如果树为空,则将“A”添加到树的根节点并退出;但如果树不为空,则使用二叉搜索插入操作插入元素,然后对新节点执行伸展操作。
类似地,在伸展树中搜索元素后,包含该元素的节点也必须进行伸展。
但是我们如何执行伸展操作呢?简单来说,伸展操作就是将一个操作节点移到根节点的过程。它有六种类型的旋转。
Zig旋转
Zag旋转
Zig-Zig旋转
Zag-Zag旋转
Zig-Zag旋转
Zag-Zig旋转
Zig旋转
当操作节点是根节点或根节点的左子节点时,执行Zig旋转。节点向右旋转。
旋转后,树将如下所示 -
Zag旋转
当操作节点是根节点或根节点的右子节点时,也执行Zag旋转。节点向左旋转。
旋转后,操作节点将成为根节点 -
Zig-Zig旋转
当操作节点同时具有父节点和祖父母节点时,执行Zig-Zig旋转。节点向右旋转两次。
第一次旋转将使树向右移动一个位置 -
第二次右旋转将再次使节点移动一个位置。旋转后的最终树将如下所示 -
Zag-Zag旋转
当操作节点同时具有父节点和祖父母节点时,也执行Zag-Zag旋转。节点向左旋转两次。
第一次旋转后,树将如下所示 -
然后是第二次旋转后的最终树。但是,操作节点仍然不是根节点,因此伸展操作被认为是不完整的。因此,在这种情况下,将再次应用其他合适的旋转,直到节点成为根节点。
Zig-Zag旋转
当操作节点同时具有父节点和祖父母节点时,执行Zig-Zag旋转。但不同之处在于祖父母节点、父节点和子节点的格式为LRL。节点先向右旋转,然后向左旋转。
第一次旋转后,树为 -
第二次旋转后的最终树 -
Zag-Zig旋转
当操作节点同时具有父节点和祖父母节点时,也执行Zag-Zig旋转。但不同之处在于祖父母节点、父节点和子节点的格式为RLR。节点先向左旋转,然后向右旋转。
执行第一次旋转,得到如下树 -
第二次旋转后,最终树如下所示。但是,操作节点尚未成为根节点,因此需要执行一次以上的旋转才能使该节点成为根节点。
伸展树的基本操作
伸展树包含与二叉搜索树提供的相同的基本操作:插入、删除和查找。但是,在每次操作之后,还有一个额外的操作使它们与二叉搜索树操作有所不同:伸展。我们已经了解了伸展操作,所以让我们了解其他操作的过程。
插入
伸展树中的插入操作与二叉搜索树中的插入操作完全相同。在伸展树中执行插入操作的过程如下 -
检查树是否为空;如果是,则添加新节点并退出
如果树不为空,则使用二叉搜索插入将新节点添加到现有树中。
然后,选择合适的伸展操作并将其应用于新添加的节点。
对新节点应用Zag(左)旋转
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <stdlib.h> struct node { int data; struct node *leftChild, *rightChild; }; struct node* newNode(int data){ struct node* Node = (struct node*)malloc(sizeof(struct node)); Node->data = data; Node->leftChild = Node->rightChild = NULL; return (Node); } struct node* rightRotate(struct node *x){ struct node *y = x->leftChild; x->leftChild = y->rightChild; y->rightChild = x; return y; } struct node* leftRotate(struct node *x){ struct node *y = x->rightChild; x->rightChild = y->leftChild; y->leftChild = x; return y; } struct node* splay(struct node *root, int data){ if (root == NULL || root->data == data) return root; if (root->data > data) { if (root->leftChild == NULL) return root; if (root->leftChild->data > data) { root->leftChild->leftChild = splay(root->leftChild->leftChild, data); root = rightRotate(root); } else if (root->leftChild->data < data) { root->leftChild->rightChild = splay(root->leftChild->rightChild, data); if (root->leftChild->rightChild != NULL) root->leftChild = leftRotate(root->leftChild); } return (root->leftChild == NULL)? root: rightRotate(root); } else { if (root->rightChild == NULL) return root; if (root->rightChild->data > data) { root->rightChild->leftChild = splay(root->rightChild->leftChild, data); if (root->rightChild->leftChild != NULL) root->rightChild = rightRotate(root->rightChild); } else if (root->rightChild->data < data) { root->rightChild->rightChild = splay(root->rightChild->rightChild, data); root = leftRotate(root); } return (root->rightChild == NULL)? root: leftRotate(root); } } struct node* insert(struct node *root, int k){ if (root == NULL) return newNode(k); root = splay(root, k); if (root->data == k) return root; struct node *newnode = newNode(k); if (root->data > k) { newnode->rightChild = root; newnode->leftChild = root->leftChild; root->leftChild = NULL; } else { newnode->leftChild = root; newnode->rightChild = root->rightChild; root->rightChild = NULL; } return newnode; } void printTree(struct node *root){ if (root == NULL) return; if (root != NULL) { printTree(root->leftChild); printf("%d ", root->data); printTree(root->rightChild); } } int main(){ struct node* root = newNode(34); root->leftChild = newNode(15); root->rightChild = newNode(40); root->leftChild->leftChild = newNode(12); root->leftChild->leftChild->rightChild = newNode(14); root->rightChild->rightChild = newNode(59); printf("The Splay tree is: \n"); printTree(root); return 0; }
输出
The Splay tree is: 12 14 15 34 40 59
#include <iostream> struct node { int data; struct node *leftChild, *rightChild; }; struct node* newNode(int data){ struct node* Node = (struct node*)malloc(sizeof(struct node)); Node->data = data; Node->leftChild = Node->rightChild = NULL; return (Node); } struct node* rightRotate(struct node *x){ struct node *y = x->leftChild; x->leftChild = y->rightChild; y->rightChild = x; return y; } struct node* leftRotate(struct node *x){ struct node *y = x->rightChild; x->rightChild = y->leftChild; y->leftChild = x; return y; } struct node* splay(struct node *root, int data){ if (root == NULL || root->data == data) return root; if (root->data > data) { if (root->leftChild == NULL) return root; if (root->leftChild->data > data) { root->leftChild->leftChild = splay(root->leftChild->leftChild, data); root = rightRotate(root); } else if (root->leftChild->data < data) { root->leftChild->rightChild = splay(root->leftChild->rightChild, data); if (root->leftChild->rightChild != NULL) root->leftChild = leftRotate(root->leftChild); } return (root->leftChild == NULL)? root: rightRotate(root); } else { if (root->rightChild == NULL) return root; if (root->rightChild->data > data) { root->rightChild->leftChild = splay(root->rightChild->leftChild, data); if (root->rightChild->leftChild != NULL) root->rightChild = rightRotate(root->rightChild); } else if (root->rightChild->data < data) { root->rightChild->rightChild = splay(root->rightChild->rightChild, data); root = leftRotate(root); } return (root->rightChild == NULL)? root: leftRotate(root); } } struct node* insert(struct node *root, int k){ if (root == NULL) return newNode(k); root = splay(root, k); if (root->data == k) return root; struct node *newnode = newNode(k); if (root->data > k) { newnode->rightChild = root; newnode->leftChild = root->leftChild; root->leftChild = NULL; } else { newnode->leftChild = root; newnode->rightChild = root->rightChild; root->rightChild = NULL; } return newnode; } void printTree(struct node *root){ if (root == NULL) return; if (root != NULL) { printTree(root->leftChild); printf("%d ", root->data); printTree(root->rightChild); } } int main(){ struct node* root = newNode(34); root->leftChild = newNode(15); root->rightChild = newNode(40); root->leftChild->leftChild = newNode(12); root->leftChild->leftChild->rightChild = newNode(14); root->rightChild->rightChild = newNode(59); printf("The Splay tree is: \n"); printTree(root); return 0; }
输出
The Splay tree is: 12 14 15 34 40 59
import java.io.*; public class SplayTree { static class node { int data; node leftChild, rightChild; }; static node newNode(int data) { node Node = new node(); Node.data = data; Node.leftChild = Node.rightChild = null; return (Node); } static node rightRotate(node x) { node y = x.leftChild; x.leftChild = y.rightChild; y.rightChild = x; return y; } static node leftRotate(node x) { node y = x.rightChild; x.rightChild = y.leftChild; y.leftChild = x; return y; } static node splay(node root, int data) { if (root == null || root.data == data) return root; if (root.data > data) { if (root.leftChild == null) return root; if (root.leftChild.data > data) { root.leftChild.leftChild = splay(root.leftChild.leftChild, data); root = rightRotate(root); } else if (root.leftChild.data < data) { root.leftChild.rightChild = splay(root.leftChild.rightChild, data); if (root.leftChild.rightChild != null) root.leftChild = leftRotate(root.leftChild); } return (root.leftChild == null)? root: rightRotate(root); } else { if (root.rightChild == null) return root; if (root.rightChild.data > data) { root.rightChild.leftChild = splay(root.rightChild.leftChild, data); if (root.rightChild.leftChild != null) root.rightChild = rightRotate(root.rightChild); } else if (root.rightChild.data < data) { root.rightChild.rightChild = splay(root.rightChild.rightChild, data); root = leftRotate(root); } return (root.rightChild == null)? root: leftRotate(root); } } static node insert(node root, int k) { if (root == null) return newNode(k); root = splay(root, k); if (root.data == k) return root; node newnode = newNode(k); if (root.data > k) { newnode.rightChild = root; newnode.leftChild = root.leftChild; root.leftChild = null; } else { newnode.leftChild = root; newnode.rightChild = root.rightChild; root.rightChild = null; } return newnode; } static void printTree(node root) { if (root == null) return; if (root != null) { printTree(root.leftChild); System.out.print(root.data + " "); printTree(root.rightChild); } } public static void main(String args[]) { node root = newNode(34); root.leftChild = newNode(15); root.rightChild = newNode(40); root.leftChild.leftChild = newNode(12); root.leftChild.leftChild.rightChild = newNode(14); root.rightChild.rightChild = newNode(59); System.out.println("The Splay tree is: "); printTree(root); } }
输出
The Splay tree is: 12 14 15 34 40 59
#Python Code for Insertion Operation of Splay Trees class Node: def __init__(self, data): self.data = data self.leftChild = None self.rightChild = None def newNode(data): return Node(data) def rightRotate(x): y = x.leftChild x.leftChild = y.rightChild y.rightChild = x return y def leftRotate(x): y = x.rightChild x.rightChild = y.leftChild y.leftChild = x return y def splay(root, data): if root is None or root.data == data: return root if root.data > data: if root.leftChild is None: return root if root.leftChild.data > data: root.leftChild.leftChild = splay(root.leftChild.leftChild, data) root = rightRotate(root) elif root.leftChild.data < data: root.leftChild.rightChild = splay(root.leftChild.rightChild, data) if root.leftChild.rightChild is not None: root.leftChild = leftRotate(root.leftChild) return root if root.leftChild is None else rightRotate(root) else: if root.rightChild is None: return root if root.rightChild.data > data: root.rightChild.leftChild = splay(root.rightChild.leftChild, data) if root.rightChild.leftChild is not None: root.rightChild = rightRotate(root.rightChild) elif root.rightChild.data < data: root.rightChild.rightChild = splay(root.rightChild.rightChild, data) root = leftRotate(root) return root if root.rightChild is None else leftRotate(root) def insert(root, k): if root is None: return newNode(k) root = splay(root, k) if root.data == k: return root newnode = newNode(k) if root.data > k: newnode.rightChild = root newnode.leftChild = root.leftChild root.leftChild = None else: newnode.leftChild = root newnode.rightChild = root.rightChild root.rightChild = None return newnode def printTree(root): if root is None: return if root is not None: printTree(root.leftChild) print(root.data, end=" ") printTree(root.rightChild) if __name__ == "__main__": root = newNode(34) root.leftChild = newNode(15) root.rightChild = newNode(40) root.leftChild.leftChild = newNode(12) root.leftChild.leftChild.rightChild = newNode(14) root.rightChild.rightChild = newNode(59) print("The Splay tree is: ") printTree(root)
输出
The Splay tree is: 12 14 15 34 40 59
删除
伸展树中的删除操作执行如下 -
对要删除的节点应用伸展操作。
一旦节点成为根节点,就删除该节点。
现在,树被分成两棵树,左子树和右子树;它们各自的第一个节点作为根节点:例如root_left和root_right。
如果root_left为NULL值,则root_right将成为树的根节点。反之亦然。
但是,如果root_left和root_right都不为NULL值,则选择左子树中的最大值并将其设为新的根节点,并将子树连接起来。
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <stdlib.h> struct node { int data; struct node *leftChild, *rightChild; }; struct node* newNode(int data){ struct node* Node = (struct node*)malloc(sizeof(struct node)); Node->data = data; Node->leftChild = Node->rightChild = NULL; return (Node); } struct node* rightRotate(struct node *x){ struct node *y = x->leftChild; x->leftChild = y->rightChild; y->rightChild = x; return y; } struct node* leftRotate(struct node *x){ struct node *y = x->rightChild; x->rightChild = y->leftChild; y->leftChild = x; return y; } struct node* splay(struct node *root, int data){ if (root == NULL || root->data == data) return root; if (root->data > data) { if (root->leftChild == NULL) return root; if (root->leftChild->data > data) { root->leftChild->leftChild = splay(root->leftChild->leftChild, data); root = rightRotate(root); } else if (root->leftChild->data < data) { root->leftChild->rightChild = splay(root->leftChild->rightChild, data); if (root->leftChild->rightChild != NULL) root->leftChild = leftRotate(root->leftChild); } return (root->leftChild == NULL)? root: rightRotate(root); } else { if (root->rightChild == NULL) return root; if (root->rightChild->data > data) { root->rightChild->leftChild = splay(root->rightChild->leftChild, data); if (root->rightChild->leftChild != NULL) root->rightChild = rightRotate(root->rightChild); } else if (root->rightChild->data < data) { root->rightChild->rightChild = splay(root->rightChild->rightChild, data); root = leftRotate(root); } return (root->rightChild == NULL)? root: leftRotate(root); } } struct node* insert(struct node *root, int k){ if (root == NULL) return newNode(k); root = splay(root, k); if (root->data == k) return root; struct node *newnode = newNode(k); if (root->data > k) { newnode->rightChild = root; newnode->leftChild = root->leftChild; root->leftChild = NULL; } else { newnode->leftChild = root; newnode->rightChild = root->rightChild; root->rightChild = NULL; } return newnode; } struct node* deletenode(struct node* root, int data){ struct node* temp; if (root == NULL) return NULL; root = splay(root, data); if (data != root->data) return root; if (!root->leftChild) { temp = root; root = root->rightChild; } else { temp = root; root = splay(root->leftChild, data); root->rightChild = temp->rightChild; } free(temp); return root; } void printTree(struct node *root){ if (root == NULL) return; if (root != NULL) { printTree(root->leftChild); printf("%d ", root->data); printTree(root->rightChild); } } int main(){ struct node* root = newNode(34); root->leftChild = newNode(15); root->rightChild = newNode(40); printf("The Splay tree is \n"); printTree(root); root = deletenode(root, 40); printf("\nThe Splay tree after deletion is \n"); printTree(root); return 0; }
输出
The Splay tree is 15 34 40 The Splay tree after deletion is 15 34
#include <iostream> struct node { int data; struct node *leftChild, *rightChild; }; struct node* newNode(int data){ struct node* Node = (struct node*)malloc(sizeof(struct node)); Node->data = data; Node->leftChild = Node->rightChild = NULL; return (Node); } struct node* rightRotate(struct node *x){ struct node *y = x->leftChild; x->leftChild = y->rightChild; y->rightChild = x; return y; } struct node* leftRotate(struct node *x){ struct node *y = x->rightChild; x->rightChild = y->leftChild; y->leftChild = x; return y; } struct node* splay(struct node *root, int data){ if (root == NULL || root->data == data) return root; if (root->data > data) { if (root->leftChild == NULL) return root; if (root->leftChild->data > data) { root->leftChild->leftChild = splay(root->leftChild->leftChild, data); root = rightRotate(root); } else if (root->leftChild->data < data) { root->leftChild->rightChild = splay(root->leftChild->rightChild, data); if (root->leftChild->rightChild != NULL) root->leftChild = leftRotate(root->leftChild); } return (root->leftChild == NULL)? root: rightRotate(root); } else { if (root->rightChild == NULL) return root; if (root->rightChild->data > data) { root->rightChild->leftChild = splay(root->rightChild->leftChild, data); if (root->rightChild->leftChild != NULL) root->rightChild = rightRotate(root->rightChild); } else if (root->rightChild->data < data) { root->rightChild->rightChild = splay(root->rightChild->rightChild, data); root = leftRotate(root); } return (root->rightChild == NULL)? root: leftRotate(root); } } struct node* insert(struct node *root, int k){ if (root == NULL) return newNode(k); root = splay(root, k); if (root->data == k) return root; struct node *newnode = newNode(k); if (root->data > k) { newnode->rightChild = root; newnode->leftChild = root->leftChild; root->leftChild = NULL; } else { newnode->leftChild = root; newnode->rightChild = root->rightChild; root->rightChild = NULL; } return newnode; } struct node* deletenode(struct node* root, int data){ struct node* temp; if (root == NULL) return NULL; root = splay(root, data); if (data != root->data) return root; if (!root->leftChild) { temp = root; root = root->rightChild; } else { temp = root; root = splay(root->leftChild, data); root->rightChild = temp->rightChild; } free(temp); return root; } void printTree(struct node *root){ if (root == NULL) return; if (root != NULL) { printTree(root->leftChild); printf("%d ", root->data); printTree(root->rightChild); } } int main(){ struct node* root = newNode(34); root->leftChild = newNode(15); root->rightChild = newNode(40); printf("The Splay tree is \n"); printTree(root); root = deletenode(root, 40); printf("\nThe Splay tree after deletion is \n"); printTree(root); return 0; }
输出
The Splay tree is 15 34 40 The Splay tree after deletion is 15 34
import java.io.*; public class SplayTree { static class node { int data; node leftChild, rightChild; }; static node newNode(int data) { node Node = new node(); Node.data = data; Node.leftChild = Node.rightChild = null; return (Node); } static node rightRotate(node x) { node y = x.leftChild; x.leftChild = y.rightChild; y.rightChild = x; return y; } static node leftRotate(node x) { node y = x.rightChild; x.rightChild = y.leftChild; y.leftChild = x; return y; } static node splay(node root, int data) { if (root == null || root.data == data) return root; if (root.data > data) { if (root.leftChild == null) return root; if (root.leftChild.data > data) { root.leftChild.leftChild = splay(root.leftChild.leftChild, data); root = rightRotate(root); } else if (root.leftChild.data < data) { root.leftChild.rightChild = splay(root.leftChild.rightChild, data); if (root.leftChild.rightChild != null) root.leftChild = leftRotate(root.leftChild); } return (root.leftChild == null)? root: rightRotate(root); } else { if (root.rightChild == null) return root; if (root.rightChild.data > data) { root.rightChild.leftChild = splay(root.rightChild.leftChild, data); if (root.rightChild.leftChild != null) root.rightChild = rightRotate(root.rightChild); } else if (root.rightChild.data < data) { root.rightChild.rightChild = splay(root.rightChild.rightChild, data); root = leftRotate(root); } return (root.rightChild == null)? root: leftRotate(root); } } static node insert(node root, int k) { if (root == null) return newNode(k); root = splay(root, k); if (root.data == k) return root; node newnode = newNode(k); if (root.data > k) { newnode.rightChild = root; newnode.leftChild = root.leftChild; root.leftChild = null; } else { newnode.leftChild = root; newnode.rightChild = root.rightChild; root.rightChild = null; } return newnode; } static node deletenode(node root, int data) { node temp; if (root == null) return null; root = splay(root, data); if (data != root.data) return root; if (root.leftChild == null) { temp = root; root = root.rightChild; } else { temp = root; root = splay(root.leftChild, data); root.rightChild = temp.rightChild; } return root; } static void printTree(node root) { if (root == null) return; if (root != null) { printTree(root.leftChild); System.out.print(root.data + " "); printTree(root.rightChild); } } public static void main(String args[]) { node root = newNode(34); root.leftChild = newNode(15); root.rightChild = newNode(40); System.out.println("The Splay tree is: "); printTree(root); root = deletenode(root, 40); System.out.println("\nThe Splay tree after deletion is: "); printTree(root); } }
输出
The Splay tree is: 15 34 40 The Splay tree after deletion is: 15 34
#Python Code for Deletion operation of Splay Trees class Node: def __init__(self, data): self.data = data self.leftChild = None self.rightChild = None def newNode(data): node = Node(data) return node def rightRotate(x): y = x.leftChild x.leftChild = y.rightChild y.rightChild = x return y def leftRotate(x): y = x.rightChild x.rightChild = y.leftChild y.leftChild = x return y def splay(root, data): if root is None or root.data == data: return root if root.data > data: if root.leftChild is None: return root if root.leftChild.data > data: root.leftChild.leftChild = splay(root.leftChild.leftChild, data) root = rightRotate(root) elif root.leftChild.data < data: root.leftChild.rightChild = splay(root.leftChild.rightChild, data) if root.leftChild.rightChild is not None: root.leftChild = leftRotate(root.leftChild) return root if root.leftChild is None else rightRotate(root) else: if root.rightChild is None: return root if root.rightChild.data > data: root.rightChild.leftChild = splay(root.rightChild.leftChild, data) if root.rightChild.leftChild is not None: root.rightChild = rightRotate(root.rightChild) elif root.rightChild.data < data: root.rightChild.rightChild = splay(root.rightChild.rightChild, data) root = leftRotate(root) return root if root.rightChild is None else leftRotate(root) def insert(root, k): if root is None: return newNode(k) root = splay(root, k) if root.data == k: return root newnode = newNode(k) if root.data > k: newnode.rightChild = root newnode.leftChild = root.leftChild root.leftChild = None else: newnode.leftChild = root newnode.rightChild = root.rightChild root.rightChild = None return newnode def deletenode(root, data): temp = None if root is None: return None root = splay(root, data) if data != root.data: return root if root.leftChild is None: temp = root root = root.rightChild else: temp = root root = splay(root.leftChild, data) root.rightChild = temp.rightChild del temp return root def printTree(root): if root is None: return if root is not None: printTree(root.leftChild) print(root.data, end=" ") printTree(root.rightChild) root = newNode(34) root.leftChild = newNode(15) root.rightChild = newNode(40) print("The Splay tree is:") printTree(root) root = deletenode(root, 40) print("\nThe Splay tree after deletion is:") printTree(root)
输出
The Splay tree is: 15 34 40 The Splay tree after deletion is: 15 34
搜索
伸展树中的查找操作遵循二叉搜索树操作的相同过程。但是,在完成查找并找到元素后,将在搜索到的节点上应用伸展操作。如果未找到元素,则会提示查找失败。
示例
以下是此操作在各种编程语言中的实现 -
#include <stdio.h> #include <stdlib.h> struct node { int data; struct node *leftChild, *rightChild; }; struct node* newNode(int data){ struct node* Node = (struct node*)malloc(sizeof(struct node)); Node->data = data; Node->leftChild = Node->rightChild = NULL; return (Node); } struct node* rightRotate(struct node *x){ struct node *y = x->leftChild; x->leftChild = y->rightChild; y->rightChild = x; return y; } struct node* leftRotate(struct node *x){ struct node *y = x->rightChild; x->rightChild = y->leftChild; y->leftChild = x; return y; } struct node* splay(struct node *root, int data){ if (root == NULL || root->data == data) return root; if (root->data > data) { if (root->leftChild == NULL) return root; if (root->leftChild->data > data) { root->leftChild->leftChild = splay(root->leftChild->leftChild, data); root = rightRotate(root); } else if (root->leftChild->data < data) { root->leftChild->rightChild = splay(root->leftChild->rightChild, data); if (root->leftChild->rightChild != NULL) root->leftChild = leftRotate(root->leftChild); } return (root->leftChild == NULL)? root: rightRotate(root); } else { if (root->rightChild == NULL) return root; if (root->rightChild->data > data) { root->rightChild->leftChild = splay(root->rightChild->leftChild, data); if (root->rightChild->leftChild != NULL) root->rightChild = rightRotate(root->rightChild); } else if (root->rightChild->data < data) { root->rightChild->rightChild = splay(root->rightChild->rightChild, data); root = leftRotate(root); } return (root->rightChild == NULL)? root: leftRotate(root); } } struct node* insert(struct node *root, int k){ if (root == NULL) return newNode(k); root = splay(root, k); if (root->data == k) return root; struct node *newnode = newNode(k); if (root->data > k) { newnode->rightChild = root; newnode->leftChild = root->leftChild; root->leftChild = NULL; } else { newnode->leftChild = root; newnode->rightChild = root->rightChild; root->rightChild = NULL; } return newnode; } struct node* deletenode(struct node* root, int data){ struct node* temp; if (root == NULL) return NULL; root = splay(root, data); if (data != root->data) return root; if (!root->leftChild) { temp = root; root = root->rightChild; } else { temp = root; root = splay(root->leftChild, data); root->rightChild = temp->rightChild; } free(temp); return root; } void printTree(struct node *root){ if (root == NULL) return; if (root != NULL) { printTree(root->leftChild); printf("%d ", root->data); printTree(root->rightChild); } } int main(){ struct node* root = newNode(34); root->leftChild = newNode(15); root->rightChild = newNode(40); root->leftChild->leftChild = newNode(12); root->leftChild->leftChild->rightChild = newNode(14); root->rightChild->rightChild = newNode(59); printf("The Splay tree is \n"); printTree(root); root = deletenode(root, 40); printf("\nThe Splay tree after deletion is \n"); printTree(root); return 0; }
输出
The Splay tree is 12 14 15 34 40 59 The Splay tree after deletion is 12 14 15 34 59
#include <bits/stdc++.h> using namespace std; class node{ public: int data; node *leftChild, *rightChild; }; node* newNode(int data){ node* Node = new node(); Node->data = data; Node->leftChild = Node->rightChild = NULL; return (Node); } node *rightRotate(node *x){ node *y = x->leftChild; x->leftChild = y->rightChild; y->rightChild = x; return y; } node *leftRotate(node *x){ node *y = x->rightChild; x->rightChild = y->leftChild; y->leftChild = x; return y; } node *splay(node *root, int data){ if (root == NULL || root->data == data) return root; if (root->data > data) { if (root->leftChild == NULL) return root; if (root->leftChild->data > data) { root->leftChild->leftChild = splay(root->leftChild->leftChild, data); root = rightRotate(root); } else if (root->leftChild->data < data) { root->leftChild->rightChild = splay(root->leftChild->rightChild, data); if (root->leftChild->rightChild != NULL) root->leftChild = leftRotate(root->leftChild); } return (root->leftChild == NULL)? root: rightRotate(root); } else { if (root->rightChild == NULL) return root; if (root->rightChild->data > data) { root->rightChild->leftChild = splay(root->rightChild->leftChild, data); if (root->rightChild->leftChild != NULL) root->rightChild = rightRotate(root->rightChild); } else if (root->rightChild->data < data) { root->rightChild->rightChild = splay(root->rightChild->rightChild, data); root = leftRotate(root); } return (root->rightChild == NULL)? root: leftRotate(root); } } node* insert(node *root, int k) { if (root == NULL) return newNode(k); root = splay(root, k); if (root->data == k) return root; node *newnode = newNode(k); if (root->data > k) { newnode->rightChild = root; newnode->leftChild = root->leftChild; root->leftChild = NULL; } else { newnode->leftChild = root; newnode->rightChild = root->rightChild; root->rightChild = NULL; } return newnode; } node* deletenode(struct node* root, int data){ struct node* temp; if (root == NULL) return NULL; root = splay(root, data); if (data != root->data) return root; if (!root->leftChild) { temp = root; root = root->rightChild; } else { temp = root; root = splay(root->leftChild, data); root->rightChild = temp->rightChild; } free(temp); return root; } void printTree(node *root){ if (root == NULL) return; if (root != NULL) { printTree(root->leftChild); cout<<root->data<<" "; printTree(root->rightChild); } } int main(){ node* root = newNode(34); root->leftChild = newNode(15); root->rightChild = newNode(40); root->leftChild->leftChild = newNode(12); root->leftChild->leftChild->rightChild = newNode(14); root->rightChild->rightChild = newNode(59); cout<<"The Splay tree is \n"; printTree(root); root = deletenode(root, 40); cout<<"\nThe Splay tree after deletion is \n"; printTree(root); return 0; }
输出
The Splay tree is 12 14 15 34 40 59 The Splay tree after deletion is 12 14 15 34 59
import java.io.*; public class SplayTree { static class node { int data; node leftChild, rightChild; }; static node newNode(int data) { node Node = new node(); Node.data = data; Node.leftChild = Node.rightChild = null; return (Node); } static node rightRotate(node x) { node y = x.leftChild; x.leftChild = y.rightChild; y.rightChild = x; return y; } static node leftRotate(node x) { node y = x.rightChild; x.rightChild = y.leftChild; y.leftChild = x; return y; } static node splay(node root, int data) { if (root == null || root.data == data) return root; if (root.data > data) { if (root.leftChild == null) return root; if (root.leftChild.data > data) { root.leftChild.leftChild = splay(root.leftChild.leftChild, data); root = rightRotate(root); } else if (root.leftChild.data < data) { root.leftChild.rightChild = splay(root.leftChild.rightChild, data); if (root.leftChild.rightChild != null) root.leftChild = leftRotate(root.leftChild); } return (root.leftChild == null)? root: rightRotate(root); } else { if (root.rightChild == null) return root; if (root.rightChild.data > data) { root.rightChild.leftChild = splay(root.rightChild.leftChild, data); if (root.rightChild.leftChild != null) root.rightChild = rightRotate(root.rightChild); } else if (root.rightChild.data < data) { root.rightChild.rightChild = splay(root.rightChild.rightChild, data); root = leftRotate(root); } return (root.rightChild == null)? root: leftRotate(root); } } static node insert(node root, int k) { if (root == null) return newNode(k); root = splay(root, k); if (root.data == k) return root; node newnode = newNode(k); if (root.data > k) { newnode.rightChild = root; newnode.leftChild = root.leftChild; root.leftChild = null; } else { newnode.leftChild = root; newnode.rightChild = root.rightChild; root.rightChild = null; } return newnode; } static node deletenode(node root, int data) { node temp; if (root == null) return null; root = splay(root, data); if (data != root.data) return root; if (root.leftChild == null) { temp = root; root = root.rightChild; } else { temp = root; root = splay(root.leftChild, data); root.rightChild = temp.rightChild; } return root; } static void printTree(node root) { if (root == null) return; if (root != null) { printTree(root.leftChild); System.out.print(root.data + " "); printTree(root.rightChild); } } public static void main(String args[]) { node root = newNode(34); root.leftChild = newNode(15); root.rightChild = newNode(40); root.leftChild.leftChild = newNode(12); root.leftChild.leftChild.rightChild = newNode(14); root.rightChild.rightChild = newNode(59); System.out.println("The Splay tree is: "); printTree(root); root = deletenode(root, 40); System.out.println("\nThe Splay tree after deletion is: "); printTree(root); } }
输出
The Splay tree is: 12 14 15 34 40 59 The Splay tree after deletion is: 12 14 15 34 59
#Python Code for Search Operation of splay Trees class Node: def __init__(self, data): self.data = data self.leftChild = None self.rightChild = None def newNode(data): newNode = Node(data) newNode.leftChild = newNode.rightChild = None return newNode def rightRotate(x): y = x.leftChild x.leftChild = y.rightChild y.rightChild = x return y def leftRotate(x): y = x.rightChild x.rightChild = y.leftChild y.leftChild = x return y def splay(root, data): if root is None or root.data == data: return root if root.data > data: if root.leftChild is None: return root if root.leftChild.data > data: root.leftChild.leftChild = splay(root.leftChild.leftChild, data) root = rightRotate(root) elif root.leftChild.data < data: root.leftChild.rightChild = splay(root.leftChild.rightChild, data) if root.leftChild.rightChild is not None: root.leftChild = leftRotate(root.leftChild) return root if root.leftChild is None else rightRotate(root) else: if root.rightChild is None: return root if root.rightChild.data > data: root.rightChild.leftChild = splay(root.rightChild.leftChild, data) if root.rightChild.leftChild is not None: root.rightChild = rightRotate(root.rightChild) elif root.rightChild.data < data: root.rightChild.rightChild = splay(root.rightChild.rightChild, data) root = leftRotate(root) return root if root.rightChild is None else leftRotate(root) def insert(root, k): if root is None: return newNode(k) root = splay(root, k) if root.data == k: return root newnode = newNode(k) if root.data > k: newnode.rightChild = root newnode.leftChild = root.leftChild root.leftChild = None else: newnode.leftChild = root newnode.rightChild = root.rightChild root.rightChild = None return newnode def deletenode(root, data): temp = None if root is None: return None root = splay(root, data) if data != root.data: return root if root.leftChild is None: temp = root root = root.rightChild else: temp = root root = splay(root.leftChild, data) root.rightChild = temp.rightChild del temp return root def printTree(root): if root is None: return if root is not None: printTree(root.leftChild) print(root.data, end=" ") printTree(root.rightChild) root = newNode(34) root.leftChild = newNode(15) root.rightChild = newNode(40) root.leftChild.leftChild = newNode(12) root.leftChild.leftChild.rightChild = newNode(14) root.rightChild.rightChild = newNode(59) print("The Splay tree is") printTree(root) root = deletenode(root, 40) print("\nThe Splay tree after deletion is") printTree(root)
输出
The Splay tree is 12 14 15 34 40 59 The Splay tree after deletion is 12 14 15 34 59
Trie数据结构
Trie是一种多路搜索树,主要用于从字符串或一组字符串中检索特定的键。它以一种有序且高效的方式存储数据,因为它使用指针指向字母表中的每个字母。
Trie数据结构基于字符串的公共前缀。根节点可以具有任意数量的节点,具体取决于集合中存在的字符串数量。Trie的根节点不包含任何值,只包含指向其子节点的指针。
Trie数据结构有三种类型 -
标准Trie
压缩Trie
后缀Trie
Trie的实际应用包括 - 自动更正、文本预测、情感分析和数据科学。
Trie的基本操作
Trie数据结构也执行树数据结构执行的相同操作。它们是 -
插入
删除
搜索
插入
Trie中的插入操作很简单。Trie中的根节点不保存任何值,插入操作从根节点的直接子节点开始,这些子节点充当其子节点的键。但是,我们观察到Trie中的每个节点都表示输入字符串中的单个字符。因此,字符一个接一个地添加到Trie中,而Trie中的链接充当指向下一级节点的指针。
示例
//C code for insertion operation of tries algorithm #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define ALPHABET_SIZE 26 struct TrieNode { struct TrieNode* children[ALPHABET_SIZE]; bool isEndOfWord; }; struct TrieNode* createNode() { struct TrieNode* node = (struct TrieNode*)malloc(sizeof(struct TrieNode)); node->isEndOfWord = false; for (int i = 0; i < ALPHABET_SIZE; i++) { node->children[i] = NULL; } return node; } void insert(struct TrieNode* root, char* word) { struct TrieNode* curr = root; for (int i = 0; word[i] != '\0'; i++) { int index = word[i] - 'a'; if (curr->children[index] == NULL) { curr->children[index] = createNode(); } curr = curr->children[index]; } curr->isEndOfWord = true; } bool search(struct TrieNode* root, char* word) { struct TrieNode* curr = root; for (int i = 0; word[i] != '\0'; i++) { int index = word[i] - 'a'; if (curr->children[index] == NULL) { return false; } curr = curr->children[index]; } return (curr != NULL && curr->isEndOfWord); } bool startsWith(struct TrieNode* root, char* prefix) { struct TrieNode* curr = root; for (int i = 0; prefix[i] != '\0'; i++) { int index = prefix[i] - 'a'; if (curr->children[index] == NULL) { return false; } curr = curr->children[index]; } return true; } int main() { struct TrieNode* root = createNode(); //inserting the elements insert(root, "Lamborghini"); insert(root, "Mercedes-Benz"); insert(root, "Land Rover"); insert(root, "Maruti Suzuki"); //printing the elements printf("Inserted values are: \n"); printf("Lamborghini\n"); printf( "Mercedes-Benz\n"); printf( "Land Rover\n"); printf( "Maruti Suzuki"); return 0; }
输出
Inserted values are: Lamborghini Mercedes-Benz Land Rover Maruti Suzuki
// C++ code for Insertion operation of tries algorithm #include <iostream> #include <unordered_map> using namespace std; class TrieNode { public: unordered_map<char, TrieNode*> children; bool isEndOfWord; TrieNode() { isEndOfWord = false; } }; class Trie { private: TrieNode* root; public: Trie() { root = new TrieNode(); } void insert(string word) { TrieNode* curr = root; for (char ch : word) { if (curr->children.find(ch) == curr->children.end()) { curr->children[ch] = new TrieNode(); } curr = curr->children[ch]; } curr->isEndOfWord = true; } bool search(string word) { TrieNode* curr = root; for (char ch : word) { if (curr->children.find(ch) == curr->children.end()) { return false; } curr = curr->children[ch]; } return curr->isEndOfWord; } bool startsWith(string prefix) { TrieNode* curr = root; for (char ch : prefix) { if (curr->children.find(ch) == curr->children.end()) { return false; } curr = curr->children[ch]; } return true; } }; int main() { Trie car; //inserting the elements car.insert("Lamborghini"); car.insert("Mercedes-Benz"); car.insert("Land Rover"); car.insert("Maruti Suzuki"); //printing the elmenents printf("Inserted values are: \n"); cout << "Lamborghini" << endl; cout <<"Mercedes-Benz"<< endl; cout <<"Land Rover" << endl; cout << "Maruti Suzuki" << endl; return 0; }
输出
Inserted values are: Lamborghini Mercedes-Benz Land Rover Maruti Suzuki
//Java Code for insertion operation of tries Algorithm import java.util.HashMap; import java.util.Map; class TrieNode { Map<Character, TrieNode> children; boolean isEndOfWord; TrieNode() { children = new HashMap<>(); isEndOfWord = false; } } class Trie { private TrieNode root; Trie() { root = new TrieNode(); } void insert(String word) { TrieNode curr = root; for (char ch : word.toCharArray()) { curr.children.putIfAbsent(ch, new TrieNode()); curr = curr.children.get(ch); } curr.isEndOfWord = true; } boolean search(String word) { TrieNode curr = root; for (char ch : word.toCharArray()) { if (!curr.children.containsKey(ch)) { return false; } curr = curr.children.get(ch); } return curr.isEndOfWord; } boolean startsWith(String prefix) { TrieNode curr = root; for (char ch : prefix.toCharArray()) { if (!curr.children.containsKey(ch)) { return false; } curr = curr.children.get(ch); } return true; } } public class Main { public static void main(String[] args) { Trie car = new Trie(); //Inserting the elements car.insert("Lamborghini"); car.insert("Mercedes-Benz"); car.insert("Land Rover"); car.insert("Maruti Suzuki"); //Printing the elements System.out.println("Inserted values are: "); System.out.println("Lamborghini"); System.out.println("Mercedes-Benz"); System.out.println("Land Rover"); System.out.println("Maruti Suzuki"); } }
输出
Inserted values are: Lamborghini Mercedes-Benz Land Rover Maruti Suzuki
#Python Code for insertion operation of tries Algorithm class TrieNode: def __init__(self): self.children = {} self.isEndOfWord = False class Trie: def __init__(self): self.root = TrieNode() def insert(self, word): curr = self.root for ch in word: if ch not in curr.children: curr.children[ch] = TrieNode() curr = curr.children[ch] curr.isEndOfWord = True def search(self, word): curr = self.root for ch in word: if ch not in curr.children: return False curr = curr.children[ch] return curr.isEndOfWord def startsWith(self, prefix): curr = self.root for ch in prefix: if ch not in curr.children: return False curr = curr.children[ch] return True if __name__ == '__main__': car = Trie() #inserting the elements car.insert("Lamborghini") car.insert("Mercedes-Benz") car.insert("Land Rover") car.insert("Maruti Suzuki") #printing the elements print("Inserted values are: ") print("Lamborghini") print("Mercedes-Benz") print("Land Rover") print("Maruti Suzuki")
输出
Inserted values are: Lamborghini Mercedes-Benz Land Rover Maruti Suzuki
删除
Trie中的删除操作使用自下而上的方法执行。在Trie中搜索要删除的元素,如果找到则删除。但是,在执行删除操作时,需要牢记一些特殊情况。
情况1 - 键是唯一的 - 在这种情况下,从节点中删除整个键路径。(唯一的键表示没有其他路径从一条路径分支出来)。
情况2 - 键不是唯一的 - 更新叶子节点。例如,如果要删除的键为see,但它是另一个键seethe的前缀;我们删除see并将t、h和e的布尔值更改为false。
情况3 - 要删除的键已经有一个前缀 - 删除到前缀为止的值,并将前缀保留在树中。例如,如果要删除的键为heart,但存在另一个键he;因此我们删除a、r和t,直到只剩下he。
示例
//C code for Deletion Operation of tries Algorithm #include <stdio.h> #include <stdlib.h> #include <stdbool.h> //Define size 26 #define ALPHABET_SIZE 26 struct TrieNode { struct TrieNode* children[ALPHABET_SIZE]; bool isEndOfWord; }; struct TrieNode* createNode() { struct TrieNode* node = (struct TrieNode*)malloc(sizeof(struct TrieNode)); node->isEndOfWord = false; for (int i = 0; i < ALPHABET_SIZE; i++) { node->children[i] = NULL; } return node; } void insert(struct TrieNode* root, char* word) { struct TrieNode* curr = root; for (int i = 0; word[i] != '\0'; i++) { int index = word[i] - 'a'; if (curr->children[index] == NULL) { curr->children[index] = createNode(); } curr = curr->children[index]; } curr->isEndOfWord = true; } bool search(struct TrieNode* root, char* word) { struct TrieNode* curr = root; for (int i = 0; word[i] != '\0'; i++) { int index = word[i] - 'a'; if (curr->children[index] == NULL) { return false; } curr = curr->children[index]; } return (curr != NULL && curr->isEndOfWord); } bool startsWith(struct TrieNode* root, char* prefix) { struct TrieNode* curr = root; for (int i = 0; prefix[i] != '\0'; i++) { int index = prefix[i] - 'a'; if (curr->children[index] == NULL) { return false; } curr = curr->children[index]; } return true; } bool deleteWord(struct TrieNode* root, char* word) { struct TrieNode* curr = root; struct TrieNode* parent = NULL; int index; for (int i = 0; word[i] != '\0'; i++) { index = word[i] - 'a'; if (curr->children[index] == NULL) { return false; // Word does not exist in the Trie } parent = curr; curr = curr->children[index]; } if (!curr->isEndOfWord) { return false; // Word does not exist in the Trie } curr->isEndOfWord = false; // Mark as deleted if (parent != NULL) { parent->children[index] = NULL; // Remove the child node } return true; } int main() { struct TrieNode* root = createNode(); //Inserting the elements insert(root, "lamborghini"); insert(root, "mercedes-benz"); insert(root, "land rover"); insert(root, "maruti suzuki"); //Before Deletion printf("Before Deletion\n"); printf("%d\n", search(root, "lamborghini")); // Output: 1 (true) printf("%d\n", search(root, "mercedes-benz")); // Output: 1 (true) printf("%d\n", search(root, "land rover")); // Output: 1 (true) printf("%d\n", search(root, "maruti suzuki")); // Output: 1 (true) //Deleting the elements deleteWord(root, "lamborghini"); deleteWord(root, "land rover"); //After Deletion printf("After Deletion\n"); printf("%d\n", search(root, "lamborghini")); // Output: 0 (false) printf("%d\n", search(root, "mercedes-benz")); // Output: 1 (true) printf("%d\n", search(root, "land rover")); // Output: 0 (false) printf("%d\n", search(root, "maruti suzuki")); // Output: 1 (true) return 0; }
输出
Before Deletion 1 1 1 1 After Deletion 0 1 0 1
//C++ code for Deletion operation of tries algorithm #include <iostream> #include <unordered_map> using namespace std; class TrieNode { public: unordered_map<char, TrieNode*> children; bool isEndOfWord; TrieNode() { isEndOfWord = false; } }; class Trie { private: TrieNode* root; public: Trie() { root = new TrieNode(); } void insert(string word) { TrieNode* curr = root; for (char ch : word) { if (curr->children.find(ch) == curr->children.end()) { curr->children[ch] = new TrieNode(); } curr = curr->children[ch]; } curr->isEndOfWord = true; } bool search(string word) { TrieNode* curr = root; for (char ch : word) { if (curr->children.find(ch) == curr->children.end()) { return false; } curr = curr->children[ch]; } return curr->isEndOfWord; } bool startsWith(string prefix) { TrieNode* curr = root; for (char ch : prefix) { if (curr->children.find(ch) == curr->children.end()) { return false; } curr = curr->children[ch]; } return true; } bool deleteWord(string word) { return deleteHelper(root, word, 0); } private: bool deleteHelper(TrieNode* curr, string word, int index) { if (index == word.length()) { if (!curr->isEndOfWord) { return false; // Word does not exist in the Trie } curr->isEndOfWord = false; // Mark as deleted return curr->children.empty(); // Return true if no more children } char ch = word[index]; if (curr->children.find(ch) == curr->children.end()) { return false; // Word does not exist in the Trie } TrieNode* child = curr->children[ch]; bool shouldDeleteChild = deleteHelper(child, word, index + 1); if (shouldDeleteChild) { curr->children.erase(ch); // Remove the child node if necessary return curr->children.empty(); // Return true if no more children } return false; } }; int main() { Trie car; //inserting the elemnets car.insert("Lamborghini"); car.insert("Mercedes-Benz"); car.insert("Land Rover"); car.insert("Maruti Suzuki"); //Before Deletion cout << "Before Deletion" << endl; cout << car.search("Lamborghini") << endl; // Output: 1 (true) cout << car.search("Mercedes-Benz") << endl; // Output: 1 (true) cout << car.search("Land Rover") << endl; // Output: 1 (true) cout << car.search("Maruti Suzuki") << endl; // Output: 1 (true) //Deleting elements using deletion operation car.deleteWord("Lamborghini"); car.deleteWord("Land Rover"); //After Deletion cout << "After Deletion" << endl; cout << car.search("Lamborghini") << endl; // Output: 0 (false) cout << car.search("Mercedes-Benz") << endl; // Output: 1 (true) cout << car.search("Land Rover") << endl; // Output: 0 (false) cout << car.search("Maruti Suzuki") << endl; // Output: 1 (true) return 0; }
输出
Before Deletion 1 1 1 1 After Deletion 0 1 0 1
//Java code for Deletion operator of tries algotrithm import java.util.HashMap; import java.util.Map; class TrieNode { Map<Character, TrieNode> children; boolean isEndOfWord; TrieNode() { children = new HashMap<>(); isEndOfWord = false; } } class Trie { private TrieNode root; Trie() { root = new TrieNode(); } void insert(String word) { TrieNode curr = root; for (char ch : word.toCharArray()) { curr.children.putIfAbsent(ch, new TrieNode()); curr = curr.children.get(ch); } curr.isEndOfWord = true; } boolean search(String word) { TrieNode curr = root; for (char ch : word.toCharArray()) { if (!curr.children.containsKey(ch)) { return false; } curr = curr.children.get(ch); } return curr.isEndOfWord; } boolean startsWith(String prefix) { TrieNode curr = root; for (char ch : prefix.toCharArray()) { if (!curr.children.containsKey(ch)) { return false; } curr = curr.children.get(ch); } return true; } boolean delete(String word) { return deleteHelper(root, word, 0); } private boolean deleteHelper(TrieNode curr, String word, int index) { if (index == word.length()) { if (!curr.isEndOfWord) { return false; // Word does not exist in the Trie } curr.isEndOfWord = false; // Mark as deleted return curr.children.isEmpty(); // Return true if no more children } char ch = word.charAt(index); if (!curr.children.containsKey(ch)) { return false; // Word does not exist in the Trie } TrieNode child = curr.children.get(ch); boolean shouldDeleteChild = deleteHelper(child, word, index + 1); if (shouldDeleteChild) { curr.children.remove(ch); // Remove the child node if necessary return curr.children.isEmpty(); // Return true if no more children } return false; } } public class Main { public static void main(String[] args) { Trie car = new Trie(); //Inserting the elements car.insert("Lamborghini"); car.insert("Mercedes-Benz"); car.insert("Land Rover"); car.insert("Maruti Suzuki"); //Before Deletion System.out.println("Before Deletion"); //Printing the elements System.out.println(car.search("Lamborghini")); // Output: true System.out.println(car.search("Mercedes-Benz")); // Output: true System.out.println(car.search("Land Rover")); // Output: true System.out.println(car.search("Maruti Suzuki")); // Output: true //Deleting the elements using deletion operation car.delete("Lamborghini"); car.delete("Land Rover"); // After Deletion System.out.println("After Deletion"); // Prints the elements in the Boolean expression System.out.println(car.search("Lamborghini")); // Output: false System.out.println(car.search("Mercedes-Benz")); // Output: true System.out.println(car.search("Land Rover")); // Output: false System.out.println(car.search("Maruti Suzuki")); // Output: true } }
输出
Before Deletion true true true true After Deletion false true false true
#python Code for Deletion operation of tries algorithm class TrieNode: def __init__(self): self.children = {} self.isEndOfWord = False class Trie: def __init__(self): self.root = TrieNode() def insert(self, word): curr = self.root for ch in word: if ch not in curr.children: curr.children[ch] = TrieNode() curr = curr.children[ch] curr.isEndOfWord = True def search(self, word): curr = self.root for ch in word: if ch not in curr.children: return False curr = curr.children[ch] return curr.isEndOfWord def startsWith(self, prefix): curr = self.root for ch in prefix: if ch not in curr.children: return False curr = curr.children[ch] return True def delete(self, word): return self.deleteHelper(self.root, word, 0) def deleteHelper(self, curr, word, index): if index == len(word): if not curr.isEndOfWord: return False # Word does not exist in the Trie curr.isEndOfWord = False # Mark as deleted return len(curr.children) == 0 # Return True if no more children ch = word[index] if ch not in curr.children: return False # Word does not exist in the Trie child = curr.children[ch] shouldDeleteChild = self.deleteHelper(child, word, index + 1) if shouldDeleteChild: del curr.children[ch] # Remove the child node if necessary return len(curr.children) == 0 # Return True if no more children return False trie = Trie() #inserting the elements trie.insert("Lamborghini") trie.insert("Mercedes-Benz") trie.insert("Land Rover") trie.insert("Maruti Suzuki") #Before Deletion print("Before Deletion:") print(trie.search("Lamborghini")) # Output: True print(trie.search("Mercedes-Benz")) # Output: True print(trie.search("Land Rover")) # Output: True print(trie.search("Maruti Suzuki")) # Output: True #deleting the elements using Deletion operation trie.delete("Lamborghini") trie.delete("Land Rover") #After Deletion print("After Deletion:") #print elements print(trie.search("Lamborghini")) # Output: False print(trie.search("Mercedes-Benz")) # Output: True print(trie.search("Land Rover")) # Output: False print(trie.search("Maruti Suzuki")) # Output: True
输出
Before Deletion: True True True True After Deletion: False True False True
搜索
在Trie中搜索是一种相当直接的方法。我们只能根据键节点(插入操作开始的节点)向下移动Trie的级别。搜索直到到达路径的末尾。如果找到元素,则搜索成功;否则,搜索失败。
示例
//C program for search operation of tries algorithm #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define ALPHABET_SIZE 26 struct TrieNode { struct TrieNode* children[ALPHABET_SIZE]; bool isEndOfWord; }; struct TrieNode* createNode() { struct TrieNode* node = (struct TrieNode*)malloc(sizeof(struct TrieNode)); node->isEndOfWord = false; for (int i = 0; i < ALPHABET_SIZE; i++) { node->children[i] = NULL; } return node; } void insert(struct TrieNode* root, char* word) { struct TrieNode* curr = root; for (int i = 0; word[i] != '\0'; i++) { int index = word[i] - 'a'; if (curr->children[index] == NULL) { curr->children[index] = createNode(); } curr = curr->children[index]; } curr->isEndOfWord = true; } bool search(struct TrieNode* root, char* word) { struct TrieNode* curr = root; for (int i = 0; word[i] != '\0'; i++) { int index = word[i] - 'a'; if (curr->children[index] == NULL) { return false; } curr = curr->children[index]; } return (curr != NULL && curr->isEndOfWord); } bool startsWith(struct TrieNode* root, char* prefix) { struct TrieNode* curr = root; for (int i = 0; prefix[i] != '\0'; i++) { int index = prefix[i] - 'a'; if (curr->children[index] == NULL) { return false; } curr = curr->children[index]; } return true; } int main() { struct TrieNode* root = createNode(); //inserting the elements insert(root, "Lamborghini"); insert(root, "Mercedes-Benz"); insert(root, "Land Rover"); insert(root, "Maruti Suzuki"); //Searching elements printf("Searching Cars\n"); //Printing searched elements printf("%d\n", search(root, "Lamborghini")); // Output: 1 (true) printf("%d\n", search(root, "Mercedes-Benz")); // Output: 1 (true) printf("%d\n", search(root, "Honda")); // Output: 0 (false) printf("%d\n", search(root, "Land Rover")); // Output: 1 (true) printf("%d\n", search(root, "BMW")); // Output: 0 (false) //Searching the elements the name starts with? printf("Cars name starts with\n"); //Printing the elements printf("%d\n", startsWith(root, "Lambo")); // Output: 1 (true) printf("%d\n", startsWith(root, "Hon")); // Output: 0 (false) printf("%d\n", startsWith(root, "Hy")); // Output: 0 (false) printf("%d\n", startsWith(root, "Mar")); // Output: 1 (true) printf("%d\n", startsWith(root, "Land")); // Output: 1 (true) return 0; }
输出
Searching Cars 1 1 0 1 0 Cars name starts with 1 0 0 1 1
//C++ code for Search operation of tries algorithm #include <iostream> #include <unordered_map> using namespace std; class TrieNode { public: unordered_map<char, TrieNode*> children; bool isEndOfWord; TrieNode() { isEndOfWord = false; } }; class Trie { private: TrieNode* root; public: Trie() { root = new TrieNode(); } void insert(string word) { TrieNode* curr = root; for (char ch : word) { if (curr->children.find(ch) == curr->children.end()) { curr->children[ch] = new TrieNode(); } curr = curr->children[ch]; } curr->isEndOfWord = true; } bool search(string word) { TrieNode* curr = root; for (char ch : word) { if (curr->children.find(ch) == curr->children.end()) { return false; } curr = curr->children[ch]; } return curr->isEndOfWord; } bool startsWith(string prefix) { TrieNode* curr = root; for (char ch : prefix) { if (curr->children.find(ch) == curr->children.end()) { return false; } curr = curr->children[ch]; } return true; } }; int main() { Trie car; //inserting the elements car.insert("Lamborghini"); car.insert("Mercedes-Benz"); car.insert("Land Rover"); car.insert("Maruti Suzuki"); //searching elements cout<< "Searching Cars"<< endl; // Printing searched elements in Boolean expression cout << car.search("Lamborghini") << endl; // Output: 1 (true) cout << car.search("Mercedes-Benz") << endl; // Output: 1 (true) cout << car.search("Honda") << endl; // Output: 0 (false) cout << car.search("Land Rover") << endl; // Output: 1 (true) cout << car.search("BMW") << endl; // Output: 0 (false) //searching names starts with? cout<<"cars name starts with" << endl; //Printing the elements cout << car.startsWith("Lambo") << endl; // Output: 1 (true) cout << car.startsWith("Hon") << endl; // Output: 0 (false) cout << car.startsWith("Hy") << endl; // Output: 0 (false) cout << car.startsWith("Mar") << endl; // Output: 1 (true) cout << car.startsWith("Land") << endl; // Output: 1 (true) return 0; }
输出
Searching Cars 1 1 0 1 0 cars name starts with 1 0 0 1 1
//Java program for tries Algorithm import java.util.HashMap; import java.util.Map; class TrieNode { Map<Character, TrieNode> children; boolean isEndOfWord; TrieNode() { children = new HashMap<>(); isEndOfWord = false; } } class Trie { private TrieNode root; Trie() { root = new TrieNode(); } void insert(String word) { TrieNode curr = root; for (char ch : word.toCharArray()) { curr.children.putIfAbsent(ch, new TrieNode()); curr = curr.children.get(ch); } curr.isEndOfWord = true; } boolean search(String word) { TrieNode curr = root; for (char ch : word.toCharArray()) { if (!curr.children.containsKey(ch)) { return false; } curr = curr.children.get(ch); } return curr.isEndOfWord; } boolean startsWith(String prefix) { TrieNode curr = root; for (char ch : prefix.toCharArray()) { if (!curr.children.containsKey(ch)) { return false; } curr = curr.children.get(ch); } return true; } } public class Main { public static void main(String[] args) { Trie car = new Trie(); //Inserting the elements car.insert("Lamborghini"); car.insert("Mercedes-Benz"); car.insert("Land Rover"); car.insert("Maruti Suzuki"); //searching the elements System.out.println("Searching Cars"); //Printing the searched elements System.out.println(car.search("Lamborghini")); // Output: true System.out.println(car.search("Mercedes-Benz")); // Output: true System.out.println(car.search("Honda")); // Output: false System.out.println(car.search("Land Rover")); // Output: true System.out.println(car.search("BMW")); // Output: false //searching the elements name start with? System.out.println("Cars name starts with"); //Printing the elements System.out.println(car.startsWith("Lambo")); // Output: true System.out.println(car.startsWith("Hon")); // Output: false System.out.println(car.startsWith("Hy")); // Output: false System.out.println(car.startsWith("Mar")); // Output: true System.out.println(car.startsWith("Land")); // Output: true } }
输出
Searching Cars true true false true false Cars name starts with true false false true true
#Python code for Search operation of tries algorithm class TrieNode: def __init__(self): self.children = {} self.isEndOfWord = False class Trie: def __init__(self): self.root = TrieNode() def insert(self, word): curr = self.root for ch in word: if ch not in curr.children: curr.children[ch] = TrieNode() curr = curr.children[ch] curr.isEndOfWord = True def search(self, word): curr = self.root for ch in word: if ch not in curr.children: return False curr = curr.children[ch] return curr.isEndOfWord def startsWith(self, prefix): curr = self.root for ch in prefix: if ch not in curr.children: return False curr = curr.children[ch] return True if __name__ == '__main__': car = Trie() #Inserting the elements car.insert("Lamborghini") car.insert("Mercedes-Benz") car.insert("Land Rover") car.insert("Maruti Suzuki") #Searching elements print("Searching Cars") #Printing the searched elements print(car.search("Lamborghini")) # Output: True print(car.search("Mercedes-Benz")) # Output: True print(car.search("Honda")) # Output: False print(car.search("Land Rover")) # Output: True print(car.search("BMW")) # Output: False #printing elements name starts with? print("Cars name starts with") print(car.startsWith("Lambo")) # Output: True print(car.startsWith("Hon")) # Output: False print(car.startsWith("Hy")) # Output: False print(car.startsWith("Mar")) # Output: True print(car.startsWith("Land")) # Output: True
输出
Before Deletion: True True True True After Deletion: False True False True
堆数据结构
堆是平衡二叉树数据结构的一种特殊情况,其中根节点键与其子节点进行比较并相应地排列。如果α具有子节点β,则 -
key(α) ≥ key(β)
由于父节点的值大于子节点的值,因此此属性生成最大堆。根据此标准,堆可以分为两种类型 -
For Input → 35 33 42 10 14 19 27 44 26 31
最小堆 (Min-Heap) − 根节点的值小于或等于其任何一个子节点的值。
最大堆 (Max-Heap) − 根节点的值大于或等于其任何一个子节点的值。
这两棵树都是使用相同的输入和到达顺序构建的。
最大堆构建算法
我们将使用相同的示例来演示如何创建一个最大堆。创建最小堆的过程类似,但我们选择最小值而不是最大值。
我们将推导出一个最大堆的算法,该算法一次插入一个元素。在任何时候,堆都必须保持其属性。在插入过程中,我们还假设我们将节点插入到一个已经堆化的树中。
Step 1 − Create a new node at the end of heap. Step 2 − Assign new value to the node. Step 3 − Compare the value of this child node with its parent. Step 4 − If value of parent is less than child, then swap them. Step 5 − Repeat step 3 & 4 until Heap property holds.
注意 − 在最小堆构建算法中,我们期望父节点的值小于子节点的值。
让我们通过动画来说明来理解最大堆的构建。我们考虑之前使用的相同输入样本。
示例
//C code for Max Heap construction Algorithm #include <stdio.h> #include <stdlib.h> // Structure to represent a heap typedef struct { int* array; // Array to store heap elements int capacity; // Maximum capacity of the heap int size; // Current size of the heap } Heap; // Function to create a new heap Heap* createHeap(int capacity) { Heap* heap = (Heap*)malloc(sizeof(Heap)); heap->array = (int*)malloc(capacity * sizeof(int)); heap->capacity = capacity; heap->size = 0; return heap; } // Function to swap two elements in the heap void swap(int* a, int* b) { int temp = *a; *a = *b; *b = temp; } // Function to heapify a subtree rooted at index i void heapify(Heap* heap, int i) { int largest = i; int left = 2 * i + 1; int right = 2 * i + 2; // Check if the left child is larger than the root if (left < heap->size && heap->array[left] > heap->array[largest]) largest = left; // Check if the right child is larger than the largest so far if (right < heap->size && heap->array[right] > heap->array[largest]) largest = right; // If the largest is not the root, swap the root with the largest if (largest != i) { swap(&heap->array[i], &heap->array[largest]); heapify(heap, largest); } } // Function to insert a new element into the heap void insert(Heap* heap, int value) { if (heap->size == heap->capacity) { printf("Heap is full. Cannot insert more elements.\n"); return; } // Insert the new element at the end int i = heap->size++; heap->array[i] = value; // Fix the heap property if it is violated while (i != 0 && heap->array[(i - 1) / 2] < heap->array[i]) { swap(&heap->array[i], &heap->array[(i - 1) / 2]); i = (i - 1) / 2; } } // Function to extract the maximum element from the heap int extractMax(Heap* heap) { if (heap->size == 0) { printf("Heap is empty. Cannot extract maximum element.\n"); return -1; } // Store the root element int max = heap->array[0]; // Replace the root with the last element heap->array[0] = heap->array[heap->size - 1]; heap->size--; // Heapify the root heapify(heap, 0); return max; } // Function to print the elements of the heap void printHeap(Heap* heap) { printf("Heap elements: "); for (int i = 0; i < heap->size; i++) { printf("%d ", heap-<array[i]); } printf("\n"); } // Example usage of the heap int main() { Heap* heap = createHeap(10); insert(heap, 35); insert(heap, 33); insert(heap, 42); insert(heap, 10); insert(heap, 14); insert(heap, 19); insert(heap, 27); insert(heap, 44); insert(heap, 26); insert(heap, 31); printHeap(heap); int max = extractMax(heap); printf("Maximum element: %d\n", max); return 0; }
输出
Heap elements: 44 42 35 33 31 19 27 10 26 14 Maximum element: 44
//C++ code for Max Heap construction Algorithm #include <iostream> // Structure to represent a heap struct Heap { int* array; // Array to store heap elements int capacity; // Maximum capacity of the heap int size; // Current size of the heap }; // Function to create a new heap Heap* createHeap(int capacity) { Heap* heap = new Heap; heap->array = new int[capacity]; heap->capacity = capacity; heap->size = 0; return heap; } // Function to swap two elements in the heap void swap(int& a, int& b) { int temp = a; a = b; b = temp; } // Function to heapify a subtree rooted at index i void heapify(Heap* heap, int i) { int largest = i; int left = 2 * i + 1; int right = 2 * i + 2; // Check if the left child is larger than the root if (left <heap->size && heap->array[left] > heap->array[largest]) largest = left; // Check if the right child is larger than the largest so far if (right <heap->size && heap->array[right] > heap->array[largest]) largest = right; // If the largest is not the root, swap the root with the largest if (largest != i) { swap(heap->array[i], heap->array[largest]); heapify(heap, largest); } } // Function to insert a new element into the heap void insert(Heap* heap, int value) { if (heap->size == heap->capacity) { std::cout << "Heap is full. Cannot insert more elements." << std::endl; return; } // Insert the new element at the end int i = heap->size++; heap->array[i] = value; // Fix the heap property if it is violated while (i != 0 && heap->array[(i - 1) / 2] < heap->array[i]) { swap(heap->array[i], heap->array[(i - 1) / 2]); i = (i - 1) / 2; } } // Function to extract the maximum element from the heap int extractMax(Heap* heap) { if (heap->size == 0) { std::cout << "Heap is empty. Cannot extract maximum element." << std::endl; return -1; } // Store the root element int max = heap->array[0]; // Replace the root with the last element heap->array[0] = heap->array[heap->size - 1]; heap->size--; // Heapify the root heapify(heap, 0); return max; } // Function to print the elements of the heap void printHeap(Heap* heap) { std::cout << "Heap elements: "; for (int i = 0; i < heap->size; i++) { std::cout << heap->array[i] << " "; } std::cout << std::endl; } // Example usage of the heap int main() { Heap* heap = createHeap(10); insert(heap, 35); insert(heap, 33); insert(heap, 42); insert(heap, 10); insert(heap, 14); insert(heap, 19); insert(heap, 27); insert(heap, 44); insert(heap, 26); insert(heap, 31); printHeap(heap); int max = extractMax(heap); std::cout << "Maximum element: " << max << std::endl; return 0; }
输出
Heap elements: 44 42 35 33 31 19 27 10 26 14 Maximum element: 44
// Java code for for Max Heap construction Algorithm //Structure to represent a heap public class MaxHeap { private int[] heap; // To store heap elements private int capacity; // Maximum capacity of the heap private int size; // Current size of the heap // To create a new heap public MaxHeap(int capacity) { this.capacity = capacity; this.size = 0; this.heap = new int[capacity]; } private int parent(int i) { return (i - 1) / 2; } private int leftChild(int i) { return 2 * i + 1; } private int rightChild(int i) { return 2 * i + 2; } private void swap(int i, int j) { int temp = heap[i]; heap[i] = heap[j]; heap[j] = temp; } // Heapify a subtree rooted at index i private void heapifyDown(int i) { int largest = i; int left = leftChild(i); int right = rightChild(i); // Check if the left child is larger than the root if (left < size && heap[left] > heap[largest]) largest = left; // Check if the right child is larger than the largest so far if (right < size && heap[right] > heap[largest]) largest = right; // If the largest is not the root, swap the root with the largest if (largest != i) { swap(i, largest); heapifyDown(largest); } } private void heapifyUp(int i) { while (i > 0 && heap[i] > heap[parent(i)]) { int parent = parent(i); swap(i, parent); i = parent; } } // Insert the new element at the end public void insert(int value) { if (size == capacity) { System.out.println("Heap is full. Cannot insert more elements."); return; } heap[size] = value; size++; heapifyUp(size - 1); } // Function to extract the maximum element from the heap public int extractMax() { if (size == 0) { System.out.println("Heap is empty. Cannot extract maximum element."); return -1; } // store th root element int max = heap[0]; //Replace the root with the last elements heap[0] = heap[size - 1]; size--; heapifyDown(0); return max; } //print the elements of the heap public void printHeap() { System.out.print("Heap elements: "); for (int i = 0; i < size; i++) { System.out.print(heap[i] + " "); } System.out.println(); } public static void main(String[] args) { MaxHeap heap = new MaxHeap(10); heap.insert(35); heap.insert(33); heap.insert(42); heap.insert(10); heap.insert(14); heap.insert(19); heap.insert(27); heap.insert(44); heap.insert(26); heap.insert(31); heap.printHeap(); int max = heap.extractMax(); System.out.println("Maximum element: " + max); } }
输出
Heap elements: 44 42 35 33 31 19 27 10 26 14 Maximum element: 44
# Python code for for Max Heap construction Algorithm class MaxHeap: def __init__(self): self.heap = [] def parent(self, i): return (i - 1) // 2 def left_child(self, i): return 2 * i + 1 def right_child(self, i): return 2 * i + 2 #Function to swap two elements in the heap def swap(self, i, j): self.heap[i], self.heap[j] = self.heap[j], self.heap[i] # Function to heapify a subtree rooted at index i def heapify_down(self, i): left = self.left_child(i) right = self.right_child(i) largest = i #Check if the left child is larger than the root if left < len(self.heap) and self.heap[left] >self.heap[largest]: largest = left # Check if the right child is larger than the largest so far if right < len(self.heap) and self.heap[right] > self.heap[largest]: largest = right # If the largest is not the root, swap the root with the largest if largest != i: self.swap(i, largest) self.heapify_down(largest) def heapify_up(self, i): while i > 0 and self.heap[i] > self.heap[self.parent(i)]: parent = self.parent(i) self.swap(i, parent) i = parent # Insert the new element at the end def insert(self, value): self.heap.append(value) # Fix the heap property if it is violated self.heapify_up(len(self.heap) - 1) # Function to extract the maximum element from the heap def extract_max(self): if len(self.heap) == 0: print("Heap is empty. Cannot extract maximum element.") return None max_value = self.heap[0] self.heap[0] = self.heap[-1] self.heap.pop() self.heapify_down(0) return max_value # Function to print the elements of the heap def print_heap(self): print("Heap elements:", end=" ") for value in self.heap: print(value, end=" ") print() # Example usage of the heap heap = MaxHeap() heap.insert(35) heap.insert(33) heap.insert(42) heap.insert(10) heap.insert(14) heap.insert(19) heap.insert(27) heap.insert(44) heap.insert(26) heap.insert(31) heap.print_heap() max_value = heap.extract_max() print("Maximum element:", max_value)
输出
Heap elements: 44 42 35 33 31 19 27 10 26 14 Maximum element: 44s
最大堆删除算法
让我们推导出一个从最大堆中删除的算法。最大(或最小)堆中的删除总是发生在根节点,以移除最大(或最小)值。
Step 1 − Remove root node. Step 2 − Move the last element of last level to root. Step 3 − Compare the value of this child node with its parent. Step 4 − If value of parent is less than child, then swap them. Step 5 − Repeat step 3 & 4 until Heap property holds.
示例
//C code for Max Heap Deletion Algorithm #include <stdio.h> #include <stdlib.h> // Structure to represent a heap typedef struct { int* array; // Array to store heap elements int capacity; // Maximum capacity of the heap int size; // Current size of the heap } Heap; // create a new heap Heap* createHeap(int capacity) { Heap* heap = (Heap*)malloc(sizeof(Heap)); heap->array = (int*)malloc(capacity * sizeof(int)); heap->capacity = capacity; heap->size = 0; return heap; } // swap two elements in the heap void swap(int* a, int* b) { int temp = *a; *a = *b; *b = temp; } // Heapify a subtree rooted at index i void heapify(Heap* heap, int i) { int largest = i; int left = 2 * i + 1; int right = 2 * i + 2; // Check if the left child is larger than the root if (left < heap->size && heap->array[left] > heap->array[largest]) largest = left; // Check if the right child is larger than the largest so far if (right < heap->size && heap->array[right] > heap->array[largest]) largest = right; // If the largest is not the root, swap the root with the largest if (largest != i) { swap(&heap->array[i], &heap->array[largest]); heapify(heap, largest); } } // Function to insert a new element into the heap void insert(Heap* heap, int value) { if (heap->size == heap->capacity) { printf("Heap is full. Cannot insert more elements.\n"); return; } // Insert the new element at the end int i = heap->size++; heap->array[i] = value; // Fix the heap property if it is violated while (i != 0 && heap->array[(i - 1) / 2] < heap->array[i]) { swap(&heap->array[i], &heap->array[(i - 1) / 2]); i = (i - 1) / 2; } } // delete the maximum element from the heap int deleteMax(Heap* heap) { if (heap->size == 0) { printf("Heap is empty. Cannot extract maximum element.\n"); return -1; } // Store the root element int max = heap->array[0]; // Replace the root with the last element heap->array[0] = heap->array[heap->size - 1]; heap->size--; // Heapify the root heapify(heap, 0); return max; } // print the elements of the heap void printHeap(Heap* heap) { printf("Heap elements: "); for (int i = 0; i < heap->size; i++) { printf("%d ", heap->array[i]); } printf("\n"); } // Deallocate memory occupied by the heap void destroyHeap(Heap* heap) { free(heap->array); free(heap); } // Example usage of the heap int main() { Heap* heap = createHeap(10); insert(heap, 35); insert(heap, 33); insert(heap, 42); insert(heap, 10); insert(heap, 14); insert(heap, 19); insert(heap, 27); insert(heap, 44); insert(heap, 26); insert(heap, 31); printHeap(heap); // Deleting the maximum element in the heap int max = deleteMax(heap); printf("Maximum element: %d\n", max); printHeap(heap); destroyHeap(heap); return 0; }
输出
Heap elements: 44 42 35 33 31 19 27 10 26 14 Maximum element: 44 Heap elements: 42 33 35 26 31 19 27 10 14
//C++ code for Max Heap Deletion Algorithm #include <iostream> // Structure to represent a heap struct Heap { int* array; // Array to store heap elements int capacity; // Maximum capacity of the heap int size; // Current size of the heap }; // Create a new heap Heap* createHeap(int capacity) { Heap* heap = new Heap; heap->array = new int[capacity]; heap->capacity = capacity; heap->size = 0; return heap; } // Swap two elements in the heap void swap(int& a, int& b) { int temp = a; a = b; b = temp; } // Heapify a subtree rooted at index i void heapify(Heap* heap, int i) { int largest = i; int left = 2 * i + 1; int right = 2 * i + 2; // Check if the left child is larger than the root if (left < heap->size && heap->array[left] > heap->array[largest]) largest = left; // Check if the right child is larger than the largest so far if (right < heap->size && heap->array[right] > heap->array[largest]) largest = right; // If the largest is not the root, swap the root with the largest if (largest != i) { swap(heap->array[i], heap->array[largest]); heapify(heap, largest); } } // Function to insert a new element into the heap void insert(Heap* heap, int value) { if (heap->size == heap->capacity) { std::cout << "Heap is full. Cannot insert more elements." << std::endl; return; } // Insert the new element at the end int i = heap->size++; heap->array[i] = value; // Fix the heap property if it is violated while (i != 0 && heap->array[(i - 1) / 2] < heap->array[i]) { swap(heap->array[i], heap->array[(i - 1) / 2]); i = (i - 1) / 2; } } // Function to delete the maximum element from the heap int deleteMax(Heap* heap) { if (heap->size == 0) { std::cout << "Heap is empty. Cannot extract maximum element." << std::endl; return -1; } // Store the root element int max = heap->array[0]; // Replace the root with the last element heap->array[0] = heap->array[heap->size - 1]; heap->size--; // Heapify the root heapify(heap, 0); return max; } // Function to print the elements of the heap void printHeap(Heap* heap) { std::cout << "Heap elements: "; for (int i = 0; i < heap->size; i++) { std::cout << heap->array[i] << " "; } std::cout << std::endl; } // Function to deallocate memory occupied by the heap void destroyHeap(Heap* heap) { delete[] heap->array; delete heap; } // Example usage of the heap int main() { Heap* heap = createHeap(10); insert(heap, 35); insert(heap, 33); insert(heap, 42); insert(heap, 10); insert(heap, 14); insert(heap, 19); insert(heap, 27); insert(heap, 44); insert(heap, 26); insert(heap, 31); printHeap(heap); int max = deleteMax(heap); std::cout << "Maximum element: " << max << std::endl; printHeap(heap); destroyHeap(heap); return 0; }
输出
Heap elements: 44 42 35 33 31 19 27 10 26 14 Maximum element: 44 Heap elements: 42 33 35 26 31 19 27 10 14
// Java code for for Max Heap Deletion Algorithm // Structure to represent a heap class Heap { private int[] array; // Array to store heap elements private int capacity; // Maximum capacity of the heap private int size; // Current size of the heap // To create a new heap public Heap(int capacity) { this.array = new int[capacity]; this.capacity = capacity; this.size = 0; } // Swap two elements in the heap private void swap(int a, int b) { int temp = array[a]; array[a] = array[b]; array[b] = temp; } // Heapify a subtree rooted at index i private void heapify(int i) { int largest = i; int left = 2 * i + 1; int right = 2 * i + 2; // Check if the left child is larger than the root if (left < size && array[left] > array[largest]) largest = left; // Check if the right child is larger than the largest so far if (right < size && array[right] > array[largest]) largest = right; // If the largest is not the root, swap the root with the largest if (largest != i) { swap(i, largest); heapify(largest); } } // Insert a new element into the heap public void insert(int value) { if (size == capacity) { System.out.println("Heap is full. Cannot insert more elements."); return; } // Insert the new element at the end int i = size++; array[i] = value; // Fix the heap property if it is violated while (i != 0 && array[(i - 1) / 2] < array[i]) { swap(i, (i - 1) / 2); i = (i - 1) / 2; } } // Delete the maximum element from the heap public int deleteMax() { if (size == 0) { System.out.println("Heap is empty. Cannot extract maximum element."); return -1; } // Store the root element int max = array[0]; // Replace the root with the last element array[0] = array[size - 1]; size--; // Heapify the root heapify(0); return max; } // Print the elements of the heap public void printHeap() { System.out.print("Heap elements: "); for (int i = 0; i < size; i++) { System.out.print(array[i] + " "); } System.out.println(); } // Deallocate memory occupied by the heap public void destroyHeap() { array = null; size = 0; } } //Inserting the elements public class Main { public static void main(String[] args) { Heap heap = new Heap(10); heap.insert(35); heap.insert(33); heap.insert(42); heap.insert(10); heap.insert(14); heap.insert(19); heap.insert(27); heap.insert(44); heap.insert(26); heap.insert(31); heap.printHeap(); int max = heap.deleteMax(); System.out.println("Maximum element: " + max); //Printing the heap elements after deletion of max element heap.printHeap(); heap.destroyHeap(); } }
输出
Heap elements: 44 42 35 33 31 19 27 10 26 14 Maximum element: 44 Heap elements: 42 33 35 26 31 19 27 10 14
#Python code for Max Heap Deletion Algorithm class Heap: def __init__(self, capacity): self.array = [0] * capacity #array to store heap elements self.capacity = capacity #maximum capacity of the heap self.size = 0 #Current size of the heap # swap two elements in the heap def swap(self, a, b): self.array[a], self.array[b] = self.array[b], self.array[a] # Heapify a subtree rooted at index i def heapify(self, i): largest = i left = 2 * i + 1 right = 2 * i + 2 # Check if the left child is larger than the root if left < self.size and self.array[left] > self.array[largest]: largest = left # Check if the right child is larger than the largest so far if right < self.size and self.array[right] > self.array[largest]: largest = right # If the largest is not the root, swap the root with the largest if largest != i: self.swap(i, largest) self.heapify(largest) # insert a new element into the heap def insert(self, value): if self.size == self.capacity: print("Heap is full. Cannot insert more elements.") return # Insert the new element at the end i = self.size self.size += 1 self.array[i] = value # Fix the heap property if it is violated while i != 0 and self.array[(i - 1) // 2] < self.array[i]: self.swap(i, (i - 1) // 2) i = (i - 1) // 2 # delete the maximum element from the heap def deleteMax(self): if self.size == 0: print("Heap is empty. Cannot extract maximum element.") return -1 # store the root element max_value = self.array[0] # Replace the root with the last element self.array[0] = self.array[self.size - 1] self.size -= 1 # Heapify the root self.heapify(0) return max_value # print the elements of the heap def printHeap(self): print("Heap elements:", end=" ") for i in range(self.size): print(self.array[i], end=" ") print() # deallocate memory occupied by the heap def destroyHeap(self): self.array = [] self.size = 0 # Example usage of the heap heap = Heap(10) heap.insert(35) heap.insert(33) heap.insert(42) heap.insert(10) heap.insert(14) heap.insert(19) heap.insert(27) heap.insert(44) heap.insert(26) heap.insert(31) heap.printHeap() max_value = heap.deleteMax() print("Maximum element:", max_value) heap.printHeap() heap.destroyHeap()
输出
Heap elements: 44 42 35 33 31 19 27 10 26 14 Maximum element: 44 Heap elements: 42 33 35 26 31 19 27 10 14
递归算法
一些计算机编程语言允许模块或函数调用自身。这种技术称为递归。在递归中,函数α要么直接调用自身,要么调用一个函数β,而β又反过来调用原始函数α。函数α称为递归函数。
示例 − 函数调用自身。
int function(int value) { if(value < 1) return; function(value - 1); printf("%d ",value); }
示例 − 一个函数调用另一个函数,而另一个函数又反过来再次调用它。
int function1(int value1) { if(value1 < 1) return; function2(value1 - 1); printf("%d ",value1); } int function2(int value2) { function1(value2); }
特性
递归函数可能会像循环一样无限循环。为了避免递归函数无限运行,递归函数必须具备两个属性:
基本条件 − 必须至少有一个基本条件或条件,使得当满足此条件时,函数停止递归调用自身。
渐进式方法 − 递归调用应该以这样一种方式进行,即每次进行递归调用时,它都更接近基本条件。
实现
许多编程语言使用堆栈来实现递归。通常,每当一个函数(调用方)调用另一个函数(被调用方)或自身作为被调用方时,调用方函数都会将执行控制权转移到被调用方。此转移过程可能还涉及一些数据从调用方传递到被调用方。
这意味着,调用方函数必须暂时挂起其执行,并在执行控制权从被调用方函数返回时恢复。在这里,调用方函数需要从其挂起执行的确切位置开始。它还需要它正在处理的完全相同的数据值。为此,将为调用方函数创建一个激活记录(或堆栈帧)。
此激活记录保存有关局部变量、形式参数、返回地址以及传递给调用方函数的所有信息的信息。
递归分析
有人可能会争论为什么要使用递归,因为相同的任务可以用迭代来完成。第一个原因是,递归使程序更易读,并且由于最新的增强型 CPU 系统,递归比迭代更有效。
时间复杂度
在迭代的情况下,我们使用迭代次数来计算时间复杂度。同样,在递归的情况下,假设所有内容都是常数,我们尝试找出进行递归调用的次数。对函数的调用为 Ο(1),因此递归调用次数为 (n) 使递归函数为 Ο(n)。
空间复杂度
空间复杂度计算为模块执行需要多少额外空间。在迭代的情况下,编译器几乎不需要任何额外的空间。编译器会不断更新迭代中使用的变量的值。但在递归的情况下,系统需要在每次进行递归调用时存储激活记录。因此,认为递归函数的空间复杂度可能会高于具有迭代的函数的空间复杂度。
示例
// C program for Recursion Data Structure #include <stdio.h> int factorial(int n) { // Base case: factorial of 0 is 1 if (n == 0) return 1; // Recursive case: multiply n with factorial of (n-1) return n * factorial(n - 1); } int main() { // case 1 int number = 6; printf("Number is: %d\n" , 6); //case 2 if (number < 0) { printf("Error: Factorial is undefined for negative numbers.\n"); return 1; } int result = factorial(number); //print the output printf("Factorial of %d is: %d\n", number, result); return 0; }
输出
Number is: 6 Factorial of 6 is: 720
// CPP program for Recursion Data Structure #include <iostream> int factorial(int n) { // Base case: factorial of 0 is 1 if (n == 0) return 1; // Recursive case: multiply n with factorial of (n-1) return n * factorial(n - 1); } int main() { // case 1 int number = 6; std::cout<<"Number is: "<<number<<"\n"; //case 2 if (number < 0) { std::cout << "Error: Factorial is undefined for negative numbers.\n"; return 1; } int result = factorial(number); //print the output std::cout << "Factorial of " << number << " is: " << result << std::endl; return 0; }
输出
Number is: 6 Factorial of 6 is: 720
// Java program for Recursion Data Structure import java.util.Scanner; public class Main { public static int factorial(int n) { // Base case: factorial of 0 is 1 if (n == 0) return 1; // Recursive case: multiply n with factorial of (n-1) return n * factorial(n - 1); } public static void main(String[] args) { //Case 1 int number = 6; System.out.println("Number is: " + number); //Case 2 if (number < 0) { System.out.println("Error: Factorial is undefined for negative numbers."); System.exit(1); } int result = factorial(number); //print the output System.out.println("Factorial of " + number + " is: " + result); } }
输出
Number is: 6 Factorial of 6 is: 720
# Python program for Recursion Data Structure def factorial(n): #Base Case: factorial of 0 is 1 if n == 0: return 1 # Recursive case: multiply n with factorial of (n-1) return n * factorial(n - 1) #Case 1: number = 6; print("Number is: ", number); #Case 2: if number < 0: print("Error: Factorial is undefined for negative numbers.") else: result = factorial(number) # print the output print("Factorial of", number, "is: ", result)
输出
Number is: 6 Factorial of 6 is: 720
汉诺塔问题使用递归
汉诺塔问题是一个数学谜题,它包含三个塔(桩)和多个环,如下图所示:
这些环大小不同,并且按升序堆叠,即较小的环位于较大的环之上。还有其他版本的谜题,其中圆盘的数量增加,但塔的数量保持不变。
规则
任务是将所有圆盘移动到另一个塔,而不会违反排列顺序。汉诺塔问题需要遵循以下规则:
- 在任何给定时间,只能在一个塔之间移动一个圆盘。
- 只能移除“顶部”圆盘。
- 较大的圆盘不能放在较小的圆盘上。
以下是使用三个圆盘解决汉诺塔问题的动画演示。
具有 n 个圆盘的汉诺塔问题可以在最少 2n−1 步内解决。此演示表明,具有 3 个圆盘的谜题已执行 23 - 1 = 7 步。
算法
要为汉诺塔编写算法,首先我们需要学习如何使用较少数量的圆盘(例如 → 1 或 2)来解决此问题。我们用名称标记三个塔,源、目标和辅助(仅用于帮助移动圆盘)。如果我们只有一个圆盘,则可以轻松地将其从源桩移动到目标桩。
如果我们有 2 个圆盘:
- 首先,我们将较小的(顶部)圆盘移动到辅助桩。
- 然后,我们将较大的(底部)圆盘移动到目标桩。
- 最后,我们将较小的圆盘从辅助桩移动到目标桩。
因此,现在我们可以为具有两个以上圆盘的汉诺塔设计算法了。我们将圆盘堆栈分成两部分。最大的圆盘(第 n 个圆盘)在一部分,所有其他 (n-1) 个圆盘在第二部分。
我们的最终目标是将圆盘 n 从源移动到目标,然后将所有其他 (n1) 个圆盘放在它上面。我们可以想象以递归的方式对所有给定的圆盘集应用相同的操作。
需要遵循的步骤如下:
Step 1 − Move n-1 disks fromsource
toaux
Step 2 − Move nth disk fromsource
todest
Step 3 − Move n-1 disks fromaux
todest
汉诺塔的递归算法可以如下驱动:
START Procedure Hanoi(disk, source, dest, aux) IF disk == 1, THEN move disk from source to dest ELSE Hanoi(disk - 1, source, aux, dest) // Step 1 move disk from source to dest // Step 2 Hanoi(disk - 1, aux, dest, source) // Step 3 END IF END Procedure STOP
示例
#include <stdio.h> #include <stdbool.h> #define MAX 10 int list[MAX] = {1,8,4,6,0,3,5,2,7,9}; void display(){ int i; printf("["); // navigate through all items for(i = 0; i < MAX; i++) { printf("%d ",list[i]); } printf("]\n"); } void bubbleSort() { int temp; int i,j; bool swapped = false; // loop through all numbers for(i = 0; i < MAX-1; i++) { swapped = false; // loop through numbers falling ahead for(j = 0; j < MAX-1-i; j++) { printf("Items compared: [ %d, %d ] ", list[j],list[j+1]); // check if next number is lesser than current no // swap the numbers. // (Bubble up the highest number) if(list[j] > list[j+1]) { temp = list[j]; list[j] = list[j+1]; list[j+1] = temp; swapped = true; printf(" => swapped [%d, %d]\n",list[j],list[j+1]); } else { printf(" => not swapped\n"); } } // if no number was swapped that means // array is sorted now, break the loop. if(!swapped) { break; } printf("Iteration %d#: ",(i+1)); display(); } } int main() { printf("Input Array: "); display(); printf("\n"); bubbleSort(); printf("\nOutput Array: "); display(); }
输出
Input Array: [1 8 4 6 0 3 5 2 7 9 ] Items compared: [ 1, 8 ] => not swapped Items compared: [ 8, 4 ] => swapped [4, 8] Items compared: [ 8, 6 ] => swapped [6, 8] Items compared: [ 8, 0 ] => swapped [0, 8] Items compared: [ 8, 3 ] => swapped [3, 8] Items compared: [ 8, 5 ] => swapped [5, 8] Items compared: [ 8, 2 ] => swapped [2, 8] Items compared: [ 8, 7 ] => swapped [7, 8] Items compared: [ 8, 9 ] => not swapped Iteration 1#: [1 4 6 0 3 5 2 7 8 9 ] Items compared: [ 1, 4 ] => not swapped Items compared: [ 4, 6 ] => not swapped Items compared: [ 6, 0 ] => swapped [0, 6] Items compared: [ 6, 3 ] => swapped [3, 6] Items compared: [ 6, 5 ] => swapped [5, 6] Items compared: [ 6, 2 ] => swapped [2, 6] Items compared: [ 6, 7 ] => not swapped Items compared: [ 7, 8 ] => not swapped Iteration 2#: [1 4 0 3 5 2 6 7 8 9 ] Items compared: [ 1, 4 ] => not swapped Items compared: [ 4, 0 ] => swapped [0, 4] Items compared: [ 4, 3 ] => swapped [3, 4] Items compared: [ 4, 5 ] => not swapped Items compared: [ 5, 2 ] => swapped [2, 5] Items compared: [ 5, 6 ] => not swapped Items compared: [ 6, 7 ] => not swapped Iteration 3#: [1 0 3 4 2 5 6 7 8 9 ] Items compared: [ 1, 0 ] => swapped [0, 1] Items compared: [ 1, 3 ] => not swapped Items compared: [ 3, 4 ] => not swapped Items compared: [ 4, 2 ] => swapped [2, 4] Items compared: [ 4, 5 ] => not swapped Items compared: [ 5, 6 ] => not swapped Iteration 4#: [0 1 3 2 4 5 6 7 8 9 ] Items compared: [ 0, 1 ] => not swapped Items compared: [ 1, 3 ] => not swapped Items compared: [ 3, 2 ] => swapped [2, 3] Items compared: [ 3, 4 ] => not swapped Items compared: [ 4, 5 ] => not swapped Iteration 5#: [0 1 2 3 4 5 6 7 8 9 ] Items compared: [ 0, 1 ] => not swapped Items compared: [ 1, 2 ] => not swapped Items compared: [ 2, 3 ] => not swapped Items compared: [ 3, 4 ] => not swapped Output Array: [0 1 2 3 4 5 6 7 8 9 ]
// C++ Code for Tower of Hanoi #include <iostream> #include <array> #include <algorithm> const int MAX = 10; std::array<int, MAX> list = {1, 8, 4, 6, 0, 3, 5, 2, 7, 9}; void display() { std::cout << "["; // navigate through all items for (int i = 0; i < MAX; i++) { std::cout << list[i] << " "; } std::cout << "]\n"; } void bubbleSort() { int temp; bool swapped = false; // loop through all numbers for (int i = 0; i < MAX - 1; i++) { swapped = false; // loop through numbers falling ahead for (int j = 0; j < MAX - 1 - i; j++) { std::cout << "Items compared: [" << list[j] << ", " << list[j+1] << "] "; // check if next number is lesser than current no // swap the numbers. // (Bubble up the highest number) if (list[j] > list[j+1]) { std::swap(list[j], list[j+1]); swapped = true; std::cout << "=> swapped [" << list[j] << ", " << list[j+1] << "]\n"; } else { std::cout << "=> not swapped\n"; } } // if no number was swapped that means // array is sorted now, break the loop. if (!swapped) { break; } std::cout << "Iteration " << (i+1) << "#: "; display(); } } int main() { std::cout << "Input Array: "; display(); std::cout << "\n"; bubbleSort(); std::cout << "\nOutput Array: "; display(); return 0; }
输出
Input Array: [1 8 4 6 0 3 5 2 7 9 ] Items compared: [1, 8] => not swapped Items compared: [8, 4] => swapped [4, 8] Items compared: [8, 6] => swapped [6, 8] Items compared: [8, 0] => swapped [0, 8] Items compared: [8, 3] => swapped [3, 8] Items compared: [8, 5] => swapped [5, 8] Items compared: [8, 2] => swapped [2, 8] Items compared: [8, 7] => swapped [7, 8] Items compared: [8, 9] => not swapped Iteration 1#: [1 4 6 0 3 5 2 7 8 9 ] Items compared: [1, 4] => not swapped Items compared: [4, 6] => not swapped Items compared: [6, 0] => swapped [0, 6] Items compared: [6, 3] => swapped [3, 6] Items compared: [6, 5] => swapped [5, 6] Items compared: [6, 2] => swapped [2, 6] Items compared: [6, 7] => not swapped Items compared: [7, 8] => not swapped Iteration 2#: [1 4 0 3 5 2 6 7 8 9 ] Items compared: [1, 4] => not swapped Items compared: [4, 0] => swapped [0, 4] Items compared: [4, 3] => swapped [3, 4] Items compared: [4, 5] => not swapped Items compared: [5, 2] => swapped [2, 5] Items compared: [5, 6] => not swapped Items compared: [6, 7] => not swapped Iteration 3#: [1 0 3 4 2 5 6 7 8 9 ] Items compared: [1, 0] => swapped [0, 1] Items compared: [1, 3] => not swapped Items compared: [3, 4] => not swapped Items compared: [4, 2] => swapped [2, 4] Items compared: [4, 5] => not swapped Items compared: [5, 6] => not swapped Iteration 4#: [0 1 3 2 4 5 6 7 8 9 ] Items compared: [0, 1] => not swapped Items compared: [1, 3] => not swapped Items compared: [3, 2] => swapped [2, 3] Items compared: [3, 4] => not swapped Items compared: [4, 5] => not swapped Iteration 5#: [0 1 2 3 4 5 6 7 8 9 ] Items compared: [0, 1] => not swapped Items compared: [1, 2] => not swapped Items compared: [2, 3] => not swapped Items compared: [3, 4] => not swapped Output Array: [0 1 2 3 4 5 6 7 8 9 ]
//Java Code for Tower of Hanoi import java.util.Arrays; public class BubbleSort { public static final int MAX = 10; public static int[] list = {1, 8, 4, 6, 0, 3, 5, 2, 7, 9}; public static void display() { System.out.print("["); // navigate through all items for (int i = 0; i < MAX; i++) { System.out.print(list[i] + " "); } System.out.println("]"); } public static void bubbleSort() { boolean swapped; // loop through all numbers for (int i = 0; i < MAX - 1; i++) { swapped = false; // loop through numbers falling ahead for (int j = 0; j < MAX - 1 - i; j++) { System.out.print("Items compared: [" + list[j] + ", " + list[j + 1] + "] "); // check if next number is lesser than current no // swap the numbers. // (Bubble up the highest number) if (list[j] > list[j + 1]) { int temp = list[j]; list[j] = list[j + 1]; list[j + 1] = temp; swapped = true; System.out.println("=> swapped [" + list[j] + ", " + list[j + 1] + "]"); } else { System.out.println("=> not swapped"); } } // if no number was swapped that means // array is sorted now, break the loop. if (!swapped) { break; } System.out.print("Iteration " + (i + 1) + "#: "); display(); } } public static void main(String[] args) { System.out.print("Input Array: "); display(); System.out.println(); bubbleSort(); System.out.print("\nOutput Array: "); display(); } }
输出
Input Array: [1 8 4 6 0 3 5 2 7 9 ] Items compared: [1, 8] => not swapped Items compared: [8, 4] => swapped [4, 8] Items compared: [8, 6] => swapped [6, 8] Items compared: [8, 0] => swapped [0, 8] Items compared: [8, 3] => swapped [3, 8] Items compared: [8, 5] => swapped [5, 8] Items compared: [8, 2] => swapped [2, 8] Items compared: [8, 7] => swapped [7, 8] Items compared: [8, 9] => not swapped Iteration 1#: [1 4 6 0 3 5 2 7 8 9 ] Items compared: [1, 4] => not swapped Items compared: [4, 6] => not swapped Items compared: [6, 0] => swapped [0, 6] Items compared: [6, 3] => swapped [3, 6] Items compared: [6, 5] => swapped [5, 6] Items compared: [6, 2] => swapped [2, 6] Items compared: [6, 7] => not swapped Items compared: [7, 8] => not swapped Iteration 2#: [1 4 0 3 5 2 6 7 8 9 ] Items compared: [1, 4] => not swapped Items compared: [4, 0] => swapped [0, 4] Items compared: [4, 3] => swapped [3, 4] Items compared: [4, 5] => not swapped Items compared: [5, 2] => swapped [2, 5] Items compared: [5, 6] => not swapped Items compared: [6, 7] => not swapped Iteration 3#: [1 0 3 4 2 5 6 7 8 9 ] Items compared: [1, 0] => swapped [0, 1] Items compared: [1, 3] => not swapped Items compared: [3, 4] => not swapped Items compared: [4, 2] => swapped [2, 4] Items compared: [4, 5] => not swapped Items compared: [5, 6] => not swapped Iteration 4#: [0 1 3 2 4 5 6 7 8 9 ] Items compared: [0, 1] => not swapped Items compared: [1, 3] => not swapped Items compared: [3, 2] => swapped [2, 3] Items compared: [3, 4] => not swapped Items compared: [4, 5] => not swapped Iteration 5#: [0 1 2 3 4 5 6 7 8 9 ] Items compared: [0, 1] => not swapped Items compared: [1, 2] => not swapped Items compared: [2, 3] => not swapped Items compared: [3, 4] => not swapped Output Array: [0 1 2 3 4 5 6 7 8 9 ]
#Python Code for Tower of Hanoi MAX = 10 list = [1, 8, 4, 6, 0, 3, 5, 2, 7, 9] def display(): print("[", end="") # navigate through all items for i in range(MAX): print(list[i], end=" ") print("]") def bubbleSort(): swapped = False # loop through all numbers for i in range(MAX - 1): swapped = False # loop through numbers falling ahead for j in range(MAX - 1 - i): print("Items compared: [", list[j], ", ", list[j + 1], "] ", end="") # check if next number is lesser than the current number # swap the numbers. # (Bubble up the highest number) if list[j] > list[j + 1]: temp = list[j] list[j] = list[j + 1] list[j + 1] = temp swapped = True print("=> swapped [", list[j], ", ", list[j + 1], "]") else: print("=> not swapped") # if no number was swapped, the array is sorted now, break the loop if not swapped: break print("Iteration", (i + 1), "#: ", end="") display() print("Input Array: ", end="") display() print() bubbleSort() print("\nOutput Array: ", end="") display()
输出
Input Array: [1 8 4 6 0 3 5 2 7 9 ] Items compared: [ 1 , 8 ] => not swapped Items compared: [ 8 , 4 ] => swapped [ 4 , 8 ] Items compared: [ 8 , 6 ] => swapped [ 6 , 8 ] Items compared: [ 8 , 0 ] => swapped [ 0 , 8 ] Items compared: [ 8 , 3 ] => swapped [ 3 , 8 ] Items compared: [ 8 , 5 ] => swapped [ 5 , 8 ] Items compared: [ 8 , 2 ] => swapped [ 2 , 8 ] Items compared: [ 8 , 7 ] => swapped [ 7 , 8 ] Items compared: [ 8 , 9 ] => not swapped Iteration 1 #: [1 4 6 0 3 5 2 7 8 9 ] Items compared: [ 1 , 4 ] => not swapped Items compared: [ 4 , 6 ] => not swapped Items compared: [ 6 , 0 ] => swapped [ 0 , 6 ] Items compared: [ 6 , 3 ] => swapped [ 3 , 6 ] Items compared: [ 6 , 5 ] => swapped [ 5 , 6 ] Items compared: [ 6 , 2 ] => swapped [ 2 , 6 ] Items compared: [ 6 , 7 ] => not swapped Items compared: [ 7 , 8 ] => not swapped Iteration 2 #: [1 4 0 3 5 2 6 7 8 9 ] Items compared: [ 1 , 4 ] => not swapped Items compared: [ 4 , 0 ] => swapped [ 0 , 4 ] Items compared: [ 4 , 3 ] => swapped [ 3 , 4 ] Items compared: [ 4 , 5 ] => not swapped Items compared: [ 5 , 2 ] => swapped [ 2 , 5 ] Items compared: [ 5 , 6 ] => not swapped Items compared: [ 6 , 7 ] => not swapped Iteration 3 #: [1 0 3 4 2 5 6 7 8 9 ] Items compared: [ 1 , 0 ] => swapped [ 0 , 1 ] Items compared: [ 1 , 3 ] => not swapped Items compared: [ 3 , 4 ] => not swapped Items compared: [ 4 , 2 ] => swapped [ 2 , 4 ] Items compared: [ 4 , 5 ] => not swapped Items compared: [ 5 , 6 ] => not swapped Iteration 4 #: [0 1 3 2 4 5 6 7 8 9 ] Items compared: [ 0 , 1 ] => not swapped Items compared: [ 1 , 3 ] => not swapped Items compared: [ 3 , 2 ] => swapped [ 2 , 3 ] Items compared: [ 3 , 4 ] => not swapped Items compared: [ 4 , 5 ] => not swapped Iteration 5 #: [0 1 2 3 4 5 6 7 8 9 ] Items compared: [ 0 , 1 ] => not swapped Items compared: [ 1 , 2 ] => not swapped Items compared: [ 2 , 3 ] => not swapped Items compared: [ 3 , 4 ] => not swapped Output Array: [0 1 2 3 4 5 6 7 8 9 ]
使用递归的斐波那契数列
斐波那契数列通过将前两个数字相加来生成后续数字。斐波那契数列从两个数字开始 − F0 & F1。F0 & F1 的初始值可以分别取 0、1 或 1、1。
斐波那契数列满足以下条件:
Fn = Fn-1 + Fn-2
因此,斐波那契数列可能如下所示:
F8 = 0 1 1 2 3 5 8 13
或者,这样:
F8 = 1 1 2 3 5 8 13 21
为了说明目的,F8 的斐波那契数列显示为:
斐波那契迭代算法
首先,我们尝试为斐波那契数列起草迭代算法。
Procedure Fibonacci(n) declare f0, f1, fib, loop set f0 to 0 set f1 to 1 <b>display f0, f1</b> for loop ← 1 to n fib ← f0 + f1 f0 ← f1 f1 ← fib <b>display fib</b> end for end procedure
斐波那契递归算法
让我们学习如何创建斐波那契数列的递归算法。递归的基本条件。
START Procedure Fibonacci(n) declare f0, f1, fib, loop set f0 to 0 set f1 to 1 display f0, f1 for loop ← 1 to n fib ← f0 + f1 f0 ← f1 f1 ← fib display fib end for END
示例
#include <stdio.h> int factorial(int n) { //base case if(n == 0) { return 1; } else { return n * factorial(n-1); } } int fibbonacci(int n) { if(n == 0){ return 0; } else if(n == 1) { return 1; } else { return (fibbonacci(n-1) + fibbonacci(n-2)); } } int main() { int n = 5; int i; printf("Factorial of %d: %d\n" , n , factorial(n)); printf("Fibbonacci of %d: " , n); for(i = 0;i<n;i++) { printf("%d ",fibbonacci(i)); } }
输出
Factorial of 5: 120 Fibbonacci of 5: 0 1 1 2 3
// C++ Code for Fibonacci series #include <iostream> int factorial(int n) { //base case if(n == 0) { return 1; } else { return n * factorial(n-1); } } int fibbonacci(int n) { if(n == 0){ return 0; } else if(n == 1) { return 1; } else { return (fibbonacci(n-1) + fibbonacci(n-2)); } } int main() { int n = 5; int i; std::cout << "Factorial of " << n << ": " << factorial(n) << std::endl; std::cout << "Fibbonacci of " << n << ": "; for(i = 0;i<n;i++) { std::cout << fibbonacci(i) << " "; } }
输出
Factorial of 5: 120 Fibbonacci of 5: 0 1 1 2 3
// Java Code for Fibonacci series public class Fibonacci { public static int factorial(int n) { // base case if (n == 0) { return 1; } else { return n * factorial(n - 1); } } public static int fibonacci(int n) { if (n == 0) { return 0; } else if (n == 1) { return 1; } else { return fibonacci(n - 1) + fibonacci(n - 2); } } public static void main(String[] args) { int n = 5; int i; System.out.println("Factorial of " + n + ": " + factorial(n)); System.out.print("Fibonacci of " + n + ": "); for (i = 0; i < n; i++) { System.out.print(fibonacci(i) + " "); } }
输出
Factorial of 5: 120 Fibonacci of 5: 0 1 1 2 3
#Python code for fibonacci Series def factorial(n): # base case if n == 0: return 1 else: return n * factorial(n-1) def fibonacci(n): if n == 0: return 0 elif n == 1: return 1 else: return fibonacci(n-1) + fibonacci(n-2) if __name__ == "__main__": n = 5 print("Factorial of", n, ":", factorial(n)) print("Fibonacci of", n, ": ") for i in range(n): print(fibonacci(i))
输出
Factorial of 5 : 120 Fibonacci of 5 : 0 1 1 2 3