二叉树非递归遍历

算法导论:10.4-3

给定一个 n 结点的二叉树,写出一个 O(n) 时间的非递归过程,将该树每个结点的关键字输出。可以使用一个栈作为辅助数据结构。

栈的实现参考这里

#ifndef	_BINARY_TREE_USE_STACK_H_
#define _BINARY_TREE_USE_STACK_H_

/**************************************************
算法导论:10.4-3

给定一个 n 结点的二叉树,写出一个 O(n) 时间的非递归过程,将该
树每个结点的关键字输出。可以使用一个栈作为辅助数据结构。

基本思路:使用一个栈暂存根结点的左孩子和右孩子节点,
	在下一个循环中将栈中的一个结点弹出作为根结点,如此
	直到栈空。
***************************************************/

#include <iostream>
#include "StackUseSinglyLinkedList.h"

template <class T>
class BinaryTreeUseStack
{
public:
	class Node{
	public:
		friend class BinaryTreeUseStack < T > ;
		T value;
	private:
		Node() :_parent(nullptr), _left(nullptr), _right(nullptr){}
		Node(const T& v) :_parent(nullptr), _left(nullptr), _right(nullptr), value(v){}
		Node* _parent;
		Node* _left;
		Node* _right;
	};

	BinaryTreeUseStack() :_root(nullptr){  }
	// 使用一个数组构造一个完全二叉树,给出数组的头指针和数组的长度
	BinaryTreeUseStack(T*, size_t);
	~BinaryTreeUseStack();

	Node *getRoot()const{ return _root; }

	void print();

private:
	// 二叉树的根结点
	Node* _root;
	// 使用 10.2-2 单链表栈作为辅助数据结构
	StackUseSinglyLinkedList<Node*> _stack;

	void freeNodes(const Node* root);
	void createTree(Node *root, T* a, size_t pos, size_t size);
};

template <class T>
BinaryTreeUseStack<T>::BinaryTreeUseStack(T* a, size_t size){
	_root = new Node(a[0]);
	createTree(_root, a, 0, size);
}

template <class T>
void BinaryTreeUseStack<T>::createTree(Node *root, T* a, size_t pos, size_t size){
	// 将数组中的元素按照顺序加入到二叉树中
	// 左子树坐标,左子数的坐标为 2 * pos + 1
	size_t pos_left = 2 * pos + 1;
	// 右子树坐标,右子树的坐标为 2 * pos + 2
	size_t pos_right = pos_left + 1;
	// 创建根结点
	if (pos_left < size){
		// 创建左子树
		root->_left = new Node(a[pos_left]);
		createTree(root->_left, a, pos_left, size);
	}
	if (pos_right < size){
		// 创建右子树
		root->_right = new Node(a[pos_right]);
		createTree(root->_right, a, pos_right, size);
	}
}

template <class T>
BinaryTreeUseStack<T>::~BinaryTreeUseStack(){
	// 释放所有结点所占空间
	if (_root)
		freeNodes(_root);
}

template <class T>
void BinaryTreeUseStack<T>::freeNodes(const Node* root){
	// 释放左孩子结点
	if (root->_left)
		freeNodes(root->_left);
	// 释放右孩子结点
	if (root->_right)
		freeNodes(root->_right);
	// 释放本结点
	delete root;
}

template <class T>
void BinaryTreeUseStack<T>::print() {
	if (_root){
		_stack.push(_root);
		while (!_stack.empty())
		{
			// 将栈中的一个结点作为根结点,输出其值
			auto root = _stack.pop();
			std::cout << root->value << " ";
			// 分别将这个根结点的左孩子和右孩子压入栈中
			if (root->_right)
				_stack.push(root->_right);
			if (root->_left)
				_stack.push(root->_left);
		}
	}
}

#endif

时间: 2024-08-08 05:20:55

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

数据结构之二叉树篇卷三 -- 二叉树非递归遍历(With Java)

Nonrecursive Traversal of Binary Tree First I wanna talk about why should we use <code>Stack</code> to implement this algorithm. I think it is due to the FILO feature of Stack, and that really matters and makes sense when you get around with t

6)二叉树非递归遍历

