非递归实现二叉树的遍历

二叉树遍历是树的最基本算法之一,是二叉树上进行其它运算之基础。

所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。

访问结点所做的操作依赖于具体的应用问题。

① 前序遍历(PreorderTraversal亦称(先序遍历))

——访问根结点的操作发生在遍历其左右子树之前。

② 中序遍历(InorderTraversal)

——访问根结点的操作发生在遍历其左右子树之中(间)。

③ 后序遍历(PostorderTraversal)

——访问根结点的操作发生在遍历其左右子树之后。

④ 层次遍历(LevelTraversal)

——访问从根结点开始,逐层访问

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Stack;

//二叉树的链式结构
class TreeNode {
	int val;
	TreeNode left;
	TreeNode right;

	TreeNode(int x) {
		val = x;
	}
}

public class TestTraversalTreeNode {
	/**
	 * 线序遍历
	 *
	 * @param root   树根
	 * @return
	 */
	public static ArrayList<Integer> preorderTraversal(TreeNode root) {
		ArrayList<Integer> result = new ArrayList<Integer>();
		if (root == null)
			return result;
		Stack<TreeNode> stack = new Stack<TreeNode>();
		stack.push(root);
		while (!stack.isEmpty()) {
			TreeNode t = stack.pop();
			result.add(t.val);
			//先检查push右结点
			if (t.right != null) {
				stack.push(t.right);
			}
			if (t.left != null) {
				stack.push(t.left);
			}
		}
		return result;
	}

	/**
	 * 中序遍历
	 *
	 * @param root   树根
	 * @return
	 */
	public static ArrayList<Integer> inorderTraversal(TreeNode root) {
		ArrayList<Integer> result = new ArrayList<Integer>();
		if (root == null)
			return result;
		Stack<TreeNode> stack = new Stack<TreeNode>();
		TreeNode p = root;
		//如果有左结点则一直push
		while (!stack.isEmpty() || p != null) {
			if (p != null) {
				stack.push(p);
				p = p.left;
			} else {
				TreeNode n = stack.pop();
				result.add(n.val);
				p = n.right;
			}
		}
		return result;
	}

	/**
	 * 后序遍历
	 *
	 * @param root  树根
	 * @return
	 */
	public static ArrayList<Integer> postorderTraversal(TreeNode root) {
		ArrayList<Integer> result = new ArrayList<Integer>();
		if (root == null) {
			return result;
		}
		Stack<TreeNode> stack = new Stack<TreeNode>();
		stack.push(root);
		TreeNode prev = null;// 记录当前结点的上一个结点
		while (!stack.empty()) {
			TreeNode curr = stack.peek();
			// 查看当前结点是否是叶节点,是的话就访问
			if (prev == null || prev.left == curr || prev.right == curr) {
				if (curr.left != null) {
					stack.push(curr.left);
				} else if (curr.right != null) {
					stack.push(curr.right);
				} else {// 当前结点是叶节点
					stack.pop();
					result.add(curr.val);
				}
				// 查看prev是否是的当前结点左结点
			} else if (curr.left == prev) {
				if (curr.right != null) {
					stack.push(curr.right);
				} else {
					stack.pop();
					result.add(curr.val);
				}
				// 查看prev是否是当前结点的右结点
			} else if (curr.right == prev) {
				stack.pop();
				result.add(curr.val);
			}
			prev = curr;
		}
		return result;
	}

	/**
	 * 层次遍历
	 *
	 * @param root  树根
	 * @return
	 */
	public static ArrayList<Integer> levelTraversal(TreeNode root) {
		ArrayList<Integer> result = new ArrayList<Integer>();
		LinkedList<TreeNode> current = new LinkedList<TreeNode>();
		if (root != null) {
			current.add(root);
			result.add(root.val);
		}
		while (current.size() > 0) {
			LinkedList<TreeNode> parents = current;
			current = new LinkedList<TreeNode>();
			for (TreeNode parent : parents) {
				if (parent.left != null) {
					current.add(parent.left);
					result.add(parent.left.val);
				}
				if (parent.right != null) {
					current.add(parent.right);
					result.add(parent.right.val);
				}
			}
		}
		return result;
	}

	/**
	 * 遍历二叉树的第k行
	 *
	 * @param root 二叉树根
	 * @param k 第k行
	 * @return 第k行的遍历
	 */
	public static String findLevelList2(TreeNode root, int k) {
		ArrayList<LinkedList<TreeNode>> result = new ArrayList<LinkedList<TreeNode>>();
		LinkedList<TreeNode> current = new LinkedList<TreeNode>();
		if (root != null) {
			current.add(root);
		}
		int count = 0;
		while (current.size() > 0) {
			result.add(current);
			if (count == k) {
				return listToString(current);
			}
			count++;
			LinkedList<TreeNode> parents = current;
			current = new LinkedList<TreeNode>();
			for (TreeNode parent : parents) {
				if (parent.left != null) {
					current.add(parent.left);
				}
				if (parent.right != null) {
					current.add(parent.right);
				}
			}
		}
		return null;
	}

	/**
	 * 链表的结点转化为字符串进行输出
	 * @param list
	 * @return
	 */
	public static String listToString(LinkedList<TreeNode> list) {
		int[] arr = new int[list.size()];
		int i = 0;
		for (TreeNode node : list) {
			arr[i] = node.val;
			i++;
		}
		return Arrays.toString(arr);
	}

