查找树ADT——查找二叉树

定义:对于树中的每个节点X,它的左子树中的所有项的值小于X中的项,而它的右子树中所有项的值大于X中的项。

现在给出字段和方法定义(BinarySearchTree.h)

  1. #include <queue>
  2. class BinarySearchTree {
  3. private:
  4. struct Node {
  5. int value;
  6. Node* left;
  7. Node* right;
  8. };
  9. Node* root;
  10. void insert(Node*, int);
  11. void traversal(Node*, std::queue<int>&);
  12. bool checkNode(Node*, int);
  13. int findRoot(Node*, int, int);
  14. public:
  15. BinarySearchTree() : root(nullptr) {};
  16. void insert(int);
  17. std::queue<int> traversal();
  18. int findRoot(int, int); // 查找两个节点的公共父节点
  19. std::queue<int> morrisTraversal(); // (Morris方法)不使用递归和栈遍历二叉树
  20. };

查找二叉树的遍历可以采用遍历和非遍历两种算法。

一、添加元素(insert)

现在假设要添加这样一组整数10,7,2,6,13,11,17,3。按照顺序形成的查找二叉树应该如下图:

算法实现:

  1. void BinarySearchTree::insert(int val) {
  2. Node* node = new Node();
  3. node->value = val;
  4. node->left = nullptr;
  5. node->right = nullptr;
  6. if (root == nullptr) {
  7. root = node;
  8. }
  9. else {
  10. insert(root, val);
  11. }
  12. }
  13.  
  14. void BinarySearchTree::insert(Node* node, int val) {
  15. if (val < node->value) {
  16. if (node->left != nullptr) {
  17. insert(node->left, val);
  18. }
  19. else {
  20. Node* chdNode = new Node();
  21. chdNode->value = val;
  22. chdNode->left = nullptr;
  23. chdNode->right = nullptr;
  24. node->left = chdNode;
  25. }
  26. }
  27. else {
  28. if (node->right != nullptr) {
  29. insert(node->right, val);
  30. }
  31. else {
  32. Node* chdNode = new Node();
  33. chdNode->value = val;
  34. chdNode->left = nullptr;
  35. chdNode->right = nullptr;
  36. node->right = chdNode;
  37. }
  38. }
  39. }

二、遍历元素(递归)

查找二叉树的遍历需要采用中序法。即对于树中的每个节点来说首先处理左子树然后处理根节点再处理右子树。

算法实现:

  1. std::queue<int> BinarySearchTree::traversal() {
  2. std::queue<int> q;
  3. if (root != nullptr) {
  4. traversal(root, q);
  5. }
  6. return q;
  7. }
  8.  
  9. void BinarySearchTree::traversal(Node* node, std::queue<int>& q) {
  10. if (node->left != nullptr) {
  11. traversal(node->left, q);
  12. }
  13. q.push(node->value);
  14. if (node->right != nullptr) {
  15. traversal(node->right, q);
  16. }
  17. }

三、查找树中任意两个节点的最小父节点

查找最小父节点的逻辑是对于给出的任意两个节点分别处于根节点的左侧与右侧。若两个节点均处于根节点左侧则向左子树递归遍历,反之,则向右子树递归遍历。如11和17,它们的最小父节点是13。一种例外情况是要求查找的两个节点其中一个是另一个的父节点。如2和3,它们的最小父节点是2。

算法实现:

  1. int BinarySearchTree::findRoot(int a, int b) {
  2. if (checkNode(root, a) && checkNode(root, b)) {
  3. return findRoot(root, a, b);
  4. }
  5. }
  6.  
  7. int BinarySearchTree::findRoot(Node* node, int a, int b) {
  8. if (a<node->value && b>node->value) {
  9. return node->value;
  10. }
  11. else if (a < node->value && b < node->value) {
  12. return findRoot(node->left, a, b);
  13. }
  14. else if (a > node->value && b > node->value) {
  15. return findRoot(node->right, a, b);
  16. }
  17. else {
  18. return a == node->value ? a : b;
  19. }
  20. }

