層次遍歷二叉樹-三種不同的方法
阿新 • • 發佈:2019-02-03
給定一棵二叉樹,要求進行分層遍歷,每層的節點值單獨列印一行,下圖給出事例結構:
對此二叉樹遍歷的結果應該是:
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的時候,我們就結束迴圈,說明沒有節點可以列印了。
以上的方法可以很清楚的看出,存在重複訪問的情況,就是第0層訪問的次數最多,第1層次之。所以這個遞迴的方法不是很有效的方法。void print_by_level_1(Tree T) { int i = 0; for (i = 0; ; i++) { if (!print_at_level(T, i)) break; } cout << endl; }
第二種方法:我們可以設定兩個佇列,想象一下佇列的特點,就是先進先出,首先把第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;
}