給定一顆二叉樹,要求按分層遍曆該二叉樹,即從上到下按層次訪問該二叉樹(每一層將單獨輸出一行),每一行要求訪問的順序是從左至右。
《編程之美》中有遞迴和非遞迴的解法。
遞迴解法的思路是,假設要求訪問二叉樹中第K層的節點,那麼可以把它轉換成訪問以該二叉樹根節點的左右節點為根的兩顆左右子樹的第K-1層的節點。依次遞迴
下面程式是輸出第K層的節點
int PrintNodeAtLevel(node *root,int level)<br />{<br /> if(root==NULL|| level<0)<br /> return 0;<br /> if(level==0)<br /> {<br /> cout << root->data << " ";<br /> return 1;<br /> }<br /> return PrintNodeAtLevel(root->left,level-1)+PrintNodeAtLevel(root->right,level-1);</p><p>}
對於非遞迴的解法,《編程之美》上使用了一個Vector數組,然後用了兩個遊標來標記一層是否結束。
我自己的解法是用了兩個隊列。一個隊列放節點,一個隊列放對應的節點的層次。如果不需要每一層次輸完換行的話,一個隊列就夠了。這種方法貌似效率要比《編程之美》上的低啊。。
#include <iostream><br />#include <queue><br />using namespace std;</p><p>struct node<br />{<br />node *left;<br />node *right;<br />char value;<br />node (char v,node *l=NULL,node *r=NULL): value(v),left(l),right(r){}<br />};</p><p>void PrintByLevel(node *root)<br />{<br />queue<node *> q;<br />queue<int> q2; //記錄當前節點的層次<br />q.push(root);<br />node *p;<br />q2.push(0);<br />while(!q.empty())<br />{<br />p=q.front();<br />if(p->left)<br />{<br />q.push(p->left);<br />q2.push(q2.front()+1);<br />}<br />if(p->right)<br />{<br />q.push(p->right);<br />q2.push(q2.front()+1);<br />}<br />cout << p->value;<br />q.pop();<br />int temp=q2.front();<br />q2.pop();<br />if(q2.empty() ||temp!=q2.front())<br />cout << endl;<br />}<br />}</p><p>int main()<br />{<br /> node *h=new node('h');<br /> node *i=new node('i');<br /> node *e=new node('e',h);<br /> node *c=new node('c',e);<br /> node *f=new node('f',NULL,i);<br /> node *g=new node('g');<br /> node *d=new node('d',f,g);<br /> node *b=new node('b',c,d);<br /> node *a=new node('a',NULL,b); </p><p> PrintByLevel(a);</p><p>}<br />
擴充問題:
1. 如果要求按深度從下到上訪問二叉樹,每層的訪問順序仍然是從左至右,如何改進?
可以在《編程之美》的基礎上改,用vector,和兩個遊標。。。
void PrintByReverseLevel(node *root)<br />{<br />vector<node *> q;<br />stack<int> q2; //記錄當前節點的層次<br />node *p;<br />q.push_back(root);<br />q2.push(0);<br />int cur=0;<br />int last=1;<br />while(cur<q.size())<br />{<br />int level=q2.top();<br />last=q.size();<br />while(cur<last)<br />{<br />p=q[cur];<br />if(p->right)<br />{<br />q.push_back(p->right);<br />q2.push(level+1);<br />}<br />if(p->left)<br />{<br />q.push_back(p->left);<br />q2.push(level+1);<br />}<br />cur++;<br />}<br />}<br />while(!q2.empty())<br />{<br />cout << q[--cur]->value;<br />int temp=q2.top();<br />q2.pop();<br />if(q2.empty() || temp!=q2.top())<br />cout << endl;<br />}<br />}
2. 如果按深度從下到上訪問,每層的訪問順序變成從右至左,演算法又該怎麼改進?
對上個程式做下修改,改變左右節點進vector的順序即可
void PrintByReverseLevel2(node *root)<br />{<br />vector<node *> q;<br />stack<int> q2; //記錄當前節點的層次<br />node *p;<br />q.push_back(root);<br />q2.push(0);<br />int cur=0;<br />int last=1;<br />while(cur<q.size())<br />{<br />int level=q2.top();<br />last=q.size();<br />while(cur<last)<br />{<br />p=q[cur];<br />if(p->left)<br />{<br />q.push_back(p->left);<br />q2.push(level+1);<br />}<br />if(p->right)<br />{<br />q.push_back(p->right);<br />q2.push(level+1);<br />}<br />cur++;<br />}<br />}<br />while(!q2.empty())<br />{<br />cout << q[--cur]->value;<br />int temp=q2.top();<br />q2.pop();<br />if(q2.empty() || temp!=q2.top())<br />cout << endl;<br />}<br />}