打印二叉樹題型:從上到下打印,打印爲爲多行以及按之字形打印爲多行

打印二叉樹題目:


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;
    }
};



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章