二叉树遍历:递归+非递归+逐层遍历

原创 2013年12月03日 18:46:39

1. 数据结构及遍历方法定义

/*
 * binarytree.h
 */

#ifndef BINARYTREE_H_
#define BINARYTREE_H_

// 二叉树几点包含的实体数据类型
typedef char elementType;

// 定义而二叉树节点数据结构
struct BinaryTreeNode {
    elementType data;
    BinaryTreeNode* left; // left child
    BinaryTreeNode* right; // right child
};

// 二叉树及节点
typedef BinaryTreeNode btNode;

// 二叉树(root节点)
typedef BinaryTreeNode btree;

// 递归先序遍历
void rpre_order(btree*);
// 递归后续遍历
void rpost_order(btree*);
// 递归中序遍历
void rin_order(btree*);

// 非递归前序遍历
void pre_order(btree*);
// 非递归后续遍历
void post_order(btree*);
// 非递归中序遍历
void in_order(btree*);

// 广度优先遍历
void bfs_order(btree*);

// 销毁树
void destory_btree(btree*);

#endif /* BINARYTREE_H_ */

2. 遍历方法实现

2.1 递归遍历

/*
 * BinaryTree.cpp
 */

#include "binarytree.h"
#include <iostream>
#include <malloc.h>
#include <stack>
#include <queue>

using namespace std;

//--------------------------------------------------

// 递归先序遍历
void rpre_order(btree* tree) {
	btNode * p = tree;
	if (NULL == p) {
		return;
	}
	cout << p->data << "  ";
	rpre_order(p->left);
	rpre_order(p->right);
}

// 递归后续遍历
void rpost_order(btree* tree) {
	btNode* p = tree;
	if (NULL == p)
		return;
	rpost_order(p->left);
	rpost_order(p->right);
	cout << p->data << "  ";
}

// 递归中序遍历
void rin_order(btree* tree) {
	btNode* p = tree;
	if (NULL == p)
		return;
	rin_order(p->left);
	cout << p->data << "  ";
	rin_order(p->right);

}


2.2  消除递归

//--------------------------------------------------

// 非递归前序遍历
void pre_order(btree* tree) {
	btNode * p = tree;
	if (NULL == p)
		return;

	stack<btNode*>* st = new stack<btNode*>();
	st->push(p);
	while (!st->empty()) {
		p = st->top();
		st->pop();
		cout << p->data << "  ";
		if (NULL != p->right) {
			st->push(p->right);
		}
		if (NULL != p->left) {
			st->push(p->left);
		}
	}
	delete st;
}
// 非递归后续遍历
//需要注意的是 : 非递归后序遍历方法相对实现比较困难,主要原因就在于父子节点访问缺乏连续
//              解决思路是将前一个访问节点记忆下来,并判断和当前节点之间的关系再做处理
void post_order(btree* tree) {

	btNode* curr = tree;  // 记录当前执行的节点
	btNode* prev = NULL; // 记录前一个访问的节点
	if (NULL == curr) {
		return;
	}
	stack<btNode*>* st = new stack<btNode*>();
	st->push(curr);
	while (!st->empty()) {
		curr = st->top();
		// 如果该节点没有孩子节点则可以直接访问
		if (NULL == curr->left && NULL == curr->right) {
			cout << curr->data << "  ";
			st->pop();
			prev = curr;
			continue;
		}
		// 如果该节点的孩子节点已经被访问过了,也可直接访问
		if (NULL != prev && (prev == curr->right || prev == curr->left)) {
			cout << curr->data << "  ";
			st->pop();
			prev = curr;
			continue;
		}

		// 除了上述情况则需要将孩子节点入栈
		if (NULL != curr->right) {
			st->push(curr->right);
		}
		if (NULL != curr->left) {
			st->push(curr->left);
		}
	}

	delete st;
}

// 非递归中序遍历
void in_order(btree* tree) {
	btNode* p = tree;
	if (NULL == p)
		return;

	stack<btNode*>* st = new stack<btNode*>();
	while (NULL != p || !st->empty()) {
		while (NULL != p) {
			st->push(p);
			p = p->left;
		}
		if (!st->empty()) {
			p = st->top();
			st->pop();
			cout << p->data << "  ";
			p = p->right;
		}
	}
	delete st;
}

2.3 逐层遍历

//--------------------------------------------------
// 广度优先
void bfs_order(btree* tree) {
	btNode* p = tree;
	if (NULL == p) {
		return;
	}

	queue<btNode*> * qu = new queue<btNode*>();
	qu->push(p);

	while (!qu->empty()) {
		p = qu->front();
		qu->pop();
		cout << p->data << "  ";
		if (NULL != p->left) {
			qu->push(p->left);
		}
		if (NULL != p->right) {
			qu->push(p->right);
		}
	}
	delete qu;
}


//--------------------------------------------------

// 销毁二叉树
void destory_btree(btree* tree) {
	btNode* p = tree;
	if (NULL == p) {
		return;
	}

	queue<btNode*> * qu = new queue<btNode*>();
	qu->push(p);

	while (!qu->empty()) {
		p = qu->front();
		qu->pop();
		if (NULL != p->left) {
			qu->push(p->left);
		}
		if (NULL != p->right) {
			qu->push(p->right);
		}
		free(p);
	}
	delete qu;
}