四、遍历元素(不使用递归和栈)

分析:查找二叉树的遍历必须采用中序法,由于不能使用递归和栈。就需要使用特殊算法,能够在处理完X节点的右子树后向上检索到Y节点。如图:

Morris算法的特点就是在处理X节点前,首先找到其最右侧的子树b(b->right == nullptr)。然后建立与Y节点的连接(b->right = Y)。处理完成后再删除临时连接恢复二叉树的原装(b->right = nullptr)

算法实现:

  1. std::queue<int> BinarySearchTree::morrisTraversal() {
  2. std::queue<int> q;
  3. if (root == nullptr) {
  4. return q;
  5. }
  6.  
  7. Node* cur = root;
  8. Node* prev = nullptr;
  9.  
  10. while (cur != nullptr) {
  11. if (cur->left == nullptr) {
  12. q.push(cur->value);
  13. cur = cur->right;
  14. }
  15. else {
  16. prev = cur->left;
  17. while (prev->right != nullptr && prev->right != cur) {
  18. prev = prev->right;
  19. }
  20.  
  21. if (prev->right == nullptr) {
  22. prev->right = cur;
  23. cur = cur->left;
  24. }
  25. else {
  26. prev->right = nullptr;
  27. q.push(cur->value);
  28. cur = cur->right;
  29. }
  30. }
  31. }
  32. return q;
  33. }

参考代码

数据结构与算法(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. openlayers应用“四”:百度地图纠偏续

    续前一篇,上一篇提到百度地图纠偏的基本思路,经过经过一天的努力,实现了百度地图坐标偏移参数的提取,步骤以及实现效果如下: 1.数据来源:四川省的省道矢量数据 2.提取坐标偏移参数的过程如下: A.将四 ...

  2. 关于IT创业和反思

    2016年8月的某一天本是世上平凡的一天,对于我而言却并不平凡. 这一天,我离开了待了近四年的创业公司.从它成立前的筹备开始,伴随着它的起起伏伏到完成C轮融资,从来没想过以这种方式离开,然而人生总是充 ...

  3. leetcode contest 20

    Q1: 520. Detect Capital Given a word, you need to judge whether the usage of capitals in it is right ...

  4. W10上面DOSBOX安装

    第一步:下载好MASM.exe.debug.exe.link.exe.将其放在根目录下面.我们以后自己编写的汇编代码也是在此目录下.如图: 第二步:我这里的文件夹名称是Assembly那么这个也就是待 ...

  5. JS立即执行函数表达式(IIFE)

    原文为 http://benalman.com/news/2010/11/immediately-invoked-function-expression/#iife ----------------- ...

  6. [笔记]ACM笔记 - 利用FFT求卷积(求多项式乘法)

    卷积 给定向量:, 向量和: 数量积(内积.点积): 卷积:,其中 例如: 卷积的最典型的应用就是多项式乘法(多项式乘法就是求卷积).以下就用多项式乘法来描述.举例卷积与DFT. 关于多项式 对于多项 ...

  7. SpringMVC构建Restful。

    因为spring是依赖jackson来生成json,需要添加jar包. pom.xml文件添加依赖. <dependency> <groupId>org.codehaus.ja ...

  8. DevCloud让代码检查更科学

    代码检查是软件开发工作中不可或缺的一部分,众所周知,规范化的编码是一个优质项目的保证.华为软件开发云(DevCloud)便提供了专业科学的自动化代码检查工作. 一.华为软件开发云(DevCloud)目 ...

  9. Charles Proxy代理使用简要说明

    1.去官网下载免费试用版: http://www.charlesproxy.com/ (需要机器有Java运行时)或下载破解注册版:http://charles.iiilab.com/,安装后开启默认 ...

  10. webpack的多文件打包问题

    1.第三方库如vue,vue-router可以利用webpack中的entry指定vendor:['vue','vue-router']来打包在一个文件中 2.将这些文件单独提取出来,在页面中使用&l ...