二叉搜尋樹(搜尋二叉樹)轉換成一個雙向連結串列
阿新 • • 發佈:2019-01-29
1.題目描述:
將一個二叉搜尋樹轉換成一個雙向連結串列;
2.二叉搜尋樹,直接看圖:
如圖就是一個二叉搜尋樹的模型,也就是轉換函式的入口資料,也是下邊函式中即將用到的例子,既然有輸入,肯定有輸出,先面在看一張圖(第三條):
3.輸入輸出模型:
右邊就是最終的輸出結果,5後邊是空,下邊來分析一下:
1.在二叉搜尋樹中,每個節點都有兩個孩子,即左和右,而在雙向連結串列中,每個節點也有兩個指標,前驅和後繼指標,二叉樹和雙向連結串列很有相似性;
2.改變二叉搜尋樹的左右孩子指標指向,就可完成二叉搜尋樹到雙向連結串列的轉換;
3.由於最終雙向連結串列的遍歷結果就是二叉搜尋樹中序的遍歷結果;
4.開始中序線索化二叉樹(即改變二叉樹指標指向)
如果對中序線索化二叉樹還有疑問,請看下圖:
如圖葉子節點的左右孩子指標指向都按中序線索的方式改變了;
4.看程式碼說話:
第一部分:
首先需要儲存最後雙向連結串列的頭,即二叉樹的最左節點:
第二部分:Node* _BinaryToDoubleList(Node* root) { //1.找到雙向連結串列的頭; Node* head = root; while(head->_left != nullptr) { head = head->_left; } Node* prev = nullptr; _Change(root,prev); //轉換函式 return head; }
轉換函式:一個遞迴過程,按照中序線索化走的
void _Change(Node* cur,Node*& prev)
{
if (cur == nullptr)
return;
//1.找到最左邊
_Change(cur->_left,prev);
cur->_left = prev; //此時prev為空
if (prev != nullptr)
prev->_right = cur;
prev = cur;
_Change(cur->_right, prev);
}
完整測試程式碼:
畫圖不容易,幫頂,賜教!#pragma once template<class K, class V> struct SBTNode { K key; V value; SBTNode<K, V> *_left; SBTNode<K, V> *_right; SBTNode(const K& key, const V& value) :key(key) , value(value) , _left(nullptr) , _right(nullptr) {} }; template<class K, class V> class SBTree { typedef SBTNode<K, V> Node; public: SBTree() :_root(nullptr) {} ~SBTree() {} public: //非遞迴插入 bool Insert(const K& key, const V& value) { return _Insert(key, value); } //遞迴插入 bool Insert_R(const K& key, const V& value); //非遞迴查詢節點 SBTNode<K, V>* Find(const K& key) { if (_root == nullptr) { return nullptr; } SBTNode<K, V> *cur = _root; while (cur->_left || cur->_right) { if (cur->key == key) { return cur; } else if (cur->key > key) { cur = cur->_left; } else if (cur->key < key) { cur = cur->_right; } else { return nullptr; } } } bool _Insert(const K& key, const V& value) { if (_root == nullptr) { _root = new SBTNode<K, V>(key, value); return true; } SBTNode<K, V> *parent = nullptr; //指向cur 的前驅 SBTNode<K, V> *cur = _root; while (cur) { if (cur->key > key) //插左邊 { parent = cur; cur = cur->_left; } else if (cur->key < key) { parent = cur; cur = cur->_right; } else { return false; } } if (parent->key < key) { SBTNode<K, V> *node = new SBTNode<K, V>(key, value); parent->_right = node; return true; } else if (parent->key > key) { SBTNode<K, V> *node = new SBTNode<K, V>(key, value); parent->_left = node; return true; } else { return false; } } Node* BinaryToDoubleList() { return _BinaryToDoubleList(_root); } Node* _BinaryToDoubleList(Node* root) { //1.找到雙向連結串列的頭; Node* head = root; while(head->_left != nullptr) { head = head->_left; } Node* prev = nullptr; _Change(root,prev); //轉換函式 return head; } void _Change(Node* cur,Node*& prev) { if (cur == nullptr) return; //1.找到最左邊 _Change(cur->_left,prev); cur->_left = prev; //此時prev為空 if (prev != nullptr) prev->_right = cur; prev = cur; _Change(cur->_right, prev); } //中序遍歷 void InOrder(SBTNode<K, V>* root) { if (root == nullptr) { return; //遞迴結束出口 } SBTNode<K, V> *cur = root; InOrder(cur->_left); cout << cur->key << " "; InOrder(cur->_right); } //順序遍歷雙向連結串列 void TreaveList() { Node* cur = BinaryToDoubleList(); while (cur) { cout << cur->key<< " "; cur = cur->_right; } cout << endl; } public: SBTNode<K, V> *_root; };