3. 测试

//============================================================================
// Name        : main.cpp
//============================================================================

#include <iostream>
#include "binarytree.h"
#include <malloc.h>

using namespace std;

btNode* init_tree() {
	btNode* a = (btNode *) malloc(sizeof(btNode));
	a->data = 'A';
	a->left = a->right = NULL;

	btNode* b = (btNode *) malloc(sizeof(btNode));
	b->data = 'B';
	b->left = b->right = NULL;

	btNode* c = (btNode *) malloc(sizeof(btNode));
	c->data = 'C';
	c->left = c->right = NULL;

	btNode* d = (btNode *) malloc(sizeof(btNode));
	d->data = 'D';
	d->left = d->right = NULL;

	btNode* e = (btNode *) malloc(sizeof(btNode));
	e->data = 'E';
	e->left = e->right = NULL;

	btNode* f = (btNode *) malloc(sizeof(btNode));
	f->data = 'F';
	f->left = f->right = NULL;

	btNode* g = (btNode *) malloc(sizeof(btNode));
	g->data = 'G';
	g->left = g->right = NULL;

	btNode* h = (btNode *) malloc(sizeof(btNode));
	h->data = 'H';
	h->left = h->right = NULL;

	btNode* i = (btNode *) malloc(sizeof(btNode));
	i->data = 'I';
	i->left = i->right = NULL;

	a->left = b;
	a->right = c;
	b->right = d;
	c->left = e;
	d->left = f;
	d->right = g;
	e->left = h;
	e->right = i;

	return a;
}

int main() {
	cout << "Binary Tree Test" << endl; // prints Binary Tree Test

	// init tree
	btree * tree = init_tree();

	cout << "Pre order" << endl;
	rpre_order(tree);
	cout << endl;
	pre_order(tree);
	cout << endl;

	cout << "Post order" << endl;
	rpost_order(tree);
	cout << endl;
	post_order(tree);
	cout << endl;

	cout << "In order" << endl;
	rin_order(tree);
	cout << endl;
	in_order(tree);
	cout << endl;

	cout << "BFS order" << endl;
	bfs_order(tree);
	cout << endl;

	//
	destory_btree(tree);

	return 0;
}

测试结果如下:

Binary Tree Test
Pre order
A  B  D  F  G  C  E  H  I  
A  B  D  F  G  C  E  H  I  
Post order
F  G  D  B  H  I  E  C  A  
F  G  D  B  H  I  E  C  A  
In order
B  F  D  G  A  H  E  I  C  
B  F  D  G  A  H  E  I  C  
BFS order
A  B  C  D  E  F  G  H  I  

相关文章推荐

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

二叉树 逐层遍历

题目描述: 从上往下打印出二叉树的每个节点,同层节点从左至右打印。 解决思路: 二叉树见下图,我们要打印的顺序是:1,2,3,4,5,6,7,8,9,10;可以看到我们先要打印根节点,之后打印第...

二叉树(6)----按层遍历二叉树

1、二叉树定义 typedef struct BTreeNodeElement_t_ { void *data; } BTreeNodeElement_t; typedef struct ...

二叉树的层次遍历

题目描述:给出一棵二叉树,返回其节点值的层次遍历(逐层从左往右访问) 样例: 之前,我们已经学习了用非递归的解法解决二叉树的前序遍历,中序遍历,后序遍历。对于这三种深搜的策略,我采用了一种特殊的结...

算法之二叉树各种遍历

树形结构是一类重要的非线性数据结构,其中以树和二叉树最为常用。 二叉树是每个结点最多有两个子树的有序树。通常子树的根被称作“左子树”(left subtree)和“右子树”(right subtree...
  • SJF0115
  • SJF0115
  • 2013年03月07日 04:51
  • 170103

【数据结构与算法】二叉树递归与非递归遍历(附完整源码)

二叉树是一种非常重要的数据结构,很多其他数据机构都是基于二叉树的基础演变过来的。二叉树有前、中、后三种遍历方式,因为树的本身就是用递归定义的,因此采用递归的方法实现三种遍历,不仅代码简洁且容易理解,但...

二叉树遍历(非递归版)

在数据量较小时,和递归版本的时间是差不多的,额因为还没有去看算法的那个计算时间复杂度和空间复杂度的东西,所以对那个不懂,只能用最直观的测试时间来判断速度文件"trees.h"#include usi...

16 - 12 - 23 二叉树遍历的非递归-栈实现

/二叉树遍历之章/
  • SoDaoo
  • SoDaoo
  • 2016年12月20日 12:04
  • 193

算法 二叉树遍历 递归和非递归

前言本篇文章介绍二叉树的几种遍历方法:前序遍历、中序遍历、后序遍历和层序遍历。 包含递归和非递归遍历。二叉树表示结点表示,构造二叉树public class BiNode { public ...

【数据结构】Java实现二叉树遍历(非递归)

以二叉排序树来建立的一棵二叉树,然后用先序,中序,后序非递归遍历package DataStructure;import java.util.Stack; public class BinaryTr...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:二叉树遍历:递归+非递归+逐层遍历
举报原因:
原因补充:

(最多只允许输入30个字)