数据结构与算法(c++)——查找二叉树与中序遍历
查找树ADT——查找二叉树
定义:对于树中的每个节点X,它的左子树中的所有项的值小于X中的项,而它的右子树中所有项的值大于X中的项。
现在给出字段和方法定义(BinarySearchTree.h)
#include <queue>
class BinarySearchTree {
private:
struct Node {
int value;
Node* left;
Node* right;
};
Node* root;
void insert(Node*, int);
void traversal(Node*, std::queue<int>&);
bool checkNode(Node*, int);
int findRoot(Node*, int, int);
public:
BinarySearchTree() : root(nullptr) {};
void insert(int);
std::queue<int> traversal();
int findRoot(int, int); // 查找两个节点的公共父节点
std::queue<int> morrisTraversal(); // (Morris方法)不使用递归和栈遍历二叉树
};
查找二叉树的遍历可以采用遍历和非遍历两种算法。
一、添加元素(insert)
现在假设要添加这样一组整数10,7,2,6,13,11,17,3。按照顺序形成的查找二叉树应该如下图:
算法实现:
void BinarySearchTree::insert(int val) {
Node* node = new Node();
node->value = val;
node->left = nullptr;
node->right = nullptr;
if (root == nullptr) {
root = node;
}
else {
insert(root, val);
}
} void BinarySearchTree::insert(Node* node, int val) {
if (val < node->value) {
if (node->left != nullptr) {
insert(node->left, val);
}
else {
Node* chdNode = new Node();
chdNode->value = val;
chdNode->left = nullptr;
chdNode->right = nullptr;
node->left = chdNode;
}
}
else {
if (node->right != nullptr) {
insert(node->right, val);
}
else {
Node* chdNode = new Node();
chdNode->value = val;
chdNode->left = nullptr;
chdNode->right = nullptr;
node->right = chdNode;
}
}
}
二、遍历元素(递归)
查找二叉树的遍历需要采用中序法。即对于树中的每个节点来说首先处理左子树然后处理根节点再处理右子树。
算法实现:
std::queue<int> BinarySearchTree::traversal() {
std::queue<int> q;
if (root != nullptr) {
traversal(root, q);
}
return q;
} void BinarySearchTree::traversal(Node* node, std::queue<int>& q) {
if (node->left != nullptr) {
traversal(node->left, q);
}
q.push(node->value);
if (node->right != nullptr) {
traversal(node->right, q);
}
}
三、查找树中任意两个节点的最小父节点
查找最小父节点的逻辑是对于给出的任意两个节点分别处于根节点的左侧与右侧。若两个节点均处于根节点左侧则向左子树递归遍历,反之,则向右子树递归遍历。如11和17,它们的最小父节点是13。一种例外情况是要求查找的两个节点其中一个是另一个的父节点。如2和3,它们的最小父节点是2。
算法实现:
int BinarySearchTree::findRoot(int a, int b) {
if (checkNode(root, a) && checkNode(root, b)) {
return findRoot(root, a, b);
}
} int BinarySearchTree::findRoot(Node* node, int a, int b) {
if (a<node->value && b>node->value) {
return node->value;
}
else if (a < node->value && b < node->value) {
return findRoot(node->left, a, b);
}
else if (a > node->value && b > node->value) {
return findRoot(node->right, a, b);
}
else {
return a == node->value ? a : b;
}
}
四、遍历元素(不使用递归和栈)
分析:查找二叉树的遍历必须采用中序法,由于不能使用递归和栈。就需要使用特殊算法,能够在处理完X节点的右子树后向上检索到Y节点。如图:
Morris算法的特点就是在处理X节点前,首先找到其最右侧的子树b(b->right == nullptr)。然后建立与Y节点的连接(b->right = Y)。处理完成后再删除临时连接恢复二叉树的原装(b->right = nullptr)
算法实现:
std::queue<int> BinarySearchTree::morrisTraversal() {
std::queue<int> q;
if (root == nullptr) {
return q;
} Node* cur = root;
Node* prev = nullptr; while (cur != nullptr) {
if (cur->left == nullptr) {
q.push(cur->value);
cur = cur->right;
}
else {
prev = cur->left;
while (prev->right != nullptr && prev->right != cur) {
prev = prev->right;
} if (prev->right == nullptr) {
prev->right = cur;
cur = cur->left;
}
else {
prev->right = nullptr;
q.push(cur->value);
cur = cur->right;
}
}
}
return q;
}
数据结构与算法(c++)——查找二叉树与中序遍历的更多相关文章
- 《剑指offer》第八题(重要!查找二叉树的中序遍历的下一个结点)
文件一:main.cpp // 面试题:二叉树的下一个结点 // 题目:给定一棵二叉树和其中的一个结点,如何找出中序遍历顺序的下一个结点? // 树中的结点除了有两个分别指向左右子结点的指针以外,还有 ...
- 数据结构《10》----二叉树 Morris 中序遍历
无论是二叉树的中序遍历还是用 stack 模拟递归, 都需要 O(n)的空间复杂度. Morris 遍历是一种 常数空间 的遍历方法,其本质是 线索二叉树(Threaded Binary Tree), ...
- LeetCode 94:二叉树的中序遍历 Binary Tree Inorder Traversal
题目: 给定一个二叉树,返回它的中序 遍历. Given a binary tree, return the inorder traversal of its nodes' values. 示例: 输 ...
- [LeetCode] Binary Tree Inorder Traversal 二叉树的中序遍历
Given a binary tree, return the inorder traversal of its nodes' values. For example:Given binary tre ...
- LeetCode(94):二叉树的中序遍历
Medium! 题目描述: 给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗 ...
- 【LeetCode题解】94_二叉树的中序遍历
目录 [LeetCode题解]94_二叉树的中序遍历 描述 方法一:递归 Java 代码 Python代码 方法二:非递归 Java 代码 Python 代码 [LeetCode题解]94_二叉树的中 ...
- LeetCode 94. 二叉树的中序遍历(Binary Tree Inorder Traversal)
94. 二叉树的中序遍历 94. Binary Tree Inorder Traversal 题目描述 给定一个二叉树,返回它的 中序 遍历. LeetCode94. Binary Tree Inor ...
- Leetcode题目94.二叉树的中序遍历(中等)
题目描述: 给定一个二叉树,返回它的中序遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 思路解析: 1 ...
- Java实现 LeetCode 94 二叉树的中序遍历
94. 二叉树的中序遍历 给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? / ...
随机推荐
- OC中的copy
copy的概念 Copy的字面意思是"复制"."拷贝",是一个产生副本的过程 对象拷贝的目的:要使用某个对象的数据,但是在修改对象的时候不影响原来的对象内容,常 ...
- Spring装配bean--01组件扫描和自动装配
Spring容器负责创建应用程序中的bean并通过DI来协调这些对象之间的关系 Spring提供了三种主要的装配机制: 在XML中进行显式配置 在Java中进行显式配置 隐式的bean发现机制和自动装 ...
- struts的package的name与namespace
<struts> <constant name="struts.devMode" value="true"></constant& ...
- 调试 Dockerfile - 每天5分钟玩转 Docker 容器技术(15)
包括 Dockerfile 在内的任何脚本和程序都会出错.有错并不可怕,但必须有办法排查,所以本节讨论如何 debug Dockerfile. 先回顾一下通过 Dockerfile 构建镜像的过程: ...
- 微信公众号开发《三》微信JS-SDK之地理位置的获取,集成百度地图实现在线地图搜索
本次讲解微信开发第三篇:获取用户地址位置信息,是非常常用的功能,特别是服务行业公众号,尤为需要该功能,本次讲解的就是如何调用微信JS-SDK接口,获取用户位置信息,并结合百度地铁,实现在线地图搜索,与 ...
- 浅谈RSA加密
RSA背景 在1976年以前,传统的加解密过程是: 1.A采用某种手段对数据进行加密. 2.数据传输到B的手中. 3.B逆向的实施A加密采用的步骤. 4.数据被还原. 这就是所谓的对称加密. 解密和加 ...
- 看完48秒动画,让你不敢再登录HTTP网站(附完整示例代码)
在我的 单点登录SSO示例代码 一文中,强烈不建议部署HTTP的SSO服务站点. 在此写个基于网络包嗅探的HTTP会话劫持程序,给大家一个直观的危害性展示. 示例中,我在一台Mac上登录58同城,被另 ...
- JavaScript window与undefined作为参数的作用
1.原函数 输出结果:1 如图: 2.加window的参数 输出结果:window对象 如图: 注意:此时的window不是全局变量,而是局部变量 3.关于形参必须传window么?当然是不需要的 输 ...
- Java调用IDL方法总结
Java调用IDL方法总结 Java调用IDL程序,需要先在java中加载IDL的java包(javaidlb.jar),该包不需要下载,在IDL的安装目录中可以直接找到(C:\Program Fil ...
- Vmware报错:此主机支持IntelVTx 但IntelVTx处于禁用状态
"此主机支持IntelVTx 但IntelVTx处于禁用状态",报错原因:电脑未开启虚拟化 解决方案: 电脑关机(是关机不是重启)--开机,进BIOS --选择 configura ...