打印二叉樹題目:
1)從上到下打印出二叉樹的每個節點,同一層的結點按照從左至右的順序打印。如上圖,打印結果則爲1,2,3,4,5,6
這種層次遍歷可以如下分析:
首先要打印根節點,打印之前要保存其左孩子2,和右孩子結點3。下一步打印左結點2,同樣保存其左右孩子節點。
可以發現這是一個類似於隊列,先進先出的結構。
用隊列實現,每次一個結點要出隊,則其左右孩子入隊。
code如下:
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
vector<int> PrintFromTopToBottom(TreeNode* root) {
vector<int> res;
if(root == nullptr) return res;
queue<TreeNode*> que;
que.push(root);
while(!que.empty())
{
TreeNode* node = que.front();
if(node->left){
que.push(node->left);
}
if(node->right){
que.push(node->right);
}
res.push_back(node->val);
que.pop();
}
return res;
}
};
2)從上到下按層打印二叉樹,同一層的結點按從左到右的順序打印,每一層打印爲一行。例如圖中二叉樹打印結果爲:1
2,3
4,5,6
與1)類似,也可以用一個隊列來保存將要打印的結點。爲了把二叉樹的每一行單獨打印到一行裏,需要兩個變量:一個變量表示在當前層中還沒有打印的節點數,另一個變量表示下一層結點的數目。
code:
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
vector<vector<int> > Print(TreeNode* pRoot) {
if(pRoot == nullptr) return vector<vector<int>>();
vector<vector<int>> res;
queue<TreeNode*> que;
que.push(pRoot);
while(!que.empty()){
int lo = 0;
int hi = que.size();
vector<int> vec;
while(lo++<hi){
TreeNode* temp = que.front();
vec.push_back(temp->val);
que.pop();
if(temp->left) que.push(temp->left);
if(temp->right) que.push(temp->right);
}
res.push_back(vec);
}
return res;
}
};
不管是廣度優先遍歷一幅有向圖還是一棵樹,都要用到隊列。
3)按之字形打印。
即第一行按照從左到右的順序打印,第二層按照從右到左的順序打印,第三行再按照從左到右的順序打印,其他依次類推。如上圖二叉樹的打印結果爲:1
3,2
4,5,6
一個直觀的想法是將2)中的結果,對第二行,第四行等翻轉,得到結果。
code:
/解法1,偷懶做法:
//先將二叉樹每層保存爲一個vector,組成每行都是從左至右順序的二維vector.
//然後用reverse對每奇數行翻轉。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
vector<vector<int> > Print(TreeNode* pRoot) {
if(pRoot == nullptr) return vector<vector<int>>();
vector<vector<int>> res;
queue<TreeNode*> que;
que.push(pRoot);
while(!que.empty()){
int lo = 0;
int hi = que.size();
vector<int> vec;
while(lo++<hi){
TreeNode* temp = que.front();
vec.push_back(temp->val);
que.pop();
if(temp->left) que.push(temp->left);
if(temp->right) que.push(temp->right);
}
res.push_back(vec);
}
int len = res.size();
for(int i = 1; i<len; i = i+2){
reverse(res[i].begin(), res[i].end());
}
return res;
}
};
另一個精巧的思路:使用兩個棧。
分析:當根節點打印之後,其左右子節點先後保存到一個數據容器裏,值得注意的是,打印第二層的節點時,先打印節點3,再打印節點2,看上去像是一個後進先出的過程。
使用兩個棧。棧1保存根節點,棧2保存其左右子節點(左子節點先進)。這樣打印的結果就是第二行先打印右子節點。
隨後,棧1保存棧2出棧節點的右左子節點(右子節點先進),打印的結果就是第三行爲從左至右打印。
後續以此類推。
code:
//解法2,使用兩個棧
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
vector<vector<int> > Print(TreeNode* pRoot) {
if(pRoot == nullptr) return vector<vector<int>>();
stack<TreeNode*> s1;
stack<TreeNode*> s2;
vector<vector<int>> res;
s1.push(pRoot);
while(!s1.empty() || !s2.empty()){
vector<int> vec;
TreeNode* temp = new TreeNode(0);
if(!s1.empty()){
while(!s1.empty()){
temp = s1.top();
s1.pop();
vec.push_back(temp->val);
if(temp->left) s2.push(temp->left);
if(temp->right) s2.push(temp->right);
}
res.push_back(vec);
}
else if(!s2.empty()){
while(!s2.empty()){
temp = s2.top();
s2.pop();
vec.push_back(temp->val);
if(temp->right) s1.push(temp->right);
if(temp->left) s1.push(temp->left);
}
res.push_back(vec);
}
}
return res;
}
};