线索二叉树
数据定义:
1 /* 2 * 枚举类型定义 NO -> 没有线索化 YES -> 线索化了的 3 */ 4 enum Thread { NO, YES } 5 6 /* 7 * 线索二叉树的结点类型定义 8 */ 9 struct Node 10 { 11 ElementType data; // 数据域 12 Thread leftTag; // 左指针标志域 13 Thread rightTag; // 右指针标志域 14 struct Node *leftChild; // 左指针域 15 struct Node *rightChild; // 右指针域 16 };
为二叉树加序:
1 /* 2 * 为二叉树加前序线索 递归实现 3 */ 4 void PreorderThread(Node *root) 5 { 6 static Node *prev = NULL; /* 指向当前结点的后序前件,用以记忆刚访问过的结点 */ 7 if(root != NULL) { // 若二叉树为空,结束递归 8 if(prev != NULL && prev->rightTag = YES) // 若当前结点的前序前件需要加线索 9 prev->rightChild = root; // 对当前结点的前序前件加指向后件(当前结点)的线索 10 if(root->leftChild == NULL) { // 若当前结点的左指针为空 11 root->leftTag = YES; // 将其修改为指向前件的线索 12 root->leftChild = prev; 13 } 14 if(root->rightChild == NULL) // 若当前结点的右指针域为空,修改右指针标志 15 root->rightTag = YES; 16 prev = root; // 将当前结点置为前件,后件将成为当前结点 17 18 PreorderThread(root->leftChild); // 递归对左子树加前序线索 19 PreorderThread(root->rightChild); // 递归对右子树加前序线索 20 } 21 } 22 23 /* 24 * 为二叉树加中序线索 递归实现 25 */ 26 void InorderThread(Node *root) 27 { 28 static Node *prev = NULL; /* 指向当前结点的后序前件,用以记忆刚访问过的结点 */ 29 if(root != NULL) { // 若二叉树为空,结束递归 30 InorderThread(root->leftChild); /* 递归对左子树加中序线索 */ 31 32 if(prev != NULL && root->rightTag == YES) // 若当前结点的中序前件需要加线索 33 prev->rightChild = root; // 对当前结点的中序前件加指向后件(当前结点)的线索 34 if(root->leftChild == NULL) { // 若当前结点的左指针为空 35 root->leftTag = YES; // 将其修改为指向前件的线索 36 root->leftChild = prev; 37 } 38 if(root->rightChild == NULL) // 若当前结点的右指针域为空,修改右指针标志 39 root->rightTag = YES; 40 prev = root; // 将当前结点置为前件,后件将成为当前结点 41 42 InorderThread(root->rightChild); /* 递归对右子树加中序线索 */ 43 } 44 } 45 46 /* 47 * 为二叉树加后序线索 递归实现 */ 48 void PostorderThread(Node *root) 49 { 50 static Node *prev = NULL; /* 指向当前结点的后序前件,用以记忆刚访问过的结点 */ 51 if(root != NULL) { // 若二叉树为空,结束递归 52 PostorderThread(root->leftChild); // 递归对左子树后序线索化 53 PostorderThread(root->rightChild); // 递归对右子树后序线索化 54 55 if(prev != NULL && root->rightTag == YES) // 若当前结点的后序前件需要加线索 56 prev->rightChild = root; // 对当前结点的后序前件加指向后件(当前结点)的线索 57 if(rot->leftChild == NULL) { // 若当前结点的左指针为空 58 root->leftTag = YES; // 将其修改为指向前件的线索 59 root->rightChild = prev; 60 } 61 if(root->rightChild == NULL) // 若当前结点的右指针域为空,修改右指针标志 62 root->rightTag = YES; 63 prev = root; // 将当前结点置为前件,后件将成为当前结点 64 } 65 }
利用加序的二叉树遍历:
1 /* 2 * 利用 前序线索树 遍历二叉树 3 */ 4 void preorderThreadTreeTraversal(Node *root) 5 { 6 Node *currentNode = root; 7 if(currentNode != NULL) { 8 while(currentNode != NULL) { 9 cout << currentNode->data; 10 if(currentNode->leftTag == NO) // 当前结点有左孩子,则使其左孩子变为当前结点 11 currentNode = currentNode->leftChild; 12 else // 若当前结点没有左孩子,则currentNode指向当前结点的前序后件 13 currentNode = currentNode->rightChild; 14 } 15 } 16 } 17 18 /* 19 * 利用 中序线索树 遍历二叉树 20 */ 21 void inorderThreadTreeTraversal(Node *root) 22 { 23 Node *currentNode = root; // 设定currentNode初始指向中序线索二叉树的根结点 24 if(currentNode != NULL) { // 二叉树为空,结束遍历 25 while(currentNode->leftTag == NO) // 找到中序遍历的第一个结点 26 currentNode = currentNode->leftChild; 27 do { /* 依次找出每个结点的后件,直到输出中序线索二叉树的最右边一个结点 */ 28 cout << currentNode->data; /* 输出当前结点数据 */ 29 if(currentNode->rightTag == YES) // 若当前结点的右指针是线索,其指示为中序后件 30 currentNode = currentNode->rightNode; 31 else { /* 若当前结点的右指针指向右孩子 */ 32 currentNode = currentNode->rightChild; // 从右孩子结点出发找中序后件 33 while(currentNode->leftTag == NO) // 找到右子树的最左边一个结点,即为中序后件 34 currentNode = currentNode->leftChild; 35 } 36 } while(currentNode != NULL); 37 } 38 } 39 40 /* 41 * 利用 后序线索树 遍历二叉树 42 */ 43 void postorderThreadTreeTraversal( Node *root) 44 { 45 46 }
OK哒!O(∩_∩)O哈哈~