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

原创 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  

算法之二叉树各种遍历

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

二叉树 逐层遍历

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

二叉树的三种遍历,递归非递归,按层。

  • 2013年12月07日 10:27
  • 4KB
  • 下载

数据结构 利用循环队列层次遍历一棵二叉树 递归实现

利用循环队列层次遍历一棵二叉树 递归实现 代码实现: #include ///循环队列实现层次遍历二叉树 #include #include #define Maxsize 100 #de...
  • PNAN222
  • PNAN222
  • 2016年04月25日 10:34
  • 743

用递归方法对二叉树进行层次遍历

用递归方法对二叉树进行层次遍历       在这里看到了这个题。层次遍历是用队列,一级一级地入队列然后输出。而用递归的话,我首先想到是用两个栈来模拟队列,在递归遍历二叉树的过程中入栈,然后最...
  • jfkidear
  • jfkidear
  • 2016年10月24日 23:00
  • 1127

二叉树按层次遍历的递归用法

对于在学数据结构的大家,在编写二叉树的按层次遍历时往往会用非递归的方法,或许有人会问可不可以用递归来做呢? 对此,小编的答案是可以的。 相对于非递归,递归稍微要复杂些(这是由于二叉树中递归左子树递归右...
  • YaoDeBiAn
  • YaoDeBiAn
  • 2016年06月07日 22:15
  • 2484

二叉树的三种遍历练习题

一 二叉树的基础问题
  • XSF50717
  • XSF50717
  • 2014年10月11日 20:10
  • 5631

二叉树之层次遍历

下面是对层次遍历的一个实例,如果对二叉树不太了解请点击这里 任务要求:输入一棵二叉树,进行层次遍历,每个节点都按照从根节点到他的移动序列给出(L表示左,R表示右)。在输入中,每个节点的左右括号之间没有...
  • luomingjun12315
  • luomingjun12315
  • 2015年04月23日 09:16
  • 14301

看懂二叉树的三种遍历

二叉树的遍历分为以下三种: 先序遍历:遍历顺序规则为【根左右】 中序遍历:遍历顺序规则为【左根右】 后序遍历:遍历顺序规则为【左右根】 什么是【根左右】?就是先遍历根,再遍历左孩子,最后遍历右...
  • soundwave_
  • soundwave_
  • 2016年11月10日 21:08
  • 10337

图解二叉树及二叉树遍历

二叉树及二叉树遍历 完全二叉树 二叉树的遍历 遍历的性质 1、完全二叉树 对于一棵具有n个节点的二叉树(按层序编号),如果编号为i的节点与同样深度的满二叉树中编号为i的节点在二叉树的位置完全相同,...
  • xiaotan2011929
  • xiaotan2011929
  • 2017年03月11日 20:53
  • 1623
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:二叉树遍历:递归+非递归+逐层遍历
举报原因:
原因补充:

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