【考研408真题】2022年408数据结构41题---判断当前顺序存储结构树是否是二叉搜索树

文章目录

  • 思路
  • 408考研各数据结构C/C++代码(Continually updating)

思路

在这里插入图片描述
在这里插入图片描述
很明显,这是一个顺序存储结构的树的构成方法。其中树的根节点位置从索引0开始,对于该结构,存在有:如果当前根节点的下标为n,那么其左子树下标为2n+1,右子树下标为2n+2。
而对于BST,我们知道,其一个非常显著的特点就是:对于根节点root,其左子树小于其根节点的值,其右子树大于其根节点的值。同时,如果当前节点为null,不影响其是否为BST。
基于这个理论,我们大概的实现思路是:递归的判断当前根节点的左子树和右子树,并且限定其左右子树的值的大小区间范围。
那么这里应该如何去限制这个范围呢?
从上面的理论中我们可以得到如下的伪代码:

//如下代码基于链式存储结构 不过不影响理论实践
bool isBST(SqBiTree* root,int low,int high)
{if(root==null){return true;}//这里逻辑严谨应该增加一个左右指针的非空判断 我就不写了if(root.left.val>=root.val || root.right.val <= root.val){return false;}return isBST(root.left,low,root.val) && isBST(root.right,root.val,maxValue);
}

为什么要这么写呢?
首先我们基于上面的定义,如果当前节点为空,不影响当前树是否是BST,因此直接返回tree。
之后,我们开始条件判断,当前节点的左右子节点,是否小于和大于当前节点。
如果不是,也就是违法了BST的特性,那么我们直接返回false。
并且,我们一开始也说了,这应该是一个递归的判断过程,因此我们还需要对当前root节点的左子树和右子树继续去执行当前的递归过程。
那么递归的条件是什么?
对于当前节点的左子树,其最小值应该是不限定的,但是其最大值必须小于当前节点的值,
而对于其右子树,其最小值应该大于当前节点的值,其最大值不限。
所以就可以得到最后两行代码的条件了。
那么换到我们题目中,我们只需要将指针操作,修改为对数组下标的数据判断即可。
最终就可以得到如下代码:

// 递归函数,判断以n为根的二叉树是否是BST
bool isBSTUtil(BinaryTree *T, int n, TreeNodeType minVal, TreeNodeType maxVal)
{if (T->data[n] == '\0')return true;TreeNodeType nodeValue = T->data[n];// 检查当前节点的值是否在[minVal, maxVal]的范围内if ((nodeValue <= minVal) || ( maxVal <= nodeValue))return false;// 递归检查左子树和右子树,更新范围return isBSTUtil(T, 2 * n, minVal, nodeValue) && isBSTUtil(T, 2 * n + 1, nodeValue, maxVal);
}

