实现二叉排序树的各种算法
二叉排序树
![二叉排序树](https://img.taocdn.com/s3/m/024187bfba1aa8114531d94d.png)
二叉排序树1.二叉排序树定义二叉排序树(Binary Sort Tree)或者是一棵空树;或者是具有下列性质的二叉树:(1)若左子树不空,则左子树上所有结点的值均小于根结点的值;若右子树不空,则右子树上所有结点的值均大于根结点的值。
(2)左右子树也都是二叉排序树,如图6-2所示。
2.二叉排序树的查找过程由其定义可见,二叉排序树的查找过程为:(1)若查找树为空,查找失败。
(2)查找树非空,将给定值key与查找树的根结点关键码比较。
(3)若相等,查找成功,结束查找过程,否则:①当给值key小于根结点关键码,查找将在以左孩子为根的子树上继续进行,转(1)。
②当给值key大于根结点关键码,查找将在以右孩子为根的子树上继续进行,转(1)。
3.二叉排序树插入操作和构造一棵二叉排序树向二叉排序树中插入一个结点的过程:设待插入结点的关键码为key,为将其插入,先要在二叉排序树中进行查找,若查找成功,按二叉排序树定义,该插入结点已存在,不用插入;查找不成功时,则插入之。
因此,新插入结点一定是作为叶子结点添加上去的。
构造一棵二叉排序树则是逐个插入结点的过程。
对于关键码序列为:{63,90,70,55,67,42,98,83,10,45,58},则构造一棵二叉排序树的过程如图6-3所示。
4.二叉排序树删除操作从二叉排序树中删除一个结点之后,要求其仍能保持二叉排序树的特性。
设待删结点为*p(p为指向待删结点的指针),其双亲结点为*f,删除可以分三种情况,如图6-4所示。
(1)*p结点为叶结点,由于删去叶结点后不影响整棵树的特性,所以,只需将被删结点的双亲结点相应指针域改为空指针,如图6-4(a)所示。
(2)*p结点只有右子树或只有左子树,此时,只需将或替换*f结点的*p子树即可,如图6-4(b)、(c)所示。
(3)*p结点既有左子树又有右子树,可按中序遍历保持有序地进行调整,如图6-4(d)、(e)所示。
设删除*p结点前,中序遍历序列为:① P为F的左子女时有:…,Pi子树,P,Pj,S子树,Pk,Sk子树,…,P2,S2子树,P1,S1子树,F,…。
二叉树先序遍历算法
![二叉树先序遍历算法](https://img.taocdn.com/s3/m/c6cb73ef8ad63186bceb19e8b8f67c1cfad6ee68.png)
二叉树先序遍历算法
二叉树先序遍历是一种树的遍历算法,先序遍历过程如下:
1. 先访问根节点;
2. 再访问左子节点;
3. 再访问右子节点;
二叉树先序遍历是一种树状数据结构的深度优先搜索(DFS)算法。
先序遍历对
树状数据结构中的每个节点仅进行一次访问,且访问的次序是从上到下,从左到右的方式。
先序遍历属于深度优先搜索,它以一定的次序访问树或图的每个节点,然后递归访问其子节点,深度优先搜索可以按一定方式去遍历有向图、二叉树等数据结构,对节点都进行一定次序的编号或标签,访问顺序是按从小到大的顺序,从而把BST全部访问一次。
二叉树先序遍历的时间复杂度为O(n),空间复杂度为O(logn),应用范围很广,常用于二叉查找树的构造或查找、求树的高度和深度、树的前中后序遍历等,其中在建立二叉查找树时,往往我们都会使用先序遍历;同时,也可用先序遍历来求二叉树的节点数,计算树的深度等。
因此,二叉树先序遍历是一种基本而又重要的数据结构遍历算法,在许多应用
场景中都可以被朂泛使用,深受各个计算机领域的热捧。
二叉堆和优先队列高效实现堆排序和Dijkstra算法
![二叉堆和优先队列高效实现堆排序和Dijkstra算法](https://img.taocdn.com/s3/m/a4006f54fd4ffe4733687e21af45b307e871f9e6.png)
二叉堆和优先队列高效实现堆排序和Dijkstra算法堆排序和Dijkstra算法是计算机科学中常见且高效的算法。
它们的实现中常用到二叉堆和优先队列的数据结构。
本文将介绍二叉堆和优先队列的概念,以及它们在堆排序和Dijkstra算法中的应用。
一、二叉堆二叉堆是一种特殊的完全二叉树,满足以下两个性质:1. 结构性质:除最后一层外,每一层都是满的,最后一层从左到右填入节点。
2. 堆序性质:对于任意节点i,其父节点值小于等于其子节点的值。
二叉堆有两种类型:大顶堆和小顶堆。
大顶堆中,父节点的值大于等于其子节点;小顶堆中,父节点的值小于等于其子节点。
二叉堆的根节点即堆中的最值。
二、优先队列优先队列是一种可以快速访问和删除最值元素的数据结构。
它支持两个主要操作:1. 插入操作:将元素按照一定的优先级插入队列中。
2. 弹出操作:弹出队列中的最值元素。
优先队列可以用二叉堆实现,其中小顶堆用于实现最小优先队列,大顶堆用于实现最大优先队列。
通过保持堆序性质,我们可以在O(logn)的时间复杂度内完成插入和弹出的操作。
三、堆排序堆排序是一种高效的排序算法,基于二叉堆数据结构。
其主要步骤如下:1. 构建最大堆:将待排序序列构建成一个最大堆。
2. 交换堆顶元素和最后一个元素:将最大堆的堆顶元素与最后一个元素交换,此时最大值被固定在了最后。
3. 调整堆:调整剩余元素构建一个新的最大堆。
4. 重复步骤2和步骤3,直到剩余元素只有一个。
堆排序的时间复杂度为O(nlogn),且具有原地排序的优点,但是不稳定。
四、Dijkstra算法Dijkstra算法是一种解决单源最短路径问题的贪心算法。
其核心思想是利用优先队列选择当前最短路径的顶点来遍历附近的节点,并更新到达这些节点的最短距离。
其主要步骤如下:1. 创建一个距离数组dist,存储源点到每个顶点的最短距离。
初始时,源点到自身的距离为0,其他顶点的距离为无穷大。
2. 将源点插入到优先队列中。
二叉树 遍历种类 算法伪码
![二叉树 遍历种类 算法伪码](https://img.taocdn.com/s3/m/05ce98521fb91a37f111f18583d049649b660e9a.png)
二叉树遍历种类算法伪码二叉树是一种常见的树形数据结构,由节点和边组成,每个节点最多有两个子节点。
二叉树的遍历是指按照某种顺序访问二叉树中的所有节点,包括先序遍历、中序遍历和后序遍历三种常见的遍历方式。
本文将介绍这三种遍历方式的算法伪码及其应用场景。
一、先序遍历(Preorder Traversal)先序遍历是指先访问二叉树的根节点,然后按照先序遍历的方式递归遍历左子树和右子树。
算法伪码如下:1. 如果树为空,返回。
2. 访问当前节点。
3. 递归先序遍历左子树。
4. 递归先序遍历右子树。
先序遍历的应用场景包括:根据二叉树的先序遍历序列重构二叉树、打印二叉树的先序遍历序列等。
二、中序遍历(Inorder Traversal)中序遍历是指先递归遍历左子树,然后访问二叉树的根节点,最后递归遍历右子树。
算法伪码如下:1. 如果树为空,返回。
2. 递归中序遍历左子树。
3. 访问当前节点。
4. 递归中序遍历右子树。
中序遍历的应用场景包括:根据二叉搜索树的中序遍历序列判断是否为合法的二叉搜索树、查找二叉搜索树中的某个节点等。
三、后序遍历(Postorder Traversal)后序遍历是指先递归遍历左子树,然后递归遍历右子树,最后访问二叉树的根节点。
算法伪码如下:1. 如果树为空,返回。
2. 递归后序遍历左子树。
3. 递归后序遍历右子树。
4. 访问当前节点。
后序遍历的应用场景包括:释放二叉树的内存、计算二叉树的高度等。
以上是二叉树的三种常见遍历方式的算法伪码及其应用场景。
下面将介绍一些常见的二叉树遍历问题及其解决方法。
1. 如何判断两个二叉树是否相同?可以使用先序遍历的方式分别遍历两个二叉树,将遍历结果进行比较。
如果两个二叉树的先序遍历序列相同,则它们相同。
2. 如何求解二叉树的深度?可以使用后序遍历的方式遍历二叉树,并记录每个节点的深度。
最后返回最大深度即可。
3. 如何判断一个二叉树是否为平衡二叉树?可以使用后序遍历的方式遍历二叉树,并记录每个节点的左子树高度和右子树高度。
二叉排序树查找的递归算法
![二叉排序树查找的递归算法](https://img.taocdn.com/s3/m/08213f1ba4e9856a561252d380eb6294dd88220b.png)
二叉排序树查找的递归算法介绍二叉排序树(Binary Search Tree),也称二叉查找树、有序二叉树或排序二叉树,是一种常用的数据结构。
它具有以下特点:•每个节点都包含一个键值和对应的数据。
•左子树中的所有节点的键值都小于根节点的键值。
•右子树中的所有节点的键值都大于根节点的键值。
•左右子树也分别是二叉排序树。
二叉排序树支持高效的查找、插入和删除操作,其中查找操作是利用递归实现的。
本文将详细介绍二叉排序树查找的递归算法。
二叉排序树的定义二叉排序树的定义如下:class TreeNode:def __init__(self, key, data):self.key = keyself.data = dataself.left = Noneself.right = Noneclass BinarySearchTree:def __init__(self):self.root = None在二叉排序树中,每个节点都是一个TreeNode对象,包含键值key和对应的数据data。
left和right分别指向左子树和右子树的根节点。
树的根节点由BinarySearchTree对象的root属性表示。
二叉排序树查找的递归算法二叉排序树的查找操作是利用递归实现的,其具体算法如下:1.如果待查找的键值等于当前节点的键值,返回当前节点的数据。
2.如果待查找的键值小于当前节点的键值,递归在左子树中查找。
3.如果待查找的键值大于当前节点的键值,递归在右子树中查找。
4.如果在左子树或右子树中找不到对应的键值,则返回空。
下面是二叉排序树查找的递归算法的代码实现:def search_recursive(node, key):if node is None or node.key == key:return node.dataelif key < node.key:return search_recursive(node.left, key)else:return search_recursive(node.right, key)在上述代码中,node表示当前节点,key表示待查找的键值。
实现二叉排序树的各种算法(2)
![实现二叉排序树的各种算法(2)](https://img.taocdn.com/s3/m/64b04a8da0116c175f0e486e.png)
BiTree S;
S = T;
while(S)
{
if(S -> data < e)
S = S->rchild;
else if(S -> data > e)
S = S->lchild;
else return OK;
}
return ERROR;
S1 -> data = e;S1 -> lchild = NULL;S1 -> rchild = NULL;
S2 = T;
if(S2 == NULL) T = S1;
else while(loop)
{
if(S1->data < S2->data)
if(S2->lchild == NULL)
{
BiTree S1, S3, S4;
S1 = T;
SqQueue S2;
InitQueue(S2);
EnQueue(S2,S1);
while(S2.front != S2.rear)
{
DeQueue(S2,S1);
printf("%d ",S1->data);
S3 = S1->lchild;S4 = S1->rchild;
if(S3) EnQueue(S2,S3);
if(S4) EnQueue(S2,S4);
}
return OK;
}
Status Turn (BiTree T)
S.top = S.base + S.stacksize;
S.stacksize += STACKINCREMENT;
数据结构实验三——二叉树基本操作及运算实验报告
![数据结构实验三——二叉树基本操作及运算实验报告](https://img.taocdn.com/s3/m/d4dbf1882cc58bd63086bd05.png)
《数据结构与数据库》实验报告实验题目二叉树的基本操作及运算一、需要分析问题描述:实现二叉树(包括二叉排序树)的建立,并实现先序、中序、后序和按层次遍历,计算叶子结点数、树的深度、树的宽度,求树的非空子孙结点个数、度为2的结点数目、度为2的结点数目,以及二叉树常用运算。
问题分析:二叉树树型结构是一类重要的非线性数据结构,对它的熟练掌握是学习数据结构的基本要求。
由于二叉树的定义本身就是一种递归定义,所以二叉树的一些基本操作也可采用递归调用的方法。
处理本问题,我觉得应该:1、建立二叉树;2、通过递归方法来遍历(先序、中序和后序)二叉树;3、通过队列应用来实现对二叉树的层次遍历;4、借用递归方法对二叉树进行一些基本操作,如:求叶子数、树的深度宽度等;5、运用广义表对二叉树进行广义表形式的打印。
算法规定:输入形式:为了方便操作,规定二叉树的元素类型都为字符型,允许各种字符类型的输入,没有元素的结点以空格输入表示,并且本实验是以先序顺序输入的。
输出形式:通过先序、中序和后序遍历的方法对树的各字符型元素进行遍历打印,再以广义表形式进行打印。
对二叉树的一些运算结果以整型输出。
程序功能:实现对二叉树的先序、中序和后序遍历,层次遍历。
计算叶子结点数、树的深度、树的宽度,求树的非空子孙结点个数、度为2的结点数目、度为2的结点数目。
对二叉树的某个元素进行查找,对二叉树的某个结点进行删除。
测试数据:输入一:ABC□□DE□G□□F□□□(以□表示空格),查找5,删除E预测结果:先序遍历ABCDEGF中序遍历CBEGDFA后序遍历CGEFDBA层次遍历ABCDEFG广义表打印A(B(C,D(E(,G),F)))叶子数3 深度5 宽度2 非空子孙数6 度为2的数目2 度为1的数目2查找5,成功,查找的元素为E删除E后,以广义表形式打印A(B(C,D(,F)))输入二:ABD□□EH□□□CF□G□□□(以□表示空格),查找10,删除B预测结果:先序遍历ABDEHCFG中序遍历DBHEAGFC后序遍历DHEBGFCA层次遍历ABCDEFHG广义表打印A(B(D,E(H)),C(F(,G)))叶子数3 深度4 宽度3 非空子孙数7 度为2的数目2 度为1的数目3查找10,失败。
二叉树的快速排序、归并排序方法
![二叉树的快速排序、归并排序方法](https://img.taocdn.com/s3/m/7f512e8af021dd36a32d7375a417866fb84ac0fa.png)
二叉树的快速排序、归并排序方法一、快速排序快速排序采用的是分治法策略,其基本思路是先选定一个基准数(一般取第一个元素),将待排序序列抽象成两个子序列:小于基准数的子序列和大于等于基准数的子序列,然后递归地对这两个子序列排序。
1. 递归实现(1)选定基准数题目要求采用第一个元素作为基准数,因此可以直接将其取出。
(2)划分序列接下来需要将待排序序列划分成两个子序列。
我们定义两个指针 i 和 j,从待排序序列的第二个元素和最后一个元素位置开始,分别向左和向右扫描,直到 i 和 j 相遇为止。
在扫描过程中,将小于等于基准数的元素移到左边(即与左侧序列交换),将大于基准数的元素移到右边(即与右侧序列交换)。
当 i=j 时,扫描结束。
(3)递归排序子序列完成划分后,左右两个子序列就确定了下来。
接下来分别对左右两个子序列递归调用快速排序算法即可。
2. 非递归实现上述方法是快速排序的递归实现。
对于大量数据或深度递归的情况,可能会出现栈溢出等问题,因此还可以使用非递归实现。
非递归实现采用的是栈结构,将待排序序列分成若干子序列后,依次将其入栈并标注其位置信息,然后将栈中元素依次出栈并分割、排序,直至栈为空。
二、归并排序归并排序同样采用的是分治思想。
其基本思路是将待排序序列拆分成若干个子序列,直至每个子序列只有一个元素,然后将相邻的子序列两两合并,直至合并成一个有序序列。
1. 递归实现(1)拆分子序列归并排序先将待排序序列进行拆分,具体方法是将序列平分成两个子序列,然后递归地对子序列进行拆分直至每个子序列只剩下一个元素。
(2)合并有序子序列在完成子序列的拆分后,接下来需要将相邻的子序列两两合并为一个有序序列。
我们先定义三个指针 i、j 和 k,分别指向待合并的左侧子序列、右侧子序列和合并后的序列。
在进行合并时,从两个子序列的起始位置开始比较,将两个子序列中较小的元素移动到合并后的序列中。
具体操作如下:- 当左侧子序列的第一个元素小于等于右侧子序列的第一个元素时,将左侧子序列的第一个元素移动到合并后的序列中,并将指针 i 和 k 分别加 1。
设计以先序遍历的顺序建立二叉树的二叉链表存储结构的算法
![设计以先序遍历的顺序建立二叉树的二叉链表存储结构的算法](https://img.taocdn.com/s3/m/301d0929e97101f69e3143323968011ca300f7d6.png)
设计以先序遍历的顺序建立二叉树的二叉链表存储结构的算法一、算法简介二叉树是一种重要的树形结构,它的建立方式有多种,其中一种是按照先序遍历的顺序建立二叉树。
这种方式需要将先序遍历序列和二叉树的存储结构相结合,采用二叉链表存储结构。
具体流程是按照先序遍历序列的顺序依次创建二叉树的各个节点,同时使用二叉链表结构保存每个节点的数据和指针信息。
二、算法实现算法的实现主要包括初始化二叉树、创建节点、建立二叉树等步骤,下面对这些步骤进行详细描述。
1. 初始化二叉树初始化二叉树需要创建一个根节点,同时将根节点的左右指针指向NULL,表示二叉树为空。
2. 创建节点创建节点需要通过输入元素数据来创建,同时节点的左右指针也需要初始化为NULL。
3. 建立二叉树建立二叉树是按照先序遍历序列来实现的,具体流程如下:(1)读入当前节点的元素数据,创建节点,并将其作为当前节点。
(2)判断当前节点的元素数据是否为结束符号(这里结束符号可以指定),如果是,则返回NULL。
(3)递归创建当前节点的左子树,将左子树的根节点赋值给当前节点的左指针。
(4)递归创建当前节点的右子树,将右子树的根节点赋值给当前节点的右指针。
(5)返回当前节点。
三、算法优化虽然上述算法实现简单明了,但它有一个缺点,即无法处理空节点的情况,如果输入的先序遍历序列中存在空节点,那么该算法就无法建立正确的二叉树了。
因此,可以在输入的先序遍历序列中使用一个特殊的符号(如#)表示空节点,在建立节点时,如果遇到该符号,则将该节点的指针设置为NULL即可。
四、算法总结按照先序遍历的顺序建立二叉树是一种基于二叉链表存储结构的建树方式。
它通过递归的方式构建整个二叉树,同时为了处理空节点的情况,还需要对输入的先序遍历序列进行特殊处理。
该算法的效率较高,适用于对先序遍历序列已知的情况下建立二叉树。
算法(平衡二叉树)
![算法(平衡二叉树)](https://img.taocdn.com/s3/m/d5f997f84793daef5ef7ba0d4a7302768e996f0f.png)
算法(平衡⼆叉树)科普⼆叉树⼆叉树⼆叉数是每个节点最多有两个⼦树,或者是空树(n=0),或者是由⼀个根节点及两个互不相交的,分别称为左⼦树和右⼦树的⼆叉树组成满⼆叉树有两个⾮空⼦树(⼆叉树中的每个结点恰好有两个孩⼦结点切所有叶⼦结点都在同⼀层)也就是⼀个结点要么是叶结点,要么是有两个⼦结点的中间结点。
深度为k且含有2^k-1个结点的⼆叉树完全⼆叉树从左到右依次填充从根结点开始,依次从左到右填充树结点。
除最后⼀层外,每⼀层上的所有节点都有两个⼦节点,最后⼀层都是叶⼦节点。
平衡⼆叉树AVL树[3,1,2,5,9,7]⾸先科普下⼆叉排序树⼜称⼆叉查找树,议程⼆叉搜索树⼆叉排序树的规则⽐本⾝⼤放右边,⽐本⾝⼩放左边平衡⼆叉数⾸先是⼀个⼆叉排序树左右两个⼦树的⾼度差不⼤于1下⾯图中是平衡的情况下⾯是不平衡的情况引⼊公式(LL)右旋function toateRight(AvlNode){let node=AvlNode.left;//保存左节点 AvlNode.left=node.right;node.right=AvlNode;}(RR)左旋function roateLeft(AvlNode){let node=AvlNode.right;//保存右⼦节点AvlNode.right=node.left;node.left=AvlNode;return node;}左右旋⼤图判断⼆叉树是不是平衡树⼆叉树任意结点的左右⼦树的深度不超过1深度计算定义⼀个初始化的⼆叉树var nodes = {node: 6,left: {node: 5,left: {node: 4},right: {node: 3}},right: {node: 2,right: {node: 1}}}//计算⾼度const treeDepth = (root) => {if (root == null) {return 0;}let left = treeDepth(root.left)let right = treeDepth(root.right)return 1+(left>right?left:right)}//判断深度const isTree=(root)=>{if (root == null) {return true;}let left=treeDepth(root.left)let right=treeDepth(root.right)let diff=left-right;if (diff > 1 || diff < -1) {return false}return isTree(root.left)&&isTree(root.right) }console.log(isTree(nodes))判断⼆叉数是不是搜索⼆叉树//第⼀种 //中序遍历let last=-Infinity;const isValidBST=(root)=>{if (root == null) {return true;}//先从左节点开始if (isValidBST(root.left)) {if (last < root.node) {last=root.node;return isValidBST(root.right)}}return false}console.log(isValidBST(nodes))//第⼆种const isValidBST = root => {if (root == null) {return true}return dfs(root, -Infinity, Infinity)}const dfs = (root, min, max) => {if (root == null) {return true}if (root.node <= min || root.node >= max) {return false}return dfs(root.left, min, root.node) && dfs(root.right, root.node, max)}console.log(isValidBST(nodes))实现⼀个⼆叉树实现了⼆叉树的添加,删除,查找,排序//⼆叉树结点class TreeNode {constructor(n, left, right){this.n = n;this.left = left;this.right = right;}}//⼆叉树class BinaryTree {constructor(){this.length = 0;this.root = null;this.arr = [];}//添加对外⼊⼝,⾸个参数是数组,要求数组⾥都是数字,如果有不是数字则试图转成数字,如果有任何⼀个⽆法强制转成数字,则本操作⽆效 addNode(){let arr = arguments[0];if(arr.length == 0) return false;return this.judgeData('_addNode', arr)}//删除结点deleteNode(){let arr = arguments[0];if(arr.length == 0) return false;return this.judgeData('_deleteNode', arr)}//传值判断,如果全部正确,则全部加⼊叉树judgeData(func, arr){let flag = false;//任何⼀个⽆法转成数字,都会失败if(arr.every(n => !Number.isNaN(n))){let _this = this;arr.map(n => _this[func](n));flag = true;}return flag;}//添加的真实实现_addNode(n){n = Number(n);let current = this.root;let treeNode = new TreeNode(n, null, null);if(this.root === null){this.root = treeNode;}else {current = this.root;while(current){let parent = current;if(n < current.n){current = current.left;if(current === null){parent.left = treeNode;}}else {current = current.right;if(current === null){parent.right = treeNode;}}}}this.length++;return treeNode;}//删除节点的真实实现_deleteNode(n){n = Number(n);if(this.root === null){return;}//查找该节点,删除节点操作⽐较复杂,为排除找不到被删除的节点的情况,简化代码,先保证该节点是存在的,虽然这样做其实重复了⼀次查询了,但⼆叉树的查找效率很⾼,这是可接受的let deleteNode = this.findNode(n);if(!deleteNode){return;}//如果删除的是根节点if(deleteNode === this.root){if(this.root.left === null && this.root.right === null){this.root = null;}else if(this.root.left === null){this.root = this.root.right;}else if(this.root.right === null){this.root = this.root.left;}else {let [replaceNode, replacePNode, rp] = this.findLeftTreeMax(deleteNode);replacePNode[rp] = null;replaceNode.left = this.root.left;replaceNode.right = this.root.right;this.root = replaceNode;}}else {//被删除的⽗节点,⼦节点在⽗节点的位置p,有left,right两种可能let [deleteParent, p] = this.findParentNode(deleteNode);if(deleteNode.left === null && deleteNode.right === null){deleteParent[p] = null;}else if(deleteNode.left === null){deleteParent[p] = deleteNode.right;}else if(deleteNode.right === null){deleteParent[p] = deleteNode.left;}else {//⽤来替换被删除的节点,⽗节点,节点在⽗节点的位置let [replaceNode, replacePNode, rp] = this.findLeftTreeMax(deleteNode);if(replacePNode === deleteNode){deleteParent[p] = replaceNode;}else {deleteParent[p] = replaceNode;replacePNode.right = null;}replacePNode[rp] = null;replaceNode.left = deleteNode.left;replaceNode.right = deleteNode.right;}}this.length--;}//查找findNode(n){let result = null;let current = this.root;while(current){if(n === current.n){result = current;break;}else if(n < current.n){current = current.left;}else {current = current.right;}}return result;}//查找⽗节点findParentNode(node){let [parent, child, p] = [null, null, null];if(this.root !== node){parent = this.root;if(node.n < parent.n){child = parent.left;p = 'left';}else {child = parent.right;p = 'right';}while(child){if(node.n === child.n){break;}else if(node.n < child.n){parent = child;child = parent.left;p = 'left';}else {parent = child;child = parent.right;p = 'right';}}}return [parent, p];}//查找当前有左⼦树的节点的最⼤值的节点M,如有A个节点被删除,M是最接近A点之⼀(还有⼀个是右⼦树节点的最⼩值) findLeftTreeMax(topNode){let [node, parent, p] = [null, null, null];if(this.root === null || topNode.left === null){return [node, parent, p];}parent = topNode;node = topNode.left;p = 'left';while(node.right){parent = node;node = node.right;p = 'right';}return [node, parent, p];}//查找最⼤值maxValue(){if(this.root !== null){return this._findLimit('right');}}//查找最⼩值minValue(){if(this.root !== null){return this._findLimit('left');}}//实现查找特殊值_findLimit(pro){let n = this.root.n;let current = this.root;while(current[pro]){current = current[pro];n = current.n;}return n;}//中序排序,并⽤数组的形式显⽰sortMiddleToArr(){this._sortMiddleToArr(this.root);return this.arr;}//中序⽅法_sortMiddleToArr(node){if(node !== null){this._sortMiddleToArr(node.left);this.arr.push(node.n);this._sortMiddleToArr(node.right);}}//打印⼆叉树对象printNode(){console.log(JSON.parse(JSON.stringify(this.root)));}}//测试var binaryTree = new BinaryTree();binaryTree.addNode([50, 24, 18, 65, 4, 80, 75, 20, 37, 40, 60]);binaryTree.printNode();//{n: 50, left: {…}, right: {…}}console.log(binaryTree.maxValue());//80console.log(binaryTree.minValue());//4console.log(binaryTree.sortMiddleToArr());// [4, 18, 20, 24, 37, 40, 50, 60, 65, 75, 80] binaryTree.deleteNode([50]);binaryTree.printNode();//{n: 40, left: {…}, right: {…}}排序复习function ArrayList() {this.array = [];}ArrayList.prototype = {constructor: ArrayList,insert: function(item) {this.array.push(item);},toString: function() {return this.array.join();},swap: function(index1, index2) {var aux = this.array[index2];this.array[index2] = this.array[index1];this.array[index1] = aux;},//冒泡排序bubbleSort: function() {var length = this.array.length;for (var i = 0; i < length; i++) {for (var j = 0; j < length - 1 - i; j++) {if (this.array[j] > this.array[j + 1]) {this.swap(j, j + 1);}}}},//选择排序selectionSort: function() {var length = this.array.length;var indexMin;for (var i = 0; i < length - 1; i++) {indexMin = i;for (var j = i; j < length; j++) {if (this.array[indexMin] > this.array[j]) {indexMin = j;}}if (indexMin !== i) {this.swap(indexMin, i);}}},//插⼊排序insertionSort: function() {var length = this.array.length;var j;var temp;for (var i = 1; i < length; i++) {temp = this.array[i];j = i;while (j > 0 && this.array[j - 1] > temp) {this.array[j] = this.array[j - 1];j--;}this.array[j] = temp;}},//归并排序mergeSort: function() {function mergeSortRec(array) {var length = array.length;if (length === 1) {return array;}var mid = Math.floor(length / 2);var left = array.slice(0, mid);var right = array.slice(mid, length);return merge(mergeSortRec(left), mergeSortRec(right)); }function merge(left, right) {var result = [];var il = 0;var ir = 0;while (il < left.length && ir < right.length) {if (left[il] < right[ir]) {result.push(left[il++]);} else {result.push(right[ir++]);}}while (il < left.length) {result.push(left[il++]);}while (ir < right.length) {result.push(right[ir++]);}return result;}this.array = mergeSortRec(this.array);},//快速排序quickSort:function(){function sort(array){if (array.length <= 1) {return array;}var pivotIndex = Math.floor(array.length/2);var pivot = array.splice(pivotIndex,1)[0];var left = [];var right = [];for(var i = 0; i < array.length; i++){if (array[i] < pivot) {left.push(array[i]);}else{right.push(array[i]);}}return sort(left).concat([pivot],sort(right));}this.array = sort(this.array);}};...................................................................................................................############################################################################ ###################################################################################。
二叉树插入算法
![二叉树插入算法](https://img.taocdn.com/s3/m/20c587201fd9ad51f01dc281e53a580217fc5068.png)
二叉树插入算法通常涉及到二叉搜索树或二叉堆。
下面是这两种二叉树的插入算法的概述。
二叉搜索树的插入算法
在二叉搜索树(BST)中,每个节点都有一个键和两个子节点。
左子节点的键小于或等于节点的键,右子节点的键大于或等于节点的键。
创建新节点:创建一个新节点,将新数据分配给该节点。
找到插入位置:从根节点开始,如果新节点的键小于当前节点的键,则向左子树移动;如果新节点的键大于当前节点的键,则向右子树移动。
重复此过程,直到找到一个空位置来插入新节点。
插入新节点:将新节点插入到找到的空位置。
调整平衡(可选):如果插入操作导致树变得不平衡,需要进行旋转等操作来重新平衡树。
二叉堆的插入算法
在二叉堆中,每个节点都满足堆属性:对于任何节点i,其值大于或等于其子节点的值(对于最大堆)或小于或等于其子节点的值(对于最小堆)。
创建新节点:创建一个新节点,将新数据分配给该节点。
上浮调整:如果新节点比其父节点大(对于最大堆)或小(对于最小堆),则交换新节点和父节点,并继续上浮调整,直到满足堆属性。
以上是二叉树插入算法的基本概述。
具体的实现细节和优化方法可能会根据实际的应用场景和需求有所不同。
二叉树基本运算算法的实现
![二叉树基本运算算法的实现](https://img.taocdn.com/s3/m/e7871765ac02de80d4d8d15abe23482fb5da0252.png)
二叉树基本运算算法的实现
二叉树是一种常见的数据结构,基本运算算法包括二叉树的遍历、查找、插入、删除等操作。
下面是这些算法的实现:
1. 二叉树遍历:二叉树遍历有三种方式,分别是前序遍历、中序遍历和后序遍历。
其中,前序遍历先访问根节点,再访问左子树和右子树;中序遍历先访问左子树,再访问根节点和右子树;后序遍历先访问左子树,再访问右子树和根节点。
遍历可以使用递归算法或栈实现。
2. 二叉树查找:二叉树查找可以使用递归算法或循环算法实现。
递归算法通过比较节点值实现查找,如果查找值小于当前节点值,则在左子树中查找,否则在右子树中查找。
循环算法使用二叉树的特性,比较查找值和当前节点值的大小,根据大小关系不断移动到左子树或右子树中进行查找,直到找到目标节点或遍历到叶子节点为止。
3. 二叉树插入:二叉树插入需要先查找到插入位置,然后在该位置插入一个新节点。
插入操作可以使用递归算法或循环算法实现。
4. 二叉树删除:二叉树删除分为三种情况:删除叶子节点、删除只有一个孩子的节点和删除有两个孩子的节点。
删除叶子节点很简单,只需要将其父节点的指针设为NULL即可。
删除只有一个孩子的节点需要将父节点的指针指向该节点的
孩子节点。
删除有两个孩子的节点需要找到该节点的后继节点(或前驱节点),将后继节点的值复制到该节点中,然后删除后继节点。
上述算法的实现需要根据具体的编程语言进行调整和实现。
二叉树各种计算公式总结
![二叉树各种计算公式总结](https://img.taocdn.com/s3/m/6fbca359974bcf84b9d528ea81c758f5f71f2963.png)
二叉树各种计算公式总结二叉树是一种常见的数据结构,它由一个根节点和最多两个子节点组成。
许多计算问题可以通过对二叉树进行各种操作和遍历来解决。
在本文中,将总结二叉树的各种计算公式。
1.二叉树节点个数:二叉树节点个数的计算公式是N=N1+N2+1,其中N表示二叉树的节点个数,N1表示左子树的节点个数,N2表示右子树的节点个数。
2. 二叉树的高度:二叉树的高度是指从根节点到最远叶子节点的最长路径上的节点数量。
计算二叉树的高度的公式是H = max(H1, H2) + 1,其中H表示二叉树的高度,H1表示左子树的高度,H2表示右子树的高度。
3.二叉树的深度:二叉树的深度是指从根节点到当前节点的路径的长度。
计算二叉树的深度的公式是D=D1+1,其中D表示二叉树的深度,D1表示父节点的深度。
4.二叉查找树:二叉查找树是一种有序二叉树,它要求对于树中的每个节点,左子树的值都小于节点的值,右子树的值都大于节点的值。
在二叉查找树中进行的公式是:-如果目标值等于当前节点的值,则返回当前节点;-如果目标值小于当前节点的值,则在左子树中继续;-如果目标值大于当前节点的值,则在右子树中继续。
5.二叉树的遍历:二叉树的遍历是指按照一定的顺序访问二叉树中的所有节点。
常见的二叉树遍历方式有三种:- 前序遍历:先访问根节点,然后递归地访问左子树,最后递归地访问右子树。
可以表示为:root -> 左子树 -> 右子树。
- 中序遍历:先递归地访问左子树,然后访问根节点,最后递归地访问右子树。
可以表示为:左子树 -> root -> 右子树。
- 后序遍历:先递归地访问左子树,然后递归地访问右子树,最后访问根节点。
可以表示为:左子树 -> 右子树 -> root。
6.二叉树的最大路径和:二叉树的最大路径和是指二叉树中两个节点之间路径上的节点值的最大和。
可以通过递归地计算每个子树的最大路径和,然后选择最大的子树路径和来得出最终结果。
二叉排序树非递归插入算法
![二叉排序树非递归插入算法](https://img.taocdn.com/s3/m/6fa96019657d27284b73f242336c1eb91a373302.png)
二叉排序树非递归插入算法
二叉排序树非递归插入算法指的是在二叉排序树中插入一个新
节点时,采用非递归的方式进行操作的算法。
其基本思想是从根节点开始找到插入位置,并将新节点插入到相应位置上。
具体实现过程为:先将新节点插入到二叉排序树的最底层,然后从底层向上逐层调整,使得整个树仍然满足二叉排序树的性质。
在插入过程中,需要从根节点开始一直向下查找,直到找到插入位置为止。
如果插入节点的值大于当前节点的值,则向右子树继续查找;如果插入节点的值小于当前节点的值,则向左子树继续查找。
非递归插入算法相对于递归插入算法具有简单、高效、节省空间等优点,因此在实际应用中被广泛采用。
同时,该算法的实现也相对较为简单,适合初学者学习二叉排序树的基本操作。
- 1 -。
二叉树的各种算法
![二叉树的各种算法](https://img.taocdn.com/s3/m/40399d69bc64783e0912a21614791711cc79798a.png)
二叉树的各种算法1.二叉树的前序遍历算法:前序遍历是指先访问根节点,再访问左子树,最后访问右子树的遍历顺序。
具体算法如下:-如果二叉树为空,则直接返回。
-访问根节点,并输出或进行其他操作。
-递归地前序遍历左子树。
-递归地前序遍历右子树。
2.二叉树的中序遍历算法:中序遍历是指先访问左子树,再访问根节点,最后访问右子树的遍历顺序。
具体算法如下:-如果二叉树为空,则直接返回。
-递归地中序遍历左子树。
-访问根节点,并输出或进行其他操作。
-递归地中序遍历右子树。
3.二叉树的后序遍历算法:后序遍历是指先访问左子树,再访问右子树,最后访问根节点的遍历顺序。
具体算法如下:-如果二叉树为空,则直接返回。
-递归地后序遍历左子树。
-递归地后序遍历右子树。
-访问根节点,并输出或进行其他操作。
4.二叉树的层序遍历算法:层序遍历是按照从上到下、从左到右的顺序逐层遍历二叉树的节点。
具体算法如下:-如果二叉树为空,则直接返回。
-创建一个队列,将根节点入队。
-循环执行以下步骤,直到队列为空:-出队并访问当前节点,并输出或进行其他操作。
-若当前节点的左子节点不为空,则将左子节点入队。
-若当前节点的右子节点不为空,则将右子节点入队。
5.二叉树的深度算法:二叉树的深度是指从根节点到叶节点的最长路径的节点数。
具体算法如下:-如果二叉树为空,则深度为0。
-否则,递归地计算左子树的深度和右子树的深度,然后取较大的值加上根节点的深度作为二叉树的深度。
6.二叉树的查找算法:二叉树的查找可以使用前序、中序或后序遍历来完成。
具体算法如下:-如果二叉树为空,则返回空。
-如果当前节点的值等于目标值,则返回当前节点。
-否则,先在左子树中递归查找,如果找到则返回找到的节点。
-如果左子树中未找到,则在右子树中递归查找,如果找到则返回找到的节点。
-如果左右子树中都未找到,则返回空。
7.二叉树的插入算法:二叉树的插入可以使用递归或循环来实现。
具体算法如下:-如果二叉树为空,则创建一个新节点作为根节点,并返回根节点。
创建二叉树的三种算法
![创建二叉树的三种算法](https://img.taocdn.com/s3/m/67a5fd9277eeaeaad1f34693daef5ef7ba0d12c8.png)
创建二叉树的三种算法1.递归算法递归算法是最直观也是最常用的创建二叉树的方法之一、递归算法通过递归地创建左子树和右子树来构建完整的二叉树。
具体步骤如下:-创建一个二叉树结构的定义,包含一个存储数据的变量和左右子节点。
-如果当前节点为空,直接将新节点插入当前位置。
-如果新节点的值小于当前节点的值,递归地将新节点插入当前节点的左子树。
-如果新节点的值大于等于当前节点的值,递归地将新节点插入当前节点的右子树。
递归算法的示例代码如下所示:```pythonclass TreeNode:def __init__(self, val):self.val = valself.left = Noneself.right = Nonedef insert(root, val):if root is None:return TreeNode(val)if val < root.val:root.left = insert(root.left, val)elif val >= root.val:root.right = insert(root.right, val)return root```2.先序遍历算法先序遍历算法通过遍历给定的节点集合,按照先序的顺序将节点逐个插入到二叉树中。
这种算法可以使用栈来实现。
具体步骤如下:-创建一个空栈,同时创建一个新节点的拷贝作为当前节点。
-依次遍历给定的节点集合,如果新节点的值小于当前节点的值,将当前节点的左子节点指向新节点,并将新节点入栈,并将新节点移动到当前节点的左子节点。
-如果新节点的值大于等于当前节点的值,重复上述过程,直到找到一个合适的位置并插入新节点。
-当遍历完所有节点后,返回二叉树的根节点。
先序遍历算法的示例代码如下所示:```pythonclass TreeNode:def __init__(self, val): self.val = valself.left = Noneself.right = Nonedef insert(root, val): if root is None:return TreeNode(val) stack = []cur = rootwhile True:if val < cur.val:if not cur.left:cur.left = TreeNode(val) breakelse:cur = cur.leftelse:if not cur.right:cur.right = TreeNode(val)breakelse:cur = cur.rightreturn root```3.层次遍历算法层次遍历算法通过逐层遍历给定的节点集合,按照从上到下、从左到右的顺序将节点逐个插入到二叉树中。
求结点在二叉排序树中的层次递归
![求结点在二叉排序树中的层次递归](https://img.taocdn.com/s3/m/a73edd505e0e7cd184254b35eefdc8d376ee1427.png)
求结点在二叉排序树中的层次递归在二叉排序树(也称为二叉搜索树)中,节点可以按照层次进行遍历。
层次遍历可以使用递归或迭代方法实现。
下面是一个使用Python 实现的递归层次遍历二叉排序树的例子:pythonclass Node:def__init__(self, val):self.val = valself.left = Noneself.right = Nonedef level_order_traversal(root):if root is None:return []result = []queue = [root]while queue:level_size = len(queue)current_level = []for _ in range(level_size):node = queue.pop(0) # 弹出队列中的第一个元素current_level.append(node.val) # 将节点值添加到当前层级列表中if node.left:queue.append(node.left) # 将左子节点添加到队列中if node.right:queue.append(node.right) # 将右子节点添加到队列中result.append(current_level) # 将当前层级列表添加到结果中return result在这个例子中,我们首先检查根节点是否为空。
如果为空,则返回一个空列表。
然后,我们创建一个队列,并将根节点添加到队列中。
接下来,我们进入一个循环,只要队列不为空,就会继续循环。
在每一轮循环中,我们首先获取当前层级的长度,然后创建一个空列表来存储当前层级的节点值。
接下来,我们通过循环访问当前层级的所有节点,并将它们的值添加到当前层级列表中。
然后,我们将每个节点的左子节点和右子节点添加到队列中。
最后,我们将当前层级列表添加到结果中。
最终,当队列为空时,循环结束,我们返回结果。
数据结构 二叉排序树
![数据结构 二叉排序树](https://img.taocdn.com/s3/m/22f8c405590216fc700abb68a98271fe910eafe8.png)
数据结构二叉排序树数据结构二叉排序树1. 概述二叉排序树(Binary Search Tree,简称BST)是一种基于二叉树的数据结构,具有以下特点:- 每个节点最多只有两个子节点。
- 对于树中的任意节点,其左子树上所有节点的值都小于该节点的值,右子树上所有节点的值都大于该节点的值。
- 中序遍历二叉排序树得到的结果是一个有序序列。
2. 二叉排序树的操作2.1 插入二叉排序树的插入操作是将一个新的节点插入到二叉排序树中的合适位置,使得二叉排序树仍然满足以上特点。
插入操作的具体步骤如下:1. 若二叉排序树为空树,则将新节点作为根节点插入即可。
2. 若二叉排序树不为空,比较新节点的值与当前节点的值的大小关系:- 若新节点的值小于当前节点的值,则继续在当前节点的左子树中进行插入操作。
- 若新节点的值大于当前节点的值,则继续在当前节点的右子树中进行插入操作。
2.2 删除二叉排序树的删除操作是将指定节点从二叉排序树中删除,并保持二叉排序树的特性不变。
删除操作的具体步骤如下:1. 若待删除节点为叶子节点,则直接将其父节点指向该节点的指针置为null。
2. 若待删除节点只有左子树或只有右子树,则将其父节点指向该节点的指针直接指向该节点的子节点。
3. 若待删除节点既有左子树又有右子树,则需要找到其右子树中的最小节点(或左子树中的最大节点)来替代待删除节点。
具体步骤如下:- 先找到待删除节点右子树中的最小节点(即右子树中最左下的节点),或者左子树中的最大节点。
- 将该最小(或最大)节点的值复制到待删除节点。
- 将最小(或最大)节点从右子树(或左子树)中删除。
2.3 查找二叉排序树的查找操作是在树中寻找具有指定值的节点。
查找操作的具体步骤如下:1. 从根节点开始,将待查找的值与当前节点的值进行比较。
2. 若待查找的值等于当前节点的值,则返回该节点。
3. 若待查找的值小于当前节点的值,则继续在当前节点的左子树中进行查找操作。
实现二叉排序树的各种算法
![实现二叉排序树的各种算法](https://img.taocdn.com/s3/m/5044ff5d83d049649a665828.png)
wyf实现二叉排序树的各种算法一.需求分析(1)系统概述:本系统是针对排序二叉树设计的各种算法,提供的功能包括有:(1)插入新结点(2)前序、中序、后序遍历二叉树(3)中序遍历的非递归算法(4)层次遍历二叉树(5)在二叉树中查找给定关键字(函数返回值为成功1,失败0)二.总体设计(1)系统模块结构图(2)数据结构设计typedef struct BiTNode{ElemType data;struct BiTNode *lchild,*rchild;//左右孩子指针} BiTNode,*BiTree;typedef BiTree SElemType;typedef BiTree QElemType;typedef struct{QElemType *base; // 初始化的动态分配存储空间int front; // 头指针,若队列不空,指向队列头元素int rear; // 尾指针,若队列不空,指向队列尾元素的下一个位置 }SqQueue;typedef struct{SElemType *base; // 在栈构造之前和销毁之后,base的值为NULLSElemType *top; // 栈顶指针int stacksize; // 当前已分配的存储空间,以元素为单位}SqStack; // 顺序栈Status InitStack(SqStack &S){// 构造一个空栈S,该栈预定义大小为STACK_INIT_SIZE// 请补全代码S.base = (SElemType * )malloc(STACK_INIT_SIZE * sizeof(SElemType));if(!S.base) return (ERROR);S.top = S.base ;S.stacksize = STACK_INIT_SIZE;return OK;}Status Push(SqStack &S,BiTree e){// 在栈S中插入元素e为新的栈顶元素// 请补全代码if(S.top - S.base >= S.stacksize){S.base = (SElemType * )realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof (SElemType));if(!S.base )return ERROR;S.top = S.base + S.stacksize;S.stacksize += STACKINCREMENT;}* S.top ++ = e;return OK;}Status Pop(SqStack &S,SElemType &e){// 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR// 请补全代码if(S.top == S.base)return ERROR;e = * --S.top;return OK;}Status InitQueue(SqQueue &Q){// 构造一个空队列Q,该队列预定义大小为MAXQSIZE// 请补全代码Q.base = (QElemType *)malloc (MAXQSIZE * sizeof(QElemType));if(!Q.base) return ERROR;Q.front = Q.rear = 0;return OK;}Status EnQueue(SqQueue &Q,QElemType e){// 插入元素e为Q的新的队尾元素// 请补全代码if((Q.rear + 1)% MAXQSIZE == Q.front)return ERROR;Q.base[Q.rear] = e ;Q.rear = (Q.rear + 1) % MAXQSIZE;return OK;}Status DeQueue(SqQueue &Q, QElemType &e){// 若队列不空, 则删除Q的队头元素, 用e返回其值, 并返回OK; 否则返回ERROR// 请补全代码if(Q.front == Q.rear) return ERROR;e = Q.base[Q.front];Q.front = (Q.front +1) % MAXQSIZE;return OK;}Status CreateBiTree(BiTree &T , int n) { // 算法6.4// 按先序次序输入二叉树中结点的值(一个字符)// 构造二叉链表表示的二叉树T。
二叉树结点计算公式
![二叉树结点计算公式](https://img.taocdn.com/s3/m/b14248844128915f804d2b160b4e767f5acf80ee.png)
二叉树结点计算公式二叉树是一种常见的数据结构,由结点和连接这些结点的边组成。
每个结点都有一个值,并且可以有最多两个子结点。
根据二叉树结点的计算公式,我们可以更好地理解和运用二叉树。
二叉树的结点计算公式可以帮助我们计算二叉树的深度。
二叉树的深度是指从根结点到最远叶子结点的路径长度。
通过遍历二叉树的每个结点,并计算结点所在的层数,我们可以得到二叉树的深度。
这可以通过递归算法实现,即从根结点开始,递归地计算左右子树的深度,并取较大值加1作为树的深度。
二叉树的结点计算公式还可以帮助我们计算二叉树的节点数。
节点数是指二叉树中所有结点的总数。
通过递归地遍历每个结点,并计数每个结点,我们可以得到二叉树的节点数。
递归算法的思路是,树的节点数等于左子树的节点数加右子树的节点数再加1。
二叉树的结点计算公式还可以用于计算二叉树的叶子结点数。
叶子结点是指没有子结点的结点。
通过遍历每个结点,并判断其是否为叶子结点,我们可以得到二叉树的叶子结点数。
递归算法的思路是,如果当前结点没有左子树和右子树,则它是叶子结点,否则递归地计算左右子树的叶子结点数并相加。
二叉树的结点计算公式还可以帮助我们判断二叉树是否为平衡二叉树。
平衡二叉树是指任意节点的左右子树的高度差不超过1的二叉树。
通过计算每个结点的左子树和右子树的深度差,并判断是否满足平衡二叉树的定义,我们可以确定二叉树是否为平衡二叉树。
递归算法的思路是,判断当前结点的左子树和右子树的深度差是否满足平衡二叉树的定义,并递归地判断左右子树是否为平衡二叉树。
除了上述常见的二叉树计算公式,还有一些其他的应用。
例如,我们可以通过二叉树的结点计算公式来计算二叉树的直径。
二叉树的直径是指二叉树中任意两个结点之间的最长路径长度。
通过遍历每个结点,并计算以该结点为根结点的子树的直径,我们可以得到二叉树的直径。
递归算法的思路是,二叉树的直径等于左子树的直径、右子树的直径和经过根结点的最长路径长度中的最大值。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
wyf实现二叉排序树的各种算法一.需求分析(1)系统概述:本系统是针对排序二叉树设计的各种算法,提供的功能包括有:(1)插入新结点(2)前序、中序、后序遍历二叉树(3)中序遍历的非递归算法(4)层次遍历二叉树(5)在二叉树中查找给定关键字(函数返回值为成功1,失败0)二.总体设计(1)系统模块结构图(2)数据结构设计typedef struct BiTNode{ElemType data;struct BiTNode *lchild,*rchild;//左右孩子指针} BiTNode,*BiTree;typedef BiTree SElemType;typedef BiTree QElemType;typedef struct{QElemType *base; // 初始化的动态分配存储空间int front; // 头指针,若队列不空,指向队列头元素int rear; // 尾指针,若队列不空,指向队列尾元素的下一个位置}SqQueue;typedef struct{SElemType *base; // 在栈构造之前和销毁之后,base的值为NULLSElemType *top; // 栈顶指针int stacksize; // 当前已分配的存储空间,以元素为单位}SqStack; // 顺序栈Status InitStack(SqStack &S){// 构造一个空栈S,该栈预定义大小为STACK_INIT_SIZE// 请补全代码S.base = (SElemType * )malloc(STACK_INIT_SIZE * sizeof(SElemType));if(!S.base) return (ERROR);S.top = S.base ;S.stacksize = STACK_INIT_SIZE;return OK;}Status Push(SqStack &S,BiTree e){// 在栈S中插入元素e为新的栈顶元素// 请补全代码if(S.top - S.base >= S.stacksize){S.base = (SElemType * )realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof (SElemType));if(!S.base )return ERROR;S.top = S.base + S.stacksize;S.stacksize += STACKINCREMENT;}* S.top ++ = e;return OK;}Status Pop(SqStack &S,SElemType &e){// 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR// 请补全代码if(S.top == S.base)return ERROR;e = * --S.top;return OK;}Status InitQueue(SqQueue &Q){// 构造一个空队列Q,该队列预定义大小为MAXQSIZE// 请补全代码Q.base = (QElemType *)malloc (MAXQSIZE * sizeof(QElemType));if(!Q.base) return ERROR;Q.front = Q.rear = 0;return OK;}Status EnQueue(SqQueue &Q,QElemType e){// 插入元素e为Q的新的队尾元素// 请补全代码if((Q.rear + 1)% MAXQSIZE == Q.front)return ERROR;Q.base[Q.rear] = e ;Q.rear = (Q.rear + 1) % MAXQSIZE;return OK;}Status DeQueue(SqQueue &Q, QElemType &e){// 若队列不空, 则删除Q的队头元素, 用e返回其值, 并返回OK; 否则返回ERROR// 请补全代码if(Q.front == Q.rear) return ERROR;e = Q.base[Q.front];Q.front = (Q.front +1) % MAXQSIZE;return OK;}Status CreateBiTree(BiTree &T , int n) { // 算法6.4// 按先序次序输入二叉树中结点的值(一个字符)// 构造二叉链表表示的二叉树T。
int i ,e ,loop = 1;BiTree S1,S2;for(i=1;i<=n;i++){loop = 1;scanf("%d",&e);if(!(S1 = (BiTNode *)malloc(sizeof(BiTNode)))) return ERROR;S1 -> data = e;S1 -> lchild = NULL;S1 -> rchild = NULL;S2 = T;if(S2 == NULL) T = S1;else while(loop){if(S1->data < S2->data)if(S2->lchild == NULL){S2 ->lchild = S1; loop = 0;}else S2=S2->lchild;else if(S2->rchild == NULL){S2 -> rchild = S1; loop = 0;}else S2=S2->rchild;}}return OK;} // CreateBiTreeStatus Insert( BiTree T) //插入新结点{BiTree S1, S2;ElemType e;scanf("%d",&e);if(!(S2 = (BiTNode *)malloc(sizeof(BiTNode)))) return ERROR;S2 -> data = e;S2 -> rchild = NULL; S2 -> lchild = NULL;S1 = T;while(T){if(S1 -> data <= S2-> data)if(!S1 -> rchild){S1 -> rchild = S2;return OK;}else S1 = S1->rchild;elseif(!S1 -> lchild){S1 -> lchild = S2;return OK;}else S1 = S1->lchild;}T = S2;return OK;}Status Search( BiTree T ,ElemType e) {BiTree S;S = T;while(S){if(S -> data < e)S = S->rchild;else if(S -> data > e)S = S->lchild;else return OK;}return ERROR;}Status Visit( ElemType e ) { // 输出元素e的值printf("%d ", e );return OK;}// PrintElementStatus PreOrderTraverse( BiTree T, Status(*Visit)(ElemType) ) { // 前序遍历二叉树T的递归算法,对每个数据元素调用函数Visit。
//补全代码,可用多个语句if(T){if(Visit(T->data))if(PreOrderTraverse(T->lchild , Visit))if(PreOrderTraverse(T->rchild , Visit)) return OK;return ERROR;}else return OK;} // PreOrderTraverseStatus InOrderTraverse( BiTree T, Status(*Visit)(ElemType) ) { // 中序遍历二叉树T的递归算法,对每个数据元素调用函数Visit。
//补全代码,可用多个语句if(T)if(T){if(InOrderTraverse(T->lchild , Visit))if(Visit(T->data))if(InOrderTraverse(T->rchild , Visit)) return OK;return ERROR;}else return OK;} // InOrderTraverseStatus PostOrderTraverse( BiTree T, Status(*Visit)(ElemType) ) { // 后序遍历二叉树T的递归算法,对每个数据元素调用函数Visit。
//补全代码,可用多个语句if(T){if(PostOrderTraverse(T->lchild , Visit))if(PostOrderTraverse(T->rchild , Visit))if(Visit(T->data)) return OK;return ERROR;}else return OK;} // PostOrderTraverseStatus Dif_InOrder( BiTree T ) //中序遍历的非递归算法{BiTree S1;SqStack S2;S1 = T;InitStack(S2);while(S1 || S2.base != S2.top){if(S1){Push( S2, S1);S1 = S1-> lchild;}else{Pop(S2,S1);printf("%d ",S1->data);S1=S1->rchild;}}return OK;}Status Level( BiTree T ) /层次/遍历{BiTree S1, S3, S4;S1 = T;SqQueue S2;InitQueue(S2);EnQueue(S2,S1);while(S2.front != S2.rear){DeQueue(S2,S1);printf("%d ",S1->data);S3 = S1->lchild;S4 = S1->rchild;if(S3) EnQueue(S2,S3);if(S4) EnQueue(S2,S4);}return OK;}三.总结终于完成了这个实验报告,经过这次的磨练,我对数据结构这门学科有了更深的理解和感悟。