【面試題】不用遞歸實現二叉樹的遍歷(使用棧)

只有先序遍歷部分的源代碼:https://github.com/cr19941016/preOrderTree
實現環境:ubuntu16.04 + cmake3.5.1
先序遍歷遞歸的本質就是循環和棧

void TreeHandler::myPreOrder(TreeNode* root){    // 非遞歸先序遍歷二叉樹git
    cout << "mypre: ";
    if(!root)
        return;
    stack<TreeNode*> stk;
    stk.push(root);
    while(!stk.empty()){
        TreeNode* p = stk.top();
        cout << p->data << " ";
        stk.pop();
        if(p->rightchild){
            stk.push(p->rightchild);
        }
        if(p->leftchild){
            stk.push(p->leftchild);
        }
    }
    cout << endl;
}

中序遍歷:

void TreeHandler::myMidOrder(TreeNode* root){
	cout << "mymid: ";
	stack<TreeNode*> stk;
	TreeNode* p = root;
	while(p || !stk.empty()){
		while(p){
			stk.push(p);
			p = p->leftchild;
		}
		if(!stk.empty()){
			p = stk.top();
			stk.pop();
			cout << p->data << ' ';
			p = p->rightchild;
		}
	}
	cout << endl;
}

後序遍歷(比較麻煩,另一種解法是採用一個指針保存上次遍歷的節點,避免重複遍歷),使用兩個棧,一個負責按照“根、右、左”的順序入棧出棧,另一個負責逆序記錄輸出的數據:

void TreeHandler::myPostOrder(TreeNode* root){
	cout << "mypost: ";
	if(!root){
		return;
	}
	stack<TreeNode*> stk1; // 輔助棧
	stack<TreeNode*> stk2; // 逆序記錄遍歷的數據
	TreeNode* p = root;
	while(p || !stk1.empty()){
		if(p){
			stk2.push(p);
			stk1.push(p);
			p = p->rightchild;
		}
		else{
			p = stk1.top();
			stk1.pop();
			p = p->leftchild;
		}

	}

	while(!stk2.empty()){
		p = stk2.top();
		stk2.pop();
		cout << p->data << ' ';
	}
	cout << endl;
}

其他:使用隊列將數組轉化爲生成二叉樹

#include "preodertree.h"
TreeNode* TreeHandler::createTree(vector<int> &nums){ // 根據數組生成二叉樹,如果數值爲-1則表示空位
    TreeNode* root = NULL;
    if(nums.empty()){
        return root;
    }
    root = new TreeNode(nums[0]);
    queue<TreeNode*> q;
    q.push(root);
    for(unsigned int i = 1; i < nums.size(); ){
        TreeNode* p = q.front();
        if(nums[i] != -1){
            TreeNode* l = new TreeNode(nums[i]);
            p->leftchild = l;
            q.push(l);
            i++;
        }
        else i++;
        if(i < nums.size() && nums[i] != -1){
            TreeNode* r = new TreeNode(nums[i]);
            p->rightchild = r;
            q.push(r);
            i++;
        }
        else i++;
        q.pop();
    }
    return root;
}

此外,不使用棧,空間複雜度爲O(1),時間複雜度爲O(n)的Morris Traversal算法:
https://www.jianshu.com/p/d2059062efac

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