ok,经过上面的解释,我们就已经得到了完整的当前题目的实现思路了。
完整代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>#define MaxSize 100typedef int TreeNodeType;// 二叉树结构
typedef struct
{TreeNodeType data[MaxSize];int BiTreeNum;
} BinaryTree;// 声明队列数据结构
typedef struct
{int front, rear;int size;int capacity;int *array;
} Queue;void initTree(BinaryTree *T);
void createTree(BinaryTree *T, int n);
TreeNodeType rootTree(BinaryTree *T);
int countTree(BinaryTree *T);
int maxDepthOfTree(BinaryTree *T, int n);
void preOrderTraverse(BinaryTree *T, int n);
void inOrderTraverse(BinaryTree *T, int n);
void postOrderTraverse(BinaryTree *T, int n);
void levelOrderTraverse(BinaryTree *T); // 层序遍历
bool destoryTree(BinaryTree *T);
void traverseArray(BinaryTree *T); // 遍历数组
bool isBSTUtil(BinaryTree *T, int n, TreeNodeType minVal, TreeNodeType maxVal);// 队列相关函数
Queue *createQueue(int capacity);
bool isQueueEmpty(Queue *queue);
bool isQueueFull(Queue *queue);
void enqueue(Queue *queue, int item);
int dequeue(Queue *queue);int main()
{BinaryTree T;// 开始构造二叉树 其中使用1作为根节点下标// 而不是使用0,使用0的问题在于不好表示数据在数组中的位置// 我们知道二叉树满足 当前节点n的左子树和右子树的序列号应该为 2n和2n+1initTree(&T);printf("请输入根结点(输入#表示该结点为空):");createTree(&T, 1);traverseArray(&T);printf("当前二叉树的最大深度为:%d\n", maxDepthOfTree(&T, 1));printf("先序遍历:");preOrderTraverse(&T, 1);printf("\n");printf("中序遍历:");inOrderTraverse(&T, 1);printf("\n");printf("后序遍历:");postOrderTraverse(&T, 1);printf("\n");printf("层序遍历:");levelOrderTraverse(&T);printf("\n");if (isBSTUtil(&T, 1, -10000, 10000)){printf("this is a BST");}else{printf("this is not a BST");}return 0;
}void initTree(BinaryTree *T)
{int i;for (i = 0; i < MaxSize; ++i){T->data[i] = '\0';}T->BiTreeNum = 0;return;
}void createTree(BinaryTree *T, int n)
{char ch;// 刷新(清空)标准输入流(stdin)// 主打一个求稳fflush(stdin);// 输入当前节点信息 # 代表当前节点为空// 先构造过字数scanf(" %c", &ch);if (ch == '#'){ // 空直接返回return;}else{T->data[n] = ch;T->BiTreeNum++;printf("输入 %c 的左子树数据(输入#表示当前左子树为空: ", ch);// 这里有一个技巧createTree(T, 2 * n);printf("输入 %c 的右子树数据(输入#表示当前右边子树为空): ", ch);createTree(T, (2 * n + 1));}
}// 计算二叉树的最大深度
// 从根节点到叶子节点的最长路径的长度
// 由于是顺序结构 因此这里从第一层也就是n=1开始向下遍历
// 然后不断的判断左子树和右子树的高度
// 最后取最大值
int maxDepthOfTree(BinaryTree *T, int n)
{if (n <= T->BiTreeNum && T->data[n] != '\0'){int leftDepth = maxDepthOfTree(T, 2 * n);int rightDepth = maxDepthOfTree(T, 2 * n + 1);return 1 + fmax(leftDepth, rightDepth);}else{return 0;}
}// 先序遍历 根左右
void preOrderTraverse(BinaryTree *T, int n)
{if (T->data[n] == '\0')return;else{printf("%c ", T->data[n]);preOrderTraverse(T, 2 * n);preOrderTraverse(T, (2 * n + 1));}
}
// 中序遍历 左根由7
void inOrderTraverse(BinaryTree *T, int n)
{if (T->data[n] == '\0')return;else{inOrderTraverse(T, 2 * n);printf("%c ", T->data[n]);inOrderTraverse(T, (2 * n + 1));}
}
// 后序遍历  左右根
void postOrderTraverse(BinaryTree *T, int n)
{if (T->data[n] == '\0')return;else{postOrderTraverse(T, 2 * n);postOrderTraverse(T, (2 * n + 1));printf("%c ", T->data[n]);}
}
void traverseArray(BinaryTree *T)
{for (int i = 1; i <= T->BiTreeNum; i++){printf("%c  ", T->data[i]);}printf("\n");
}// 层序遍历二叉树
void levelOrderTraverse(BinaryTree *T)
{if (T->BiTreeNum == 0){printf("二叉树为空\n");return;}Queue *queue = createQueue(T->BiTreeNum);int current = 1; // 从根节点开始while (current <= T->BiTreeNum){printf("%c ", T->data[current]);if (2 * current <= T->BiTreeNum && T->data[2 * current] != '\0'){enqueue(queue, 2 * current);}if (2 * current + 1 <= T->BiTreeNum && T->data[2 * current + 1] != '\0'){enqueue(queue, 2 * current + 1);}if (!isQueueEmpty(queue)){current = dequeue(queue);}else{break;}}free(queue->array);free(queue);
}// 创建队列
Queue *createQueue(int capacity)
{Queue *queue = (Queue *)malloc(sizeof(Queue));if (!queue){perror("内存分配失败");exit(EXIT_FAILURE);}queue->front = 0;queue->rear = -1;queue->size = 0;queue->capacity = capacity;queue->array = (int *)malloc(capacity * sizeof(int));if (!queue->array){perror("内存分配失败");exit(EXIT_FAILURE);}return queue;
}// 检查队列是否为空
bool isQueueEmpty(Queue *queue)
{return (queue->size == 0);
}// 检查队列是否已满
bool isQueueFull(Queue *queue)
{return (queue->size == queue->capacity);
}// 入队列
void enqueue(Queue *queue, int item)
{if (isQueueFull(queue)){printf("队列已满\n");return;}queue->rear = (queue->rear + 1) % queue->capacity;queue->array[queue->rear] = item;queue->size++;
}// 出队列
int dequeue(Queue *queue)
{if (isQueueEmpty(queue)){printf("队列为空\n");return -1;}int item = queue->array[queue->front];queue->front = (queue->front + 1) % queue->capacity;queue->size--;return item;
}// 递归函数,判断以n为根的二叉树是否是BST
bool isBSTUtil(BinaryTree *T, int n, TreeNodeType minVal, TreeNodeType maxVal)
{if (T->data[n] == '\0')return true;TreeNodeType nodeValue = T->data[n];// 检查当前节点的值是否在[minVal, maxVal]的范围内if ((nodeValue <= minVal) || ( maxVal <= nodeValue))return false;// 递归检查左子树和右子树,更新范围return isBSTUtil(T, 2 * n, minVal, nodeValue) && isBSTUtil(T, 2 * n + 1, nodeValue, maxVal);
}

