【小浩算法 BST与其验证】

news2024/11/24 1:15:46

BST与其验证

  • 前言
  • 我的思路
    • 思路一 中序遍历+判断数组无重复递增
    • 思路二 递归+边界最大值最小值的传递
  • 我的代码
    • 测试用例1
    • 测试用例2

前言

BST是二叉树一个经典应用,我们常常将其用于数据的查找以及构建平衡二叉树等。今天我所做的题目是验证一颗二叉树是否为二叉搜索树,应该还算是基础题吧。

我的思路

其实最开始这个题目我的思路并不清晰,基本上只能想到去用递归,但是如何去构建递归的子问题,我想不太到,哈哈哈还是算法小白呢,想不到很正常(偷偷安慰自己…)。思路学习链接:
小浩算法-BST验证
力扣–验证二叉搜索树【98】

思路一 中序遍历+判断数组无重复递增

这个思路我觉得很巧妙,因为它利用了一个特性:二叉搜索树的中序遍历得到的一定是一个完全递增的序列(我们考虑的是二叉树里面无重复值),随后我们只需要判断一下遍历的结果是否严格递增就好了。总结一下:

  • 先中序遍历BST把结果存储在一个vector里面。
  • 判断该vector是否严格递增。
//验证是否为二叉搜索树
	void isBST(node* root) {
		//先创建一个数组
		vector<char> midOrderArr;
		midOrder(root, midOrderArr);
		//输出看一下我的数组里面存的是不是中序遍历的值
		for (int i = 0; i < midOrderArr.size(); i++) {
			cout << midOrderArr[i] << ' ';
		}
		cout << endl;
		for (int i = 0; i < midOrderArr.size()-1; i++) {
			if (midOrderArr[i] >= midOrderArr[i + 1]) {
				cout << "该二叉树 不是一颗二叉搜索树!" << endl;
				return;
			}
		}
		cout << "该二叉树 是一颗二叉搜索树!" << endl;
	}

	//二叉树的中序遍历
	void midOrder(node* root,vector<char>& Arr) {
		if (root == nullptr) {
			return;
		}
		midOrder(root->left, Arr);
		Arr.push_back(root->info);
		midOrder(root->right, Arr);
	}

思路二 递归+边界最大值最小值的传递

这个题目有一个很有意思的陷阱,那就是我们不光要求 一个结点的左孩子比它小,右孩子比它大。我们要求的是,这个结点的左子树上的所有结点都比它小,右子树上的所有结点都比他大

因此在递归的时候,我们需要一个上界和下界
首先需要考虑初始化的问题,这里我们用到climits库里面的LONG_MAX和LONG_MIN.代表long long 类型的最大值和最小值。
递归左子树,上界是根节点的值,下界就选上一层的min ;递归右子树,下界是根节点的值,上界就选上一层的max。perfect!完美!

bool isBST_Recursion(node* root,long long min,long long max) {
		if (root == nullptr) {
			return true;
		}
		if (root->info <= min || root->info >=max) {
			//cout << "该二叉树不是一个二叉搜索树";
			return false;
		}
		return isBST_Recursion(root->left, min, root->info) && isBST_Recursion(root->right, root->info, max);
	}

我的代码

测试用例1

1248##9##5##36##7##

在这里插入图片描述

测试用例2

421##3##65##7##

在这里插入图片描述

#include <iostream>
#include<algorithm>
#include<cmath>
#include <queue> 
#include<climits>
using namespace std;

struct node {
	char info;
	node* left;
	node* right;
	node(char data) :info(data), left(nullptr), right(nullptr) {

	};
	node() :info(NULL), left(nullptr), right(nullptr) {

	};
};

class binaryTree {
private:
		node* root;
public:
	binaryTree() {
		root = new node(NULL);
	}

	//得到树的根结点
	node* getRoot() {
		return root;
	}

	//以递归的方式构建一棵树
	void createTree(node*& t) {
		char str;
		cin >> str;
		if (str == '#') {
			t = NULL;
		}
		else {
			t = new node;//为t开辟空间
			t->info = str;
			createTree(t->left);
			createTree(t->right);
		}
	}

	//树的深度
	int depth(node* root) {
		if (root == nullptr) {
			return 0;
		}
		int left = depth(root->left);
		int right = depth(root->right);
		return max(left, right) + 1;
	}

