【編程練習】二叉樹相關算法(二)

二叉樹的第一部分算法如下
https://blog.csdn.net/weixin_44611644/article/details/95897436

下面是第二部分的二叉樹題目
(1)知道前序和中序之後,重建二叉樹
前序遍歷的特點是第一個值爲根節點,中序遍歷的值是根節點在中間,利用此規律對數組進行分割歸併。

TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
        int n = pre.size();
        if(n!=vin.size()||n==0)
            return nullptr;
         
        TreeNode* root = new TreeNode(pre[0]);
        vector<int> newPre;
        vector<int> newVin;
        for(int i = 0;i<vin.size();i++)
        {
            if(vin[i] == pre[0])
            {
                newPre.assign(pre.begin()+1,pre.begin()+i+1);
                newVin.assign(vin.begin(),vin.begin()+i);
                root->left = reConstructBinaryTree(newPre,newVin);
                
                newPre.assign(pre.begin()+i+1,pre.end());
                newVin.assign(vin.begin()+i+1,vin.end());
                root->right = reConstructBinaryTree(newPre,newVin);
                break;
            }
        }
        return root;
}

(2)二叉搜索樹展開爲雙向鏈表
和二叉樹展開爲鏈表相似,遞歸算法。

TreeNode* Convert(TreeNode* pRootOfTree)
    {
        if(pRootOfTree == nullptr) return nullptr;
        TreeNode* pre = nullptr;
        convertHelper(pRootOfTree, pre);
        TreeNode* res = pRootOfTree;
        while(res ->left)
            res = res ->left;
        return res;
    }
     
    void convertHelper(TreeNode* cur, TreeNode*& pre)
    {
        if(cur == nullptr) return;    
        convertHelper(cur ->left, pre);   
        cur ->left = pre;
        if(pre) pre ->right = cur;
        pre = cur;
        convertHelper(cur ->right, pre);
}

(3)左右視圖樹

以左視圖樹講解,代表從最左面能看到的結點,可以這樣做,先遍歷一次,map存放結點和層數,然後進行逆序更新,就是從右忘左更新,比如第三層有2個結點 左面的結點是x1,右面的結點是x2,map中的鍵值對應關係是去重複的,先加載了x2 map[3]=x2;這裏含義就是第三層能看到x2,逆序的最後把map[3]的值更新成了x1,這樣就實現了map中保存的是各個層中 最左面的那個數。

void reUpdate(vector<float> &result) {
    map<int, float> mp;
    // 逆序更新
    for(int i = result.size() - 1; i >0; i -= 2) {
        auto pos = mp.find((int)result[i - 1]);
        // 如果已經存在則更新,若不存在則添加
        if(pos != mp.end()) {
            pos->second = result[i]; // 更新
        } else {
            mp.insert(make_pair((int)result[i - 1], result[i]));
        }
    }
    // 清空原result
    vector<float>().swap(result);
    // 將mp的結果放入result,並輸出結果
    for(auto pair : mp) {
        result.push_back(pair.second);
    }
}
void preLeftView(Node & node, vector<float> &result, const int deep = 0) {
    result.push_back(deep);
    result.push_back(node.data);
    if(node.leftChiled != nullptr) {
        preLeftView(*(node.leftChiled), result, deep + 1);
    }
    if(node.rightChiled != nullptr) {
        preLeftView(*(node.rightChiled), result, deep + 1);
    }
}

// 左視圖生成函數
void leftView(Node & node) {
    vector<float> result;
    preLeftView(node, result);
    // 逆序更新result
    reUpdate(result);
    for(auto x : result) {
        cout << x << " ";
    }
    
}

(4)判斷是不是二叉搜索樹後序遍歷的結果
特點是 左節點比自己小,右結點比自己大。後序遍歷的話根節點在最後,對數組進行遍歷,先升後降,如果最後到達數組末尾則這個結點符合規律,依次判斷全部結點。
這時候如果比較難理解的話不妨自己畫一棵樹模擬一下。

bool VerifySquenceOfBST(vector<int> sequence) {
        int size = sequence.size();
        if(0==size)return false;
 
        int i = 0;
        while(--size)
        {
            while(sequence[i++]<sequence[size]);
            while(sequence[i++]>sequence[size]);
 
            if(i<size)return false;
            i=0;
        }
        return true;
}

(5)二叉樹中和爲某一值的路徑
和爲某一值的路徑可能不止一條,用二維數組保存所有結果。

class Solution {
public:
    vector<vector<int> > FindPath(TreeNode* root,int expectNumber) 
    {
        if (!root) return res;

        cur.push_back(root->val);
        if (root->val == expectNumber && !root->left && !root->right)
            res.push_back(cur);

        FindPath(root->left, expectNumber - root->val);
        FindPath(root->right, expectNumber - root->val);
 
        if (!cur.empty())
            cur.pop_back();
        return res;
    }

private:
    vector<int> cur;
    vector<vector<int>> res;
};

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