408考研各数据结构C/C++代码(Continually updating)

408考研各数据结构C/C++代码(Continually updating)
这个模块是我应一些朋友的需求,希望我能开一个专栏,专门提供考研408中各种常用的数据结构的代码,并且希望我附上比较完整的注释以及提供用户输入功能,ok,fine,这个专栏会一直更新,直到我认为没有新的数据结构可以讲解了。
目前我比较熟悉的数据结构如下:
数组、链表、队列、栈、树、B/B+树、红黑树、Hash、图。
所以我会先有空更新出如下几个数据结构的代码,欢迎关注。 当然,在我前两年的博客中,对于链表、哈夫曼树等常用数据结构,我都提供了比较完整的详细的实现以及思路讲解,有兴趣可以去考古。

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

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

相关文章

凉鞋的 Unity 笔记 108. 第二个通识:增删改查

在这一篇&#xff0c;我们来学习此教程的第二个通识&#xff0c;即&#xff1a;增删改查。 增删改查我们不只是一次接触到了。 在最先接触的场景层次窗口中&#xff0c;我们是对 GameObject 进行增删改查。 在 Project 文件窗口中&#xff0c;我们是对文件&文件夹进行增删…

Jetpack:007-Kotlin中的Button

文章目录 1. 概念介绍2. 使用方法2.1 Button2.2 IconButton2.3 ElevatedButton2.4 OutlinedButton2.5 TextButton2.6 FloatingActionButton 3. 示例代码4. 内容总结 我们在上一章回中介绍了Jetpack中输入框相关的内容&#xff0c;本章回中将要介绍 Button。闲话休提&#xff0…

使用【Blob、Base64】两种方式显示【文本、图片、视频】 使用 video 组件播放视频

Blob 显示 Blob 对象的类型是由 MIME 类型&#xff08;Multipurpose Internet Mail Extensions&#xff09;来确定的。MIME 类型是一种标准&#xff0c;用于表示文档、图像、音频、视频等多媒体文件的类型。以下是一些常见的 Blob 对象类型&#xff1a; text/plain&#xff1…

drone如何发布docker服务

上篇主要实现了drone在物理机上进行发布程序&#xff0c;这次介绍drone如何发布docker类型的服务。 一 drone.yml文件配置 前提&#xff1a;需要提前在drone里添加文件里面所引用的密钥 kind: pipeline # 定义对象类型&#xff0c;还有secret和signature两种类型 type: dock…

SaaS人力资源管理系统的Bug

SaaS人力资源管理系统的Bug Bug1【18】 这里我是直接把代码复制过来的&#xff0c;然后就有一个空白 这是因为它的代码有问题&#xff0c;原本的代码如下所示 <el-table-column fixed type"index" label"序号" width"50"></el-table…

Android之SpannableString使用

文章目录 前言一、效果图二、实现代码总结 前言 在开发中&#xff0c;往往有些需求是我们不愿意遇到的&#xff0c;但是也不得不处理的事情&#xff0c;比如一段文案&#xff0c;需要文案中某些文字变颜色或者点击跳转&#xff0c;所以简单写了几句代码实现&#xff0c;没什么…

java气候分析平台天气预报系统springboot+vue

保护措施 (自动编号、图片、措施简介、措施地点、措施时间、创建时间、措施详情、措施名称)&#xff1b; 报名信息 (自动编号、活动地点、图片、活动名称、活动时间、参与人数、活动详情、审核回复、创建时间、报名时间、手机、活动简介、是否审核、姓名、账号)&#xff1b; 配…

uniapp 一次性上传多条视频 u-upload accept=“video“ uni.chooseMedia uni.uploadFile

方式 一 部分安卓机 只能一条一条传视频 文档地址 uview 2.0 Upload 上传组件 html <view class"formupload"><u-upload accept"video":fileList"fileList3" afterRead"afterRead" delete"deletePic" name"…

Elasticsearch集群管理原理

