590. N叉樹的后序遍歷

給定一個 N 叉樹,返回其節(jié)點值的后序遍歷。
N叉樹的定義如下

class Node {
public:
    int val;
    vector<Node*> children;

    Node() {}

    Node(int _val, vector<Node*> _children) {
        val = _val;
        children = _children;
    }
};

例如

給定一個 3叉樹 :

    1
   /|\
  3 2 4
 / \
5  6

返回其后序遍歷: [5,6,3,2,4,1]。

說明:

遞歸法很簡單,你可以使用迭代法完成此題嗎?

思路1

首先采用遞歸法,假設當前節(jié)點不為空
遍歷所有孩子節(jié)點,向每個孩子節(jié)點進行遞歸
遞歸后,存入當前節(jié)點的值。和前序遍歷僅相差在存入節(jié)點的代碼位置

遞歸法具體代碼

vector<int> res; // 結果集
vector<int> postorder(Node* root) {
    if(root == NULL){ //判斷當前節(jié)點不為空
        return res;
    }
    for(int i = 0; i < root->children.size(); i++){ //遍歷所有孩子節(jié)點
        postorder(root->children[i]); //遞歸進入孩子節(jié)點
    }
    res.push_back(root->val); //將當前節(jié)點加入結果集
    return res; //返回結果
}

思路2

使用迭代法,不使用遞歸調用的方式。
使用棧來輔助,我們一層一層進行遍歷
假設此時我們在處理第n行的節(jié)點p1
先把p1的所有兄弟節(jié)點(p2,p3,p4,...)存入棧中,等待后續(xù)使用
接著把p1存入結果集中,遍歷p1所有孩子節(jié)點(pc1,pc2,...),存入棧中,等待后續(xù)使用
取出p1的最左孩子節(jié)點pc1,依次往下處理,假設此時p1的所有孩子節(jié)點都處理完畢了
從棧中取出p2,以此類推使用。
因此整個棧的存放順序為
棧底|pn, pn-1,...,p2,pcn,...,pc2,pc1
也就是說,存棧的時候,局部逆序存儲

和遞歸法不同,迭代法的迭代過程中,其實我們是不知道什么時候p1的孩子節(jié)點全部遍歷完,開始遍歷p2的
所以需要在棧中,額外壓入p1的位置,并使用第二個棧,用來存儲暫時不存入結果集的根節(jié)點
整個棧的存放順序為
孩子棧棧底|pn,pn-1,...,p2,p1,pcn,...pc2,pc1
根節(jié)點棧棧底|p,p1

迭代法具體代碼

vector<int> res;
stack<Node*> s_child;
stack<Node*> s_root;
vector<int> postorder(Node* root) {
    while(root != NULL){ // 該判斷用來規(guī)避初始為空的情況
        if(root->children.size()){ //根節(jié)點處理
            s_root.push(root);  //根節(jié)點存入根節(jié)點棧
            s_child.push(root); //根節(jié)點臨時存入孩子節(jié)點棧
            //存入所有孩子節(jié)點
            for(int i = root->children.size() - 1; i >= 0; i--){
                s_child.push(root->children[i]);
            }
        }
        else{ //葉子節(jié)點,直接存入結果集
            res.push_back(root->val);
        }

        //取出棧頂值
        if(s_child.empty()){ //全部取完,結束
            break;
        }
        root = s_child.top();
        s_child.pop();

        //如果當前節(jié)點為預存的根節(jié)點
        while(root == s_root.top()){
            res.push_back(root->val);  //存入結果集
            s_root.pop();              //根節(jié)點棧彈出一個元素
            if(s_child.empty()){       //遍歷完成則break
                break;
            }
            root = s_child.top();      //否則再次取棧頂
            s_child.pop();
        }
        if(s_child.empty()){           //若是break離開while循環(huán)的,結束遍歷
            break;                     //可能出現(xiàn)的情況是:最后一個根節(jié)點輸出完畢時
        }
    }
    return res;
}
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容