	//打印一棵树满二叉树,只能打印满二叉树,节点数目最好不要超过10
	void print(node*& root) {
		//存放打印的二叉树
		char str[10][100] = {};
		queue<node*> q;
		int h = depth(root);
		q.push(root);
		int index = 0;
		while (!q.empty()) {
			int size = q.size();
			//存放每一层的节点
			vector<char> list;
			for (int i = 0; i < size; i++) {
				node* temp = q.front();
				q.pop();
				list.push_back(temp->info);
				//cout << temp->info;
				if (temp->left != nullptr) {
					q.push(temp->left);
				}
				if (temp->right != nullptr) {
					q.push(temp->right);
				}
			}
			bool flag = true;
			int j = 0;
			//打印前面部分空白
			while (j <= 2 * h - 1 - index) {
				str[index][j] = ' ';
				j++;

			}
			//保持第一行居中
			if (index == 0) {
				for (int m = 0; m < h - 2; m++) {
					str[index][j++] = ' ';
				}
			}

			for (int k = 0; k < list.size(); k++) {
				//如果是一层最后一个节点
				if (k == list.size() - 1) {
					str[index][j++] = list[k];
				}
				else {
					//相邻左右子节点
					if (k % 2 == 0) {
						str[index][j++] = list[k];
						for (int l = 0; l < 3 + 2 * (h - index / 2 - 1); l++) {
							str[index][j++] = ' ';
						}
					}
					else {
						str[index][j++] = list[k];
						str[index][j++] = ' ';
					}
				}
			}

			index += 2;
			//cout << endl;
		}
		for (int i = 0; i < 10; i++) {
			if (i % 2 == 1) {
				for (int j = 0; j < 100; j++) {
					str[i][j] = ' ';
				}
			}
		}
		for (int i = 0; i < 10; i++) {
			if (i % 2 == 0) {
				for (int j = 0; j < 100; j++) {
					if (str[i][j] - '0' >= 0 && str[i][j] - '0' <= 9 && i < 2 * h - 2) {
						str[i + 1][j - 1] = '/';
						str[i + 1][j + 1] = '\\';
					}

				}
			}
		}
		for (int i = 0; i < 10; i++) {
			for (int j = 0; j < 100; j++) {
				cout << str[i][j];
			}
			cout << endl;
		}
	}

	void DeepFirstSearch(node* root) {
		if (root == NULL) {
			return;
		}
		else {
			cout << root->info << ' ';
			DeepFirstSearch(root->left);
			DeepFirstSearch(root->right);
		}

	}

	void BreadthFirstSearch(node* root) {
		queue<node> myTree;
		if (root != nullptr) {
			myTree.push(*root);
		}
		while (!myTree.empty()) {
			cout << myTree.front().info << ' ';
			if (myTree.front().left != nullptr) {
				myTree.push(*(myTree.front().left));
			}
			if (myTree.front().right != nullptr) {
				myTree.push(*(myTree.front().right));
			}
			myTree.pop();
		}
	}

	//用于BFS递归的主函数
	void BFS_Recursion(node* root, int level, vector<vector<char>>& res) {
		if (root == nullptr) {
			return;
		}
		if (res.size() < level) {
			res.push_back(vector<char>());
		}
		res[level - 1].push_back(root->info);
		BFS_Recursion(root->left, level + 1, res);
		BFS_Recursion(root->right, level + 1, res);
	}

	void BreadthFirstSearch_recursion(node* root) {
		vector<vector<char>> res;
		BFS_Recursion(root, 1, res);
		for (int i = 0; i < res.size(); i++) {
			for (int j = 0; j < res[i].size(); j++) {
				cout << res[i][j] << " ";
			}
		}
	}

	//验证是否为二叉搜索树
	void isBST(node* root) {
		//先创建一个数组
		vector<char> midOrderArr;
		midOrder(root, midOrderArr);
		//输出看一下我的数组里面存的是不是中序遍历的值
		for (int i = 0; i < midOrderArr.size(); i++) {
			cout << midOrderArr[i] << ' ';
		}
		cout << endl;
		for (int i = 0; i < midOrderArr.size()-1; i++) {
			if (midOrderArr[i] >= midOrderArr[i + 1]) {
				cout << "该二叉树 不是一颗二叉搜索树!" << endl;
				return;
			}
		}
		cout << "该二叉树 是一颗二叉搜索树!" << endl;
	}

