查找树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++)——查找二叉树与中序遍历的更多相关文章

  1. 《剑指offer》第八题(重要!查找二叉树的中序遍历的下一个结点)

    文件一:main.cpp // 面试题:二叉树的下一个结点 // 题目:给定一棵二叉树和其中的一个结点,如何找出中序遍历顺序的下一个结点? // 树中的结点除了有两个分别指向左右子结点的指针以外,还有 ...

  2. 数据结构《10》----二叉树 Morris 中序遍历

    无论是二叉树的中序遍历还是用 stack 模拟递归, 都需要 O(n)的空间复杂度. Morris 遍历是一种 常数空间 的遍历方法,其本质是 线索二叉树(Threaded Binary Tree), ...

  3. LeetCode 94:二叉树的中序遍历 Binary Tree Inorder Traversal

    题目: 给定一个二叉树,返回它的中序 遍历. Given a binary tree, return the inorder traversal of its nodes' values. 示例: 输 ...

  4. [LeetCode] Binary Tree Inorder Traversal 二叉树的中序遍历

    Given a binary tree, return the inorder traversal of its nodes' values. For example:Given binary tre ...

  5. LeetCode(94):二叉树的中序遍历

    Medium! 题目描述: 给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗 ...

  6. 【LeetCode题解】94_二叉树的中序遍历

    目录 [LeetCode题解]94_二叉树的中序遍历 描述 方法一:递归 Java 代码 Python代码 方法二:非递归 Java 代码 Python 代码 [LeetCode题解]94_二叉树的中 ...

  7. LeetCode 94. 二叉树的中序遍历(Binary Tree Inorder Traversal)

    94. 二叉树的中序遍历 94. Binary Tree Inorder Traversal 题目描述 给定一个二叉树,返回它的 中序 遍历. LeetCode94. Binary Tree Inor ...

  8. Leetcode题目94.二叉树的中序遍历(中等)

    题目描述: 给定一个二叉树,返回它的中序遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 思路解析: 1 ...

  9. Java实现 LeetCode 94 二叉树的中序遍历

    94. 二叉树的中序遍历 给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? / ...

随机推荐

  1. 【2017-05-05】timer控件、三级联动、帐号激活权限设置

    一.Timer控件 Timer实际就是一个线程控件. 属性:Enabled    是否被启用 Interval     多长时间执行一次控件中的代码 事件: Tick     事件中放要执行的代码. ...

  2. Oracle的正则应用之匹配出手机号

    按照要求匹配出符合中国大陆手机号规则的数据 --1 表准备create table test_regexp( object varchar2(50)); --2 数据准备 insert into te ...

  3. (5)微信二次开发 之 XML格式数据解析

    1.首先理解一下html html的全名是:HyperText Transfer markup language 超级文本标记语言,html本质上是一门标记(符合)语言,在html里,这些标记是事先定 ...

  4. [刷题]算法竞赛入门经典(第2版) 5-6/UVa1595 - Symmetry

    题意:平面上给若干点,问它们是不是关于某垂直于x轴的直线对称. 代码:(Wrong Answer, –ms) //UVa1595 - Symmetry #include<iostream> ...

  5. Spring BeanFactory源码学习

    一.BeanFactory BeanFactory是Spring IOC容器的基础,是IOC容器的基础接口,所有的容器都是从它这里继承实现而来.BeanFactory提供了最基本的IOC容器的功能,即 ...

  6. 通过分析 JDK 源代码研究 TreeMap 红黑树算法实

    TreeMap和TreeSet是Java Collection Framework的两个重要成员,其中TreeMap是Map接口的常用实现类,而TreeSet是Set接口的常用实现类.虽然HashMa ...

  7. Charles Proxy 4.1.2 破解版

    下载Charles Proxy 4.1.2版本,百度云盘下载 或 去官网下载 安装后先打开Charles一次(Windows版可以忽略此步骤) 在这个网站(http://charles.iiilab. ...

  8. Fragment回调接口应用间分享数据

    package com.example.mydemo; import java.util.List; import android.app.Activity; import android.app.A ...

  9. Linux常用命令-jdk和Tomcat

    一.JDK的安装和配置 1.下载jdk文件 去官方网站下载Linux 64位  jdk-8u131-linux-x64.tar.gz 2.使用Ftp工具上传到/usr/local 下. 使用命令:ta ...

  10. VR全景:电商巨头的角逐

    VR全景智慧城市:京东推"京东梦"挑战淘宝Buy+ ,VR购物谁主沉浮? VR全景智慧城市是国内首家商业全景平台,结合先进VR虚拟现实技术,以线下实体为依托,将空间还原到线上,用户 ...