1.問題定義
給定一棵二叉樹,要求按分層遍歷該二叉樹,即從上到下按層次訪問該二叉樹(每一層將單獨輸出一行),每一層要求訪問的順序爲從左到右,並將節點依次編號。 要求遍歷輸出的結果分別爲圖2,圖3和圖4,其中圖3和圖4是擴展問題。
圖1 圖2 圖3 圖4
2.原問題
編程之美書上,採用的是容器構成的數組來實現的,相比於遞歸算法,時間複雜度大大降低,僅爲O(n),但其空間複雜度並非最優。此處採用STL中的Queue來解決此問題,代碼如下:
節點數據:
struct node
{
char value;
node* pleft;
node* pright;
};
實現代碼:
queue<node*> Queue3;//------------------使用系統的STL的queue
void cengxu3(node* root)
{
node *temp;
Queue3.push(root);
int len=Queue3.size();
int cur=0;
while(!Queue3.empty())
{
while(cur++<len)//cur++,注意一些小的邏輯
{
temp=Queue3.front();
Queue3.pop();
cout<<temp->value<<" ";
if (temp->pleft)
Queue3.push(temp->pleft);
if (temp->pright)
Queue3.push(temp->pright);
}
cout<<endl;
cur=0;
len=Queue3.size();
}
}
分析總結:
該法中採用隊列,將已輸出的節點彈出,節省了空間開銷,降低了空間複雜度。
對於輸出指定行的節點數據,只需引入一個變量保存層數即可,代碼如下:
queue<node*> Queue5;
void cengxu_n_ceng(node *root,int ceng)
{
int cur=0,len=1,cengshu=0;
Queue5.push(root);
while(!Queue5.empty())
{
while(cur++<len)
{
node *temp=Queue5.front();
Queue5.pop();
if (cengshu==ceng)
{
cout<<temp->value<<" ";
}
if (temp->pleft)
Queue5.push(temp->pleft);
if (temp->pright)
Queue5.push(temp->pright);
}
if (cengshu==ceng)
{
cout<<endl;
return;
}
else
cengshu++;
cur=0;
len=Queue5.size();
}
}
3.擴展問題
圖3中的輸出順序剛好是圖1中的逆序,先壓人棧中,再出棧即可。圖4中,每一行的輸出順序和原問題的順序相同,可壓人隊列存儲,行序和原問題相反,可將每一行作爲隊列壓入棧中。再出棧、出隊列輸出即可。方便起見,將原問題和擴展圖3和圖4的擴展問題的代碼,編寫在一起,如下:
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <string>
#include <queue>
#include <vector>
#include <stack>
using namespace std;
struct node
{
char value;
node* pleft;
node* pright;
};
queue<node*> Queue3;//------------------使用系統的STL的queue
stack<int> Queue3_temp;
stack<queue<node*>> Queue3_tempfan;
void cengxu3(node* root)
{
node *temp;
queue<node*> Queue3_fuzhu;
char temp_value;
Queue3.push(root);
Queue3_tempfan.push(Queue3);
int len=Queue3.size();
int cur=0;
while(!Queue3.empty())
{
while(cur++<len)//cur++,注意一些小的邏輯、圖2的結果
{
temp=Queue3.front();
Queue3_temp.push(temp->value);
Queue3.pop();
cout<<temp->value<<" ";
if (temp->pleft)
{
Queue3.push(temp->pleft);
}
if (temp->pright)
{
Queue3.push(temp->pright);
}
}
Queue3_tempfan.push(Queue3);
Queue3_temp.push('\n');
cout<<endl;
cur=0;
len=Queue3.size();
}
while(!Queue3_temp.empty())//圖3的結果
{
temp_value=Queue3_temp.top();
Queue3_temp.pop();
if (temp_value=='\n')
{
cout<<temp_value;
}
else
cout<<temp_value<<" ";
}
while(!Queue3_tempfan.empty())//圖4的結果
{
Queue3_fuzhu=Queue3_tempfan.top();//注意要彈出
Queue3_tempfan.pop();
while(!Queue3_fuzhu.empty())
{
temp=Queue3_fuzhu.front();
Queue3_fuzhu.pop();
cout<<temp->value<<" ";
}
cout<<endl;
}
}
4.測試結果
採用先序和中序結果重建二叉樹(代碼見3.9),再對其進行遍歷的測試結果如圖5所示,前四行分別爲先序、中序、後序和層序遍歷結果,後面3個三角形分別對應圖2、圖3、圖4中的結果。
圖5
歡迎各位交流批評指正^_^····