查找树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. Oracle12c多租户管理用户、角色、权限

    Oracle 数据库 12 c 多租户选项允许单个容器数据库 (CDB) 来承载多个单独的可插拔数据库 (PDB).那么我们如何在容器数据库 (CDB) 和可插拔数据库 (PDB)管理用户权限.背景: ...

  2. IOS对话框UIAlertView

    //修改弹出对话框的样式 alertView.alertViewStyle = UIAlertViewStylePlainTextInput; //根据索引获取指定的某个文本框 [alertView ...

  3. Tp5.0 PHPMailer邮件发送

    今天突然想起来邮件发送,就看了一下PHPmailer,其实这个用起来很简单,都是封装好的 https://github.com/PHPMailer/PHPMailer,直接下载下来之后,把他放入TP5 ...

  4. [转载]PHP文件解压代码

    来自开源中国:

  5. 最简单的代码,CURL获取页面

    function getHTML($url){ $ch = curl_init(); //1.初始化curl curl_setopt($ch,CURLOPT_URL, $url); //2.curl配 ...

  6. Java中线程的实现:

    Java中线程的实现: 一.线程简介: 实现的两种方式为: 1.Thread类 2.Runnable接口 都在java.lang中 都有共通的方法:public void run() 二.线程常用方法 ...

  7. Facade模式——设计模式学习(转载)

    Facade模式 一 意图 为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 二 动机 将一个系统划分成为若干个子系统有利于降低系统的复 ...

  8. Linux 安装USB摄像头

    sudo apt-get update sudo apt-get install fswebcam sudo apt-get install mplayer sudo apt-get install ...

  9. mysqldump备份还原mysql

    本文实现在mysql 5.7 解压版为例子 1.在window上简单试下一个例子 1.使用管理员权限打开cmd命名行,并切换到mysqldump执行程序下

  10. spring-定时器(2)

    Spring提供的三种定时任务机制及其比较 定时任务的需求在众多应用系统中广泛存在,在Spring中,我们可以使用三种不同的定时机制,下面一一描述并加以比较 1. 基于Quartz的定时机制 下面详细 ...