数据结构 《22》---- 二叉树三种遍历的迭代器算法

二叉树的三种遍历有递归版本,和迭代版本。本文介绍一种新的思路。

参考了 http://coolshell.cn/articles/9886.html

  • 在许多应用中,我们还需要对遍历本身进行抽象。假如有一个求和的函数sum,我们希望它能应用于链表,数组,二叉树等等不同的数据结构。这时,我们可以抽象出迭代器(Iterator)的概念,通过迭代器把算法和数据结构解耦了,使得通用算法能应用于不同类型的数据结构。

以下给出了三种遍历的迭代器算法。

class Iterator {
public:
  virtual TreeNode* next() = 0;
};

class PreOrderIterator : public Iterator {
public:
  PreOrderIterator(TreeNode * root) {
    if(root) s.push(root);
  }

  virtual TreeNode* next() {
    TreeNode *top(nullptr);
    if(!s.empty()) {
      top = s.top();
      s.pop();

      if(top->right_child)
        s.push(top->right_child);

      if(top->left_child)
        s.push(top->left_child);
    }
    return top;
  }

private:
  stack<TreeNode*> s;
};

class InOrderIterator : public Iterator {
public:
  InOrderIterator(TreeNode * root) {
    while(root) {
      s.push(root);
      root = root->left_child;
    }
  }

  virtual TreeNode* next() {
    TreeNode *top(nullptr);
    TreeNode *cur(nullptr);
    if(!s.empty()) {
      top = cur = s.top();
      s.pop();
      cur = cur->right_child;
      while(cur) {
        s.push(cur);
        cur = cur->left_child;
      }
    }
    return top;
  }

private:
  stack<TreeNode*> s;
};

class PostOrderIterator : public Iterator {
public:
  PostOrderIterator(TreeNode *root): pre(nullptr) {
    while(root) {
      s.push(root);
      root = root->left_child;
    }
  }

  virtual TreeNode* next() {
    TreeNode *cur(nullptr);

    while(cur || !s.empty()) {
      while(cur) {
        s.push(cur);
        cur = cur->left_child;
      }
      cur = s.top(); s.pop();
      if(nullptr == cur->right_child || pre == cur->right_child) {
        //right_child is nullptr or already visited
        pre = cur;
        return cur;
      }
      else {
        s.push(cur);
        cur = cur->right_child;
      }
    }
    return nullptr;
  }

private:
  TreeNode *pre; //previously visited node
  stack<TreeNode*> s;
};

上述迭代器的使用方法如下:

PostOrderIterator iter(root);
  TreeNode *node = iter.next();
  while(node) {
    cout << node->value << " ";
    node = iter.next();
  }
  cout << endl;

数据结构 《22》---- 二叉树三种遍历的迭代器算法

时间: 2024-10-11 17:54:01

数据结构 《22》---- 二叉树三种遍历的迭代器算法的相关文章

二叉树三种遍历(递归以及非递归实现)

package com.shiyeqiang.tree; import java.util.Stack; public class BiTree { public static void main(String[] args) { // 首先构造叶子节点 BiTree leafA1 = new BiTree(4); BiTree leafA2 = new BiTree(5); BiTree leafB1 = new BiTree(6); BiTree leafB2 = new BiTree(7)

二叉树三种遍历非递归算法

http://blog.csdn.net/pipisorry/article/details/37353037 c实现: 1.先序遍历非递归算法 #define maxsize 100 typedef struct { Bitree Elem[maxsize]; int top; } SqStack; void PreOrderUnrec(Bitree t) { SqStack s; StackInit(s); p=t; while (p!=null || !StackEmpty(s)) { w

二叉树三种遍历递归及非递归实现(Java)

import java.util.Stack; //二叉树三种遍历递归及非递归实现(Java) public class Traverse { /******************定义二叉树**************************/ private final int MAX_SIZE = 10; //链式存储 public static class BinaryTreeNode { int mValue; BinaryTreeNode mLeft; BinaryTreeNode

关于二叉树三种遍历的相互推导

嗯..跟着陈越姥姥上数据结构,期末考试遇到一道从后序遍历和中序遍历推前序遍历的题,然后硬是不会做,今天突然有了思路,遂记下来: 原题是这样的:一颗二叉树的后序遍历序列是FDEBGCA,中序遍历序列是FDBEACG,那么前序遍历序列是? 思路如下: 根据后序遍历的性质,最后访问的元素一定是根节点,可知该二叉树根节点为A: 根据中序遍历的性质,出现在A前面的一定是A的左子树里面的节点,出现在A后面的一定是A右子树里面的节点.那么我们现在可以确定FDBE一定是A的左子树,CG一定是A的右子树: 根据树

对二叉树三种遍历的理解

二叉树普通的遍历分为三种,分别是前序遍历(先序遍历).中序遍历.后序遍历. 这是从别处拷来的一张图,以此图为例说明: 前序遍历的顺序是:根节点.左节点.右节点. 从第一个根节点A开始为ABE,接下来是B开始,由于B没有左节点,所以遍历为BC:然后是E作为开始遍历为EF,C作为开始遍历为CD,F作为开始遍历为FG,G作为开始遍历为GHK. 将上面的一次关联起来,整个前序遍历即为ABCDEFGHK. 中序遍历的顺序是:左节点.根节点.右节点. 从第一个根节点A作为参照遍历为BAE,B作为参照遍历为B

二叉树三种遍历算法的递归和非递归实现(C++)

struct BinaryTreeNode { int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRight; }; //递归前序遍历 void PreOrder(BinaryTreeNode* pNode) { if(pNode!=NULL) { cout<<pNode->m_nValue<<endl; PreOrder(pNode->m_pLeft); PreOrder(pNode->m_pRi

HDU 1710 二叉树三种遍历

Binary Tree Traversals Problem Description A binary tree is a finite set of vertices that is either empty or consists of a root r and two disjoint binary trees called the left and right subtrees. There are three most important ways in which the verti

java中ArrayList集合的三种遍历方式

public class ListDemo { public static void main(String[] args) { ArrayList<String> mList = new ArrayList<>(); mList.add("郭靖"); mList.add("黄蓉"); mList.add("洪七公"); mList.add("周伯通"); // 第一种遍历方式:普通for循环 for

重温数据结构:二叉树的常见方法及三种遍历方式 Java 实现

读完本文你将了解到: 什么是二叉树 Binary Tree 两种特殊的二叉树 满二叉树 完全二叉树 满二叉树 和 完全二叉树 的对比图 二叉树的实现 用 递归节点实现法左右链表示法 表示一个二叉树节点 用 数组下标表示法 表示一个节点 二叉树的主要方法 二叉树的创建 二叉树的添加元素 二叉树的删除元素 二叉树的清空 获得二叉树的高度 获得二叉树的节点数 获得某个节点的父亲节点 二叉树的遍历 先序遍历 中序遍历 后序遍历 遍历小结 总结 树的分类有很多种,但基本都是 二叉树 的衍生,今天来学习下二