1)  我们举例子的图片还是这张图片: 2)然后  我们讲解一下 普通的先序遍历 (1)首先有一个栈,来存节点信息 (2)然后我们是按照先序遍历的,首先存的是A,我们将A入栈时,同时给这个节点加一个标志  就是FALSE (3)然后将A的左子树和右子树也入栈,因为先序是DLR,要是你想按照这个顺序输出,就得是按照RLD的顺序入栈,同时将A的标志由FALSE改为TRUE,现在栈的顺序就是 (4)然后就是将B出栈,同时改为TRUE,同时将B的左子树和右子树入栈,现在栈的顺序是: 5)然后就是C---

【转】更简单的非递归遍历二叉树的方法

解决二叉树的很多问题的方案都是基于对二叉树的遍历.遍历二叉树的前序,中序,后序三大方法算是计算机科班学生必写代码了.其递归遍历是人人都能信手拈来,可是在手生时写出非递归遍历恐非易事.正因为并非易事,所以网上出现无数的介绍二叉树非递归遍历方法的文章.可是大家需要的真是那些非递归遍历代码和讲述吗?代码早在学数据结构时就看懂了,理解了,可为什么我们一而再再而三地忘记非递归遍历方法,却始终记住了递归遍历方法? 三种递归遍历对遍历的描述,思路非常简洁,最重要的是三种方法完全统一,大大减轻了我们理解的负担.

二叉树学习之非递归遍历

二叉树递归遍历可谓是学过数据结构的同仁都能想一下就能写出来,但在应聘过程我们常常遇到的是写出一个二叉树非递归遍历函数,接着上篇文章写二叉树的非递归遍历,先难后易,一步一步的来. 先上代码: #include "binarytree.h" #include <stack> #include <queue> #ifndef RECU #warning("RECU is not defined") /** *前序遍历(根左右) * *1.当前节点为

数据结构二叉树的递归与非递归遍历之 实现可编译(1)java

前一段时间,学习数据结构的各种算法,概念不难理解,只是被C++的指针给弄的犯糊涂,于是用java,web,javascript,分别去实现数据结构的各种算法. 二叉树的遍历,本分享只是以二叉树中的先序遍历为例进行说明,中序遍历和后序遍历,以此类推! 二叉树递归与非递归遍历的区别,虽然递归遍历,跟容易读懂,代码量少,运算快,但是却容易出现溢出的问题,所以所以非递归遍历,在处理千万级的运算量时会先的很有用处. 二叉树的先序遍历:先访问根节点,再访问先后访问左右节点.如图: 二叉树的递归遍历之java

二叉树的非递归遍历--京东2015笔试回忆

题目回忆: C/C++研发试卷:偏重于数据结构的考察,编程题有2题+1题附加题: 1.输入整数n,求m,m>9,m中各个数位的乘积=n的最小整数;如n=36,m=49; 2.二叉树前序遍历的非递归实现(本文的总结) 3.求第n个数,这个序列满足(2^i)*(3^j)*(5^k),前7个为:2,3,4,5,6,8,10 .... 小题有基本的数据结构.程序运行结果.SQL题目. 4.删除表格用DROP命令,死锁产生的条件: 4.1互斥使用(资源独占) 一个资源每次只能给一个进程使用 4.2.不可强

数据结构——二叉树遍历之“递归与非递归遍历”

简述 二叉树的遍历分为先序遍历.中序遍历和后序遍历.如下图所示: 递归遍历 private void bianli1(List<Integer> list, TreeNode root) { // 先序遍历 if (root == null) { return; } list.add(root.val); bianli1(list, root.left); bianli1(list, root.right); } private void bianli2(List<Integer>

JAVA递归、非递归遍历二叉树(转)

原文链接: JAVA递归.非递归遍历二叉树 import java.util.Stack; import java.util.HashMap; public class BinTree { private char date; private BinTree lchild; private BinTree rchild; public BinTree(char c) { date = c; } // 先序遍历递归 public static void preOrder(BinTree t) {

史上最简明易懂非递归遍历二叉树算法

巧若拙(欢迎转载,但请注明出处:http://blog.csdn.net/qiaoruozhuo) 遍历二叉树的递归函数是体现了算法之美的高妙算法,思路清晰,代码简洁,读之赏心悦目.代码例如以下: 程序代码: void PreOrderTraverse_R(BiTree BT)//採用递归方式先序遍历二叉树BT { if(BT != NULL) { printf("%c", BT->data);//输出该结点(根结点) PreOrderTraverse_R(BT->lchi