Elasticsearch 是一个开源的、基于 Lucene 的分布式搜索和分析引擎&#xff0c;设计用于云计算环境中&#xff0c;能够实现实时的、可扩展的搜索、分析和探索全文和结构化数据。它具有高度的可扩展性&#xff0c;可以在短时间内搜索和分析大量数据。 Elasticsearch 不仅仅是一个…

算法练习13——跳跃游戏II

LeetCode 45 跳跃游戏 II 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说&#xff0c;如果你在 nums[i] 处&#xff0c;你可以跳转到任意 nums[i j] 处: 0 < j < nums[i] i j < n 返回…

【漏洞复现】安全云平台存在任意文件下载getshell

漏洞描述 深圳市强鸿电子有限公司鸿运主动安全云平台存在任意文件下载漏洞,攻击者可通过此漏洞下载敏感文件信息。 免责声明 技术文章仅供参考,任何个人和组织使用网络应当遵守宪法法律,遵守公共秩序,尊重社会公德,不得利用网络从事危害国家安全、荣誉和利益,未经授权…

el-table合计行合并

效果如下 因为合计el-table的合并方法是不生效的,所以需要修改css下手 watch: {// 应急物资的合计合并planData: {immediate: true,handler() {setTimeout(() > {const tds document.querySelectorAll(".pro_table .el-table__footer-wrapper tr>td");tds[0]…

C++笔记之std::future的用法

C笔记之std::future的用法 code review! 文章目录 C笔记之std::future的用法1.C中std::future和std::async总是一起出现吗&#xff1f;2.主要特点和用法3.一个完整的例子4.std::future 存放的是一个结果吗&#xff1f;5.cppreference——std::future 1.C中std::future和std::a…

数据分析基础:数据可视化+数据分析报告

数据分析是指通过对大量数据进行收集、整理、处理和分析&#xff0c;以发现其中的模式、趋势和关联&#xff0c;并从中提取有价值的信息和知识。 数据可视化和数据分析报告是数据分析过程中非常重要的两个环节&#xff0c;它们帮助将数据转化为易于理解和传达的形式&#xff0…

C++ - git 命令行

为什么要有 git 你很可能遇到过这种情况&#xff0c;在写项目的时候&#xff0c;要我不符合 leader 的要求&#xff0c;因而修改了很多个版本&#xff0c;但是修改到最后一版的时候&#xff0c;leader 有觉得当前这版还没有之前 某一版好&#xff0c;现在又要求你在 之前的那一…

OJ项目——用户的登录拦截,我是如何实现的?

目录 前言 1、关于Session该如何处理 简单session回顾&#xff1a; 回顾session的setAttribute、getAttribute : 项目中如何做&#xff1f; 2、登陆拦截器实现 自定义拦截器&#xff1a; 自定义拦截&#xff1a; 前言 博主之前也有出过一期关于拦截器的&#xff0c;大…

Zabbix监控系统详解2:基于Proxy分布式实现Web应用监控及Zabbix 高可用集群的搭建

文章目录 1. zabbix-proxy的分布式监控的概述1.1 分布式监控的主要作用1.2 监控数据流向1.3 构成组件1.3.1 zabbix-server1.3.2 Database1.3.3 zabbix-proxy1.3.4 zabbix-agent1.3.5 web 界面 2. 部署zabbix代理服务器2.1 前置准备2.2 配置 zabbix 的下载源&#xff0c;安装 za…

零代码编程:用ChatGPT批量采集bookroo网页上的英文书目列表

bookroo网页上有很多不错的英文图书书目。比如这个关于儿童花样滑冰的书单&#xff1a; https://bookroo.com/explore/books/topics/ice-skating 怎么批量下载下来呢&#xff1f; 这个网页是动态网页&#xff0c;要爬取下来比较麻烦&#xff0c;可以先查看源代码&#xff0c;…

Golang中gRPC使用及原理探究

文章目录 概述gRPC的优势&#xff1a; 1、gRPC入门1.1 protobuf安装1.2 使用gRPC1.2.1 定义proto文件1.2.2 编译proto文件1.2.3 编写客户端和服务端代码 2、gRPC的通信模式2.1 一元RPC模式2.2 客户端流RPC模式2.3 服务端流RPC模式2.4双向流RPC模式 3、 gRPC的底层原理探究3.1 H…

P1433 吃奶酪

#include <iostream> #include <cmath> using namespace std; #define M 15 #define S(n) ((n) * (n)) double indx[M 5], indy[M 5], ans 0, sum 0;//坐标数组&#xff0c;从下标为1开始记录 int n, vis[M 5] { 0 };//vis数组&#xff0c;选过的数字标记为1…