引線二叉樹(Threaded Binary Tree)
介紹
連結:
參考學習連結 1
參考學習連結 2
引線二叉樹是一種特殊的二叉樹,其中所有空的子樹指針都被用來存儲對樹中其他節點的指針,這樣可以實現高效的中序遍歷,而不需要使用棧或遞歸。
資料結構概述
引線二叉樹的核心思想是在普通的二叉樹上進行改造,使得所有空的左指針和右指針指向樹中某些節點,從而實現高效的中序遍歷。這樣的結構不僅可以避免使用遞歸或棧,還能在遍歷過程中節省空間。
- 結構設計:每個節點除了原有的左子樹和右子樹指針外,還增加了
hasLeftThread 和 hasRightThread 標記,分別指示是否存在左線引和右線引。
- 主要特性:引線二叉樹的主要特性是其能夠在中序遍歷時不使用額外的空間。
操作和方法
1. 插入節點到二叉樹中
這個操作將新節點插入到普通的二叉樹中,按層次順序插入。
詳細步驟:
- 使用隊列進行層次遍歷,找到第一個空的左子節點位置,插入新節點。
- 如果左子節點位置已滿,則插入到右子節點位置。
2. 將普通二叉樹轉換為引線二叉樹
這個操作將普通的二叉樹轉換為引線二叉樹,設置線引指針。
詳細步驟:
- 遞歸遍歷左子樹,對每個節點設置左線引和右線引。
- 如果節點的左子節點為空,則設置左線引指向前驅節點。
- 如果節點的前驅節點的右子節點為空,則設置右線引指向當前節點。
3. 中序遍歷引線二叉樹
這個操作在引線二叉樹中進行中序遍歷,利用線引指針提高效率。
詳細步驟:
- 從樹的最左節點開始,逐步訪問每個節點。
- 如果節點有右線引,則直接跳到右子樹的節點。
- 否則,移動到右子樹,並找到右子樹的最左節點。
代碼實現
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
| #include <bits/stdc++.h> using namespace std;
struct ThreadedBinaryTreeNode { int hasLeftThread; ThreadedBinaryTreeNode* leftChild; char data; ThreadedBinaryTreeNode* rightChild; int hasRightThread;
ThreadedBinaryTreeNode(char data = '\0') : data(data), hasLeftThread(0), leftChild(nullptr), hasRightThread(0), rightChild(nullptr) {} };
void insertIntoBinaryTree(ThreadedBinaryTreeNode*& root, char currData) { queue<ThreadedBinaryTreeNode*> nodeQueue; nodeQueue.push(root);
while (!nodeQueue.empty()) { ThreadedBinaryTreeNode* currentNode = nodeQueue.front(); nodeQueue.pop();
if (currentNode->leftChild == nullptr) { currentNode->leftChild = new ThreadedBinaryTreeNode(currData); break; } else { nodeQueue.push(currentNode->leftChild); }
if (currentNode->rightChild == nullptr) { currentNode->rightChild = new ThreadedBinaryTreeNode(currData); break; } else { nodeQueue.push(currentNode->rightChild); } } }
void convertToThreadedBinaryTree(ThreadedBinaryTreeNode*& root) { static ThreadedBinaryTreeNode* previousNode = nullptr;
if (!root) return;
convertToThreadedBinaryTree(root->leftChild);
if (root->leftChild == nullptr) { root->leftChild = previousNode; root->hasLeftThread = 1; }
if (previousNode && previousNode->rightChild == nullptr) { previousNode->rightChild = root; previousNode->hasRightThread = 1; }
previousNode = root; convertToThreadedBinaryTree(root->rightChild); }
void inorderTraversalThreadedBinaryTree(ThreadedBinaryTreeNode*& root) { if (!root) return;
ThreadedBinaryTreeNode* currentNode = root;
while (currentNode && !currentNode->hasLeftThread) { currentNode = currentNode->leftChild; }
while (currentNode) { cout << currentNode->data << " ";
if (currentNode->hasRightThread) { currentNode = currentNode->rightChild; } else { currentNode = currentNode->rightChild; while (currentNode && !currentNode->hasLeftThread) { currentNode = currentNode->leftChild; } } } }
int main() { ios::sync_with_stdio(0); cin.tie(0);
vector<char> nodes = {'A', 'B', 'C', 'D', 'E', 'F', 'G'}; ThreadedBinaryTreeNode* root = nullptr;
for (char c : nodes) { if (root == nullptr) { root = new ThreadedBinaryTreeNode(c); } else { insertIntoBinaryTree(root, c); } }
convertToThreadedBinaryTree(root); inorderTraversalThreadedBinaryTree(root); }
|