1. 程式人生 > >層次遍歷二叉樹-三種不同的方法

層次遍歷二叉樹-三種不同的方法

給定一棵二叉樹,要求進行分層遍歷,每層的節點值單獨列印一行,下圖給出事例結構:


對此二叉樹遍歷的結果應該是:

1,

2 , 3

4, 5, 6

7, 8

第一種方法,就是利用遞迴的方法,按層進行列印,我們把根節點當做第0層,之後層次依次增加,如果我們想列印第二層怎麼辦呢,利用遞迴的程式碼如下:

int print_at_level(Tree T, int level) {
	if (!T || level < 0)
		return 0;
	if (0 == level) {
		cout << T->data << " ";
		return 1;
	}
	return print_at_level(T->lchild, level - 1) + print_at_level(T->rchild, level - 1);
}

如果我們成功的列印了給定的層次,那麼就返回非0的正值,如果失敗返回0。有了這個思路,我們就可以應用一個迴圈,來列印這顆樹的所有層的節點,但是有個問題就是我們不知道這棵二叉樹的深度,怎麼來控制迴圈使其結束呢,仔細看一下print_at_level,如果指定的Tree是空的,那麼就直接返回0,當返回0的時候,我們就結束迴圈,說明沒有節點可以列印了。
void print_by_level_1(Tree T) {
	int i = 0; 
	for (i = 0; ; i++) {
		if (!print_at_level(T, i))
			break;
	}
	cout << endl;
}
以上的方法可以很清楚的看出,存在重複訪問的情況,就是第0層訪問的次數最多,第1層次之。所以這個遞迴的方法不是很有效的方法。

第二種方法:我們可以設定兩個佇列,想象一下佇列的特點,就是先進先出,首先把第0層儲存在一個佇列中,然後按節點訪問,並把已經訪問節點的左右孩子節點放在第二個佇列中,當第一個佇列中的所有節點都訪問完成之後,交換兩個節點。這樣重複下去,知道所有層的節點都被訪問,這樣做的代價就是空間複雜度有點高。

void print_by_level_2(Tree T) {
	deque<tree_node_t*> q_first, q_second;
	q_first.push_back(T);
	while(!q_first.empty()) {
		while (!q_first.empty()) {
			tree_node_t *temp = q_first.front();
			q_first.pop_front();
			cout << temp->data << " ";
			if (temp->lchild)
				q_second.push_back(temp->lchild);
			if (temp->rchild)
				q_second.push_back(temp->rchild);
		}
		cout << endl;
		q_first.swap(q_second);
	}
}

第三種方法就是設定雙指標,一個指向訪問當層開始的節點,一個指向訪問當層結束節點的下一個位置:


這是第一層訪問的情況,當訪問第0層之後的結構如下,把第0層的所有子節點加入之後:


訪問完第1層之後:


之後大家就可以自己畫圖了,下面給出程式程式碼:

void print_by_level_3(Tree T) {
	vector<tree_node_t*> vec;
	vec.push_back(T);
	int cur = 0;
	int end = 1;
	while (cur < vec.size()) {
		end = vec.size();
		while (cur < end) {
			cout << vec[cur]->data << " ";
			if (vec[cur]->lchild)
				vec.push_back(vec[cur]->lchild);
			if (vec[cur]->rchild)
				vec.push_back(vec[cur]->rchild);
			cur++;
		}
		cout << endl;
	}
}

最後給出完成程式碼的測試用例:124##57##8##3#6##
#include<iostream>
#include<vector>
#include<deque>
using namespace std;

typedef struct tree_node_s {
	char data;
	struct tree_node_s *lchild;
	struct tree_node_s *rchild;
}tree_node_t, *Tree;

void create_tree(Tree *T) {
	char c = getchar();
	if (c == '#') {
		*T = NULL;
	} else {
		*T = (tree_node_t*)malloc(sizeof(tree_node_t));
		(*T)->data = c;
		create_tree(&(*T)->lchild);
		create_tree(&(*T)->rchild);
	}
}

void print_tree(Tree T) {
	if (T) {
		cout << T->data << " ";
		print_tree(T->lchild);
		print_tree(T->rchild);
	}
}
int print_at_level(Tree T, int level) {
	if (!T || level < 0)
		return 0;
	if (0 == level) {
		cout << T->data << " ";
		return 1;
	}
	return print_at_level(T->lchild, level - 1) + print_at_level(T->rchild, level - 1);
}

void print_by_level_1(Tree T) {
	int i = 0; 
	for (i = 0; ; i++) {
		if (!print_at_level(T, i))
			break;
	}
	cout << endl;
}

void print_by_level_2(Tree T) {
	deque<tree_node_t*> q_first, q_second;
	q_first.push_back(T);
	while(!q_first.empty()) {
		while (!q_first.empty()) {
			tree_node_t *temp = q_first.front();
			q_first.pop_front();
			cout << temp->data << " ";
			if (temp->lchild)
				q_second.push_back(temp->lchild);
			if (temp->rchild)
				q_second.push_back(temp->rchild);
		}
		cout << endl;
		q_first.swap(q_second);
	}
}

void print_by_level_3(Tree T) {
	vector<tree_node_t*> vec;
	vec.push_back(T);
	int cur = 0;
	int end = 1;
	while (cur < vec.size()) {
		end = vec.size();
		while (cur < end) {
			cout << vec[cur]->data << " ";
			if (vec[cur]->lchild)
				vec.push_back(vec[cur]->lchild);
			if (vec[cur]->rchild)
				vec.push_back(vec[cur]->rchild);
			cur++;
		}
		cout << endl;
	}
}

int main(int argc, char *argv[]) {
	Tree T = NULL;
	create_tree(&T);
	print_tree(T);
	cout << endl;
	print_by_level_3(T);
	cin.get();
	cin.get();
	return 0;
}