二叉樹遍歷:遞歸+非遞歸+逐層遍歷

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