二叉树构建及双向链表
生活随笔
收集整理的這篇文章主要介紹了
二叉树构建及双向链表
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
二叉樹構建及雙向鏈表
文章目錄
- 二叉樹構建及雙向鏈表
- 一、從前序與中序遍歷序列構造二叉樹
- 代碼
- 二、從中序與后序遍歷序列構造二叉樹
- 代碼
- 三、二叉搜索樹轉雙向鏈表
- 代碼
一、從前序與中序遍歷序列構造二叉樹
根據一棵樹的前序遍歷與中序遍歷構造二叉樹。
注意: 你可以假設樹中沒有重復的元素。例如,給出前序遍歷 preorder = [3,9,20,15,7] 中序遍歷 inorder = [9,3,15,20,7] 返回如下的二叉樹:3/ \9 20/ \15 7代碼
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/ class Solution { private:unordered_map<int, int> index;public:TreeNode* myBuildTree(const vector<int>& preorder, const vector<int>& inorder, int preorder_left, int preorder_right, int inorder_left, int inorder_right) {if (preorder_left > preorder_right) {return nullptr;}// 前序遍歷中的第一個節點就是根節點int preorder_root = preorder_left;// 在中序遍歷中定位根節點int inorder_root = index[preorder[preorder_root]];// 先把根節點建立出來TreeNode* root = new TreeNode(preorder[preorder_root]);// 得到左子樹中的節點數目int size_left_subtree = inorder_root - inorder_left;// 遞歸地構造左子樹,并連接到根節點// 先序遍歷中「從 左邊界+1 開始的 size_left_subtree」個元素就對應了中序遍歷中「從 左邊界 開始到 根節點定位-1」的元素root->left = myBuildTree(preorder, inorder, preorder_left + 1, preorder_left + size_left_subtree, inorder_left, inorder_root - 1);// 遞歸地構造右子樹,并連接到根節點// 先序遍歷中「從 左邊界+1+左子樹節點數目 開始到 右邊界」的元素就對應了中序遍歷中「從 根節點定位+1 到 右邊界」的元素root->right = myBuildTree(preorder, inorder, preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right);return root;}TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {int n = preorder.size();// 構造哈希映射,幫助我們快速定位根節點for (int i = 0; i < n; ++i) {index[inorder[i]] = i;}return myBuildTree(preorder, inorder, 0, n - 1, 0, n - 1);} };二、從中序與后序遍歷序列構造二叉樹
根據一棵樹的中序遍歷與后序遍歷構造二叉樹。
注意: 你可以假設樹中沒有重復的元素。例如,給出中序遍歷 inorder = [9,3,15,20,7] 后序遍歷 postorder = [9,15,7,20,3] 返回如下的二叉樹:3/ \9 20/ \15 7代碼
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/ class Solution { public:unordered_map<int, int> mp;TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {if (inorder.empty()) return NULL;for (int i = 0; i < inorder.size(); i++) mp[inorder[i]] = i; //記住每個數的位置return build(inorder, postorder, 0, inorder.size() - 1, 0, postorder.size() - 1);}TreeNode * build(vector<int>& inorder, vector<int>& postorder, int inL, int inR, int pL, int pR){if (pL > pR) return NULL;TreeNode * root = new TreeNode(postorder[pR]);int k = mp[postorder[pR]];root->left = build(inorder, postorder, inL, k - 1, pL, pL + k - inL - 1);root->right = build(inorder, postorder, k + 1, inR, pL + k - inL, pR - 1);return root;} };三、二叉搜索樹轉雙向鏈表
輸入一棵二叉搜索樹,將該二叉搜索樹轉換成一個排序的雙向鏈表。要求不能創建任何新的結點,只能調整樹中結點指針的指向。
代碼
/* struct TreeNode {int val;struct TreeNode *left;struct TreeNode *right;TreeNode(int x) :val(x), left(NULL), right(NULL) {} };*/ class Solution { public:void BToL(TreeNode* pRootOfTree,TreeNode** Head){if(pRootOfTree == nullptr){return ;}//找到最左側節點TreeNode* cur = pRootOfTree; if(cur->left){BToL(cur->left,Head);}//cur:當前判斷節點,也是雙向鏈表當中的后一個節點//head:當前節點的上一個節點,即cur的上一個節點,即雙向鏈表的前一個節點 //這一步相當于雙向鏈表當中的鏈接prev指針,即后一個節點鏈接前一個節點cur->left = *Head;//當第一次走到這里時cur->left肯定是空,需要判斷if(*Head){//這一步相當于雙向鏈表的next指針,即前一個節點鏈接后一個節點(*Head)->right = cur;}//head也同步往后*Head = cur;//判斷右子樹,遞歸進行if(cur->right){BToL(cur->right,Head);}//注意隨著head不斷往后,得到的雙向鏈表剛好是反的,head指針指向的位置是二叉樹的最由節點}TreeNode* Convert(TreeNode* pRootOfTree){TreeNode* Head = nullptr;BToL(pRootOfTree,&Head);//翻轉while(Head && Head->left){Head = Head->left;}return Head;} };總結
以上是生活随笔為你收集整理的二叉树构建及双向链表的全部內容,希望文章能夠幫你解決所遇到的問題。