	public static void main(String[] args) {
		TreeNode root = new TreeNode(1);
		root.left = new TreeNode(2);
		root.right = new TreeNode(3);
		root.left.left = new TreeNode(4);
		root.left.right = new TreeNode(5);
		System.out.println("前序:" + preorderTraversal(root).toString());
		System.out.println("中序:" + inorderTraversal(root).toString());
		System.out.println("后序:" + postorderTraversal(root).toString());
		System.out.println("顺序:" + levelTraversal(root).toString());
		System.out.println("K序:" + findLevelList2(root, 2));
	}
}
时间: 2024-10-28 07:58:44

非递归实现二叉树的遍历的相关文章

非递归实现二叉树的遍历(前序、中序、后序)

树的定义本是递归定义,所以采用递归的方法实现遍历算法,更加让人理解,且代码简单方便.若采用非递归的方法实现,须得利用栈模拟实现. 栈的特点(后进先出) 非递归实现二叉树的前序遍历: 原理如图所示: 参考代码如下: void _PrevOrder(Node* root)//非递归实现前序遍历 { stack<Node*> s; if(root == NULL) return; s.push(root); while (!s.empty()) { root = s.top(); cout<&

C语言非递归实现二叉树的先序、中序、后序、层序遍历

C语言非递归实现二叉树的先序.中序.后序.层序遍历代码如下: 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <stack> 4 #include <queue> 5 using namespace std; 6 7 //*****二叉树的二叉链表存储表示*****// 8 typedef struct BiNode 9 { 10 char data; 11 struct BiNode *lchil

二叉树的存储方式以及递归和非递归的三种遍历方式

树的定义和基本术语 树(Tree)是n(n>=0)个结点的有限集T,T为空时称为空树,否则它满足如下两个条件: (1)有且仅有一个特定的称为根(Root)的结点: (2)其余的结点可分为m(m>=0)个互不相交的子集T1,T2,T3-Tm,其中每个子集又是一棵树,并称其为子树(Subtree). 树形结构应用实例: 1.日常生活:家族谱.行政组织结构:书的目录 2.计算机:资源管理器的文件夹: 编译程序:用树表示源程序的语法结构: 数据库系统:用树组织信息: 分析算法:用树来描述其执行过程:

二叉树非递归先中后序遍历 及 非递归交换二叉树两个孩子的位置

看到一个非递归交换一个二叉树的左右孩子的位置,于是想实现之,才发现非递归的先中后序遍历都忘记了……于是杂七杂八的写了一些,抄抄资料就实现了,然后实现非递归交换两个孩子的位置还是相当容易的.先直接上代码吧,其实这东西还是得自己写写过一遍的,印象才会更加深刻: #include <iostream> #include <fstream> #include <string> #include <stack> using std::cout; using std::

递归非递归的二叉树遍历(递归前中后,非递归前中后,层次遍历,凹入打印法等)

由于所有的递归算法都可以借助于堆栈转换成循环结构的非递归算法.方法一:形式化模拟转换.方法二:根据要求解问题的特点设计借助于堆栈的循环结构算法.而此次正好是利用第二种按方法求解. 1.1非递归前序遍历: 首先利用下图来设计非递归前序遍历算法思想: 堆栈结构体如下: #define size 100 typedef struct { DataType data[size]; int tag[100]; //这个是在非递归后序中用到 int top : }SeqStack : (1)初始化设置一个堆

[C++]LeetCode: 93 Binary Search Tree Iterator (经典题,非递归的中序遍历)

题目: Implement an iterator over a binary search tree (BST). Your iterator will be initialized with the root node of a BST. Calling next() will return the next smallest number in the BST. Note: next() and hasNext() should run in average O(1) time and u

非递归实现先序遍历 java leecode 提交

写完才知道自己学习都是似是而非啊,大家可以也在leecode上提交代码,纯手写,离开eclipse第一种方式:数据结构书上的,使用栈大概思路.1.不断将根节点的左孩子的左孩子直到为空,在这个过程入栈.2.因为栈顶的节点的左孩子为空,所以栈顶的的节点的左子树肯定访问完毕,所以出栈后直接指向右孩子.其实这里面有个思想迭代和递归的本质相同之处是什么?以后会写一篇我的思考. public class Solution { public List<Integer> preorderTraversal(T

二叉树的遍历:先序中序后序遍历的递归与非递归实现及层序遍历

对于一种数据结构而言,遍历是常见操作.二叉树是一种基本的数据结构,是一种每个节点的儿子数目都不多于2的树.二叉树的节点声明如下: 1 typedef struct TreeNode *PtrToNode; 2 typedef struct TreeNode *BinTree; 3 4 struct TreeNode 5 { 6 int Data; //为简单起见,不妨假设树节点的元素为int型 7 BinTree Left; 8 BinTree Right; 9 }; 二叉树的遍历主要有先序遍历

c++实现二叉树层序、前序创建二叉树,递归非递归实现二叉树遍历

#include <iostream> #include <cstdio> #include <stdio.h> #include <string> #include <queue> #include <stack> using namespace std; class Node{ public : char data; struct Node *lchild,*rchild; }; class BiTree{ public: Nod