將搜尋二叉樹轉換成雙向連結串列
阿新 • • 發佈:2019-01-10
題目
對二叉樹的節點來說, 有本身的值域, 有指向左孩子和右孩子的兩個指標; 對雙向連結串列的節點來說,有本身的值域, 有指向上一個節點和下一個節點的指標。 在結構上, 兩種結構有相似性, 現在有一棵搜尋二叉樹, 請將其轉換為一個有序的雙向連結串列。
分析
用兩種方法求解本題。 方法一:由於是搜尋二叉樹,直接求出其中序遍歷序列,構造雙向連結串列即可。方法二:採用遞迴實現。分別得到左右子樹的雙向子連結串列(儲存該子連結串列的尾節點,並使該尾節點的next連結子連結串列的頭節點,效能優化,避免線性查詢),然後將當前節點連結即可。
程式碼
#include <iostream> #include <cstdlib> #include <vector> using namespace std; //雙向連結串列結構體 struct DListNode { int val; DListNode *prev, *next; DListNode(int v) :val(v), prev(NULL),next(NULL){} }; //二叉搜尋樹 struct BSTNode { int val; BSTNode *left, *right; BSTNode(int v):val(v),left(NULL),right(NULL){} }; //二叉搜尋樹插入節點 void insert(BSTNode **root, int val) { if (*root == NULL) { *root = new BSTNode(val); return; } if (val < (*root)->val) insert(&((*root)->left),val); else insert(&((*root)->right),val); } //中序遍歷二叉樹 void inOrder(BSTNode *root, vector<int> &ret) { if (root == NULL) return; inOrder(root->left, ret); ret.push_back(root->val); inOrder(root->right, ret); } //方法一,利用中序排序得到二叉搜尋樹序列,構造雙向連結串列T(n)=o(n) S(n)=o(n) DListNode *translate(BSTNode *root) { if (root == NULL) return NULL; vector<int> inRet; inOrder(root, inRet); DListNode *head = NULL, *p = NULL; for (auto iter = inRet.begin(); iter != inRet.end(); ++iter) { if (head == NULL) { head = new DListNode(*iter); p = head; }//if else { DListNode *node = new DListNode(*iter); node->prev = p; p->next = node; p = node; }//else }//for return head; } //方法二,遞迴實現,T(n)=O(n) S(n)=O(h) DListNode *translate2(BSTNode *root) { if (root == NULL) return NULL; //返回構造好連結串列的尾節點,並使得尾節點的next指向頭結點 DListNode *lEnd = translate2(root->left); DListNode *rEnd = translate2(root->right); DListNode *lHead = NULL; DListNode *rHead = NULL; if (lEnd) lHead = lEnd->next; if (rEnd) rHead = rEnd->next; DListNode *node = new DListNode(root->val); if (lEnd && rEnd) { lEnd->next = node; node->prev = lEnd; node->next = rHead; rHead->prev = node; rEnd->next = lHead; }//if else if (lEnd != NULL) { lEnd->next = node; node->prev = lEnd; node->next = lHead; return node; } else if (rEnd != NULL) { node->next = rHead; rHead->prev = node; rEnd->next = node; return rEnd; }else{ node->next = node; return node; } } //遍歷雙向連結串列 void display(DListNode *head) { if (head == NULL) return; DListNode *p = head; while (p) { cout << p->val << "\t"; p = p->next; }//while cout << endl; } int main() { vector<int> v = { 5,4,6,2,7 }; BSTNode *root = NULL; for (auto iter = v.begin(); iter != v.end(); ++iter) { insert(&root, *iter); }//for DListNode *head = translate(root); display(head); DListNode *end = translate2(root); head = end->next; end->next = NULL; display(head); system("pause"); return 0; }