	//二叉树的中序遍历
	void midOrder(node* root,vector<char>& Arr) {
		if (root == nullptr) {
			return;
		}
		midOrder(root->left, Arr);
		Arr.push_back(root->info);
		midOrder(root->right, Arr);
	}

	bool isBST_Recursion(node* root,long long min,long long max) {
		if (root == nullptr) {
			return true;
		}
		if (root->info <= min || root->info >=max) {
			//cout << "该二叉树不是一个二叉搜索树";
			return false;
		}
		return isBST_Recursion(root->left, min, root->info) && isBST_Recursion(root->right, root->info, max);
	}

};

int main() {
    binaryTree T;
	node* root = T.getRoot();
	T.createTree(root);
	cout << "树的深度:" << T.depth(root) << endl;
	T.print(root);
	cout << "\n===========mid-order recursion===================="<<endl;
	T.isBST(root);
	cout << "\n===========upper and lower bounds recursion====================" << endl;
	if (T.isBST_Recursion(root, LONG_MIN, LONG_MAX)) {
		cout << "这是一颗二叉搜索树" << endl;
	}
	else {
		cout << "这不是一颗二叉搜索树" << endl;
	}
	/*cout << "\n===========DFS recursion====================" << endl;
	T.DeepFirstSearch(root);
	cout << "\n===========BFS QUEUE====================" << endl;
	T.BreadthFirstSearch(root);
	cout << "\n===========BFS recursion====================" << endl;
	T.BreadthFirstSearch_recursion(root);*/
	return 0;
}

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

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

相关文章

Web,Sip,Rtsp,Rtmp,WebRtc,专业MCU融屏视频混流会议直播方案分析

随着万物互联&#xff0c;视频会议直播互动深入业务各方面&#xff0c;主流SFU并不适合管理&#xff0c;很多业务需要各种监控终端&#xff0c;互动SIP硬件设备&#xff0c;Web在线业务平台能相互融合&#xff0c;互联互通&#xff0c; 视频混流直播&#xff0c;录存直播推广&a…

带环链表问题

带环链表就是字面意思带环的链表&#xff0c;例如以下这三种情况 练习题 1.给定一个链表&#xff0c;判断链表中是否带环. - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a;快慢指针&#xff0c;慢指针走一步&#xff0c;快指针走两步&#xff0c;两个指针从链表的起…

硅片和SOI哪个研究方向更好?

知识星球&#xff08;星球名&#xff1a;芯片制造与封测社区&#xff0c;星球号&#xff1a;63559049&#xff09;里的学员问&#xff1a;我研一将要结束&#xff0c;即将进入课题组。我们课题组方向有硅片和soi两种方向&#xff0c;这两种方向该如何选择呢&#xff1f; 硅片与…

python离线安装包的方法

python离线安装包的方法 访问对应安装包的镜像文件的网站找到适合自己的whl文件安装 访问对应安装包的镜像文件的网站 https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple/<包名>/找到适合自己的whl文件 安装 下载完成后&#xff0c;进入opencv_python-3.4.11.45-c…

这是一个简单网站,后续还会更新

1、首页效果图 代码 <!DOCTYPE html> <html> <head> <meta charset"utf-8" /> <title>爱德照明网站首页</title> <style> /*外部样式*/ charset "utf-8"…

标准降水指数(SPI)、标准化降水蒸发蒸腾指数(SPEI)和帕尔默干旱指数(PDSI)的下载、读取和可视化

数据下载网址&#xff1a;WWDT Data (dri.edu)https://wrcc.dri.edu/wwdt/data/PRISM/ 以SPI为例说明&#xff0c; 标准化降水指数(Standardized Precipitation Index, SPI)是由Mckee et al(.1993)分析美国科罗拉多干旱时,发现降水服从偏态分布,基于此提出了标准化降水指数。…

【千帆平台】使用AppBuilder三步手搓应用创建精准多轮对话agent之K12互动式练习题

欢迎来到《小5讲堂》 这是《千帆平台》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 前言创建应用应用头像应用名称应用描述角色指令能力扩展开场白 …

gitlab设置保护分支

gitlab设置保护分支方法 进入代码仓库首页&#xff0c;找到settings下的repository并点击进入 找到Protected Branches 下的Exoand按钮&#xff0c;并点击展开 可以看到已经存在默认的保护分支&#xff0c;通常是master/main分支&#xff0c;也可以添加新的保护分支 新建保护分…

使用idm下载百度云被限速 idm下载大文件后要整合 idm下载百度网盘有限制最新解决办法教程 idm限速解除方法

