雖然我們把樹化成二元樹可以減少空間浪費由 2/3 降低到 1/2, 但是如果仔細觀察我們使用鏈結串列建立 n 節點二元樹, 實際上用來指向左右兩節點的指標只有n-1 個鏈結, 另外的 n+1 個指標都是空鏈結.
所謂的 "引線二元樹" (Thread Binary Tree) 就是把這些空的鏈結加以利用, 再指到樹的其它節點, 而這些鏈結就稱為 "引線" (Thread), 而這棵樹就稱為引線二元樹. 至於將二元樹轉換成引線二元樹的步驟如下 :
引線二元樹的基本結構如下 :
和鏈結串列所建立的二元樹不同在於, 為了區分正常指標或引線而加入的兩個欄位 LBIT 及 RBIT. 其中:
二元樹轉引線二元樹 :
接著我們練習如何將下圖二元樹轉為引線二元樹 :
步驟 :
1. 以中序追蹤二元樹 : HDIBEAFCG
2. 找出相對應的引線二元樹, 並按照中序走訪求得下圖 :
以下整理出來使用引線二元樹的優缺點 :
優點 :
缺點 :
範例代碼 :
* ThreadBTree.h 代碼 :
- #include
- using namespace std;
- class ThreadBTreeNode{
- public:
- int data;
- int left_Thread;
- int right_Thread;
- class ThreadBTreeNode *leftNode;
- class ThreadBTreeNode *rightNode;
- };
- typedef class ThreadBTreeNode tbtNode;
- typedef tbtNode *tbtNodePoint;
- class ThreadBTree{
- tbtNodePoint root;
- public:
- ThreadBTree(){root = NULL;}
- virtual void Add_Node_To_Tree(int value);
- virtual void CreateTree(int *m, int len);
- virtual void Inorder(); /*中序走訪二元樹*/
- };
- #include "ThreadBTree.h"
- void ThreadBTree::Inorder(){
- tbtNodePoint tempNode = root;
- do{
- if(tempNode->right_Thread == 0)
- tempNode = tempNode->rightNode;
- else {
- tempNode = tempNode->rightNode;
- while(tempNode->left_Thread !=0)
- tempNode = tempNode->leftNode;
- }
- if(tempNode != root)
- cout << "[" << tempNode->data << "] ";
- }while(tempNode != root);
- cout << endl;
- }
- void ThreadBTree::CreateTree(int *m, int len) {
- for(int i=0; i
- this->Add_Node_To_Tree(m[i]);
- }
- void ThreadBTree::Add_Node_To_Tree(int value){
- tbtNodePoint newnode;
- tbtNodePoint previous;
- newnode = new tbtNode;
- newnode->data = value;
- newnode->left_Thread = 0;
- newnode->right_Thread = 0;
- newnode->leftNode = NULL;
- newnode->rightNode = NULL;
- tbtNodePoint current;
- tbtNodePoint parent;
- int pos;
- // 設定引線二元樹的開頭節點
- if(root == NULL) {
- root = newnode;
- root->leftNode = root;
- root->rightNode = NULL;
- root->left_Thread = 0;
- root->right_Thread = 1;
- return;
- }
- // 設定開頭節點所指節點
- current = root->rightNode;
- if(current == NULL) {
- root->rightNode = newnode;
- newnode->leftNode = root;
- newnode->rightNode = root;
- return;
- }
- parent = root; // 父節點是開頭節點
- pos = 0; // 設定二元樹中的行進方向
- while(current != NULL) {
- if(current->data > value) { // 往左節點
- if(pos != -1){
- pos = -1;
- previous = parent;
- }
- parent = current;
- if(current->left_Thread == 1)
- current = current->leftNode;
- else
- current = NULL;
- } else { // 往右節點
- if(pos != 1) {
- pos = 1;
- previous = parent;
- }
- parent = current;
- if(current->right_Thread == 1)
- current = current->rightNode;
- else
- current = NULL;
- }
- }
- if(parent->data > value) {
- parent->leftNode = newnode;
- parent->left_Thread = 1;
- newnode->leftNode = previous;
- newnode->rightNode = parent;
- } else {
- parent->rightNode = newnode;
- parent->right_Thread = 1;
- newnode->leftNode = parent;
- newnode->rightNode = previous;
- }
- }
- void ch06_07(bool b) {
- if(b) {
- ThreadBTree tBTree;
- tBTree.Add_Node_To_Tree(0); // 建立Null Node
- int sv = 0;
- while(sv != -1) {
- cout << "請輸入值 (輸入-1離開):" ;
- cin >> sv;
- if(sv!=-1) {
- tBTree.Add_Node_To_Tree(sv);
- }
- }
- /*中序走法列印二元樹內容*/
- tBTree.Inorder();
- }
- }
執行結果 :
補充說明 :
* [ 資料結構 小學堂 ] 樹狀結構導論 : 二元樹的走訪
* [ 資料結構 小學堂 ] 樹狀結構導論 : 樹
沒有留言:
張貼留言