首页 > 代码库 > 二叉树非递归遍历

二叉树非递归遍历

算法导论: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


二叉树非递归遍历