Internet Download Manager简称IDM,是一款Windows系统专业下载加速工具,IDM下载器支持多种类型文件下载,并能完美恢复各种中断的下载任务,是一款Windows平台下的多线程下载器&#xff0c;支持浏览器自动嗅探功能下载资源文件&#xff0c;包括视频、音频以及图片等类型文件&…

BUUCTF:Web 解析(一)

一、[极客大挑战 2019] EasySQL 点击链接进入靶场 登录页面&#xff0c;查看页面源代码发现没留注释 先输入 admin or 11# 提交看看&#xff08;根据题意猜测考察的 SQL 注入&#xff09; 显示 Flag 二、[极客大挑战 2019] Havefun 打开靶场 页面只有一只猫&#xff0c;打开…

区块链 | IPFS:Merkle DAG(进阶版)

&#x1f98a;原文&#xff1a;Merkle DAGs: Structuring Data for the Distributed Web &#x1f98a;写在前面&#xff1a;本文属于搬运博客&#xff0c;自己留存学习。 1 Merkle DAG 当我们在计算机上表示图时&#xff0c;必须通过提供节点和边的具体表示来编码我们的数据…

jenkins 部署springboot 项目

文章目录 持续集成指定tag发布 基于Jenkins拉取GitLab的SpringBoot代码进行构建发布到测试环境实现持续集成 基于Jenkins拉取GitLab指定发行版本的SpringBoot代码进行构建发布到生产环境实现CD实现持续部署 持续集成 为了让程序代码可以自动推送到测试环境基于Docker服务运行…

服务网关GateWay原理

文章目录 自动装配核心类GatewayAutoConfigurationDispatcherHandler请求处理阶段apply方法httpHandler#handle方法WebHandler#handle方法DispatchHanlder#handle方法第一步 getHandler获取请求映射第二步 invokeHandler 请求适配第三步 handleResult请求处理总结 上一篇博文我…

C语言二叉树和堆

二叉树基础知识&#xff1a; 1.栈、队列和顺序表都是线性结构 但是二叉树不是&#xff0c;二叉树是多分支结构 2.任何一棵树都可以拆分为子树和根节点&#xff0c;许多二叉树的相关问题都是用分治的思想进行函数的递归进行解决。 例&#xff1a;前序&#xff0c;中序&#x…

社交媒体数据恢复:推特、Twitter

推特&#xff08;Twitter&#xff09;数据恢复&#xff1a;如何找回丢失的内容 随着社交媒体的普及&#xff0c;越来越多的人开始使用推特&#xff08;Twitter&#xff09;来分享生活点滴、发表观点和获取信息。然而&#xff0c;有时候我们会不小心删除了重要的推文&#xff0…

【牛客网】排列计算

原题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 如果直接涂色来计算单点权重&#xff0c;2e5*2e5必然超时。 所以用差分进行优化。 3. 代码实现 #include<bits/stdc.h> using name…

漏洞扫描神器:Nessus 保姆级教程(附破解步骤)

一、介绍 Nessus是一款广泛使用的网络漏洞扫描工具&#xff0c;用于发现和评估计算机系统和网络中的安全漏洞。它是一款功能强大的商业工具&#xff0c;由Tenable Network Security开发和维护。 以下是Nessus的一些主要特点和功能&#xff1a; 1. 漏洞扫描&#xff1a;Nessu…

来一篇错题集(虽然简单吧)

一.Assembly via Remainders #include<bits/stdc.h> using namespace std; typedef long long ll; int a[2000]; int b[2000]; int main(){int t;cin>>t;while(t--){int n;cin>>n;for(int i1;i<n-1;i){cin>>b[i];}int x1000000000;//使用1000000000…

241 基于matlab的Dijkstra算法进行路径规划

基于matlab的Dijkstra算法进行路径规划。可根据实际情况输入障碍物和起止点坐标信息&#xff1b; 输出避碰最短路径&#xff1b; 能够利用切线图算法对障碍物区域进行环境建模&#xff0c;设置障碍物的位置和区域。利用Dijkstra算法进行路径规划。程序已调通&#xff0c;可直接…

uniapp实现点击事件跳转页面

首先定义一个点击事件 这里采用的vue3的写法&#xff0c;然后写上触发事件后要跳转的路径 function jump() {uni.switchTab({url:/pages/bangong/index})} 到这里就简单的实现uniapp的点击跳转页面了