问题引入
从中序遍历的角度来看,找前驱、后继很不方便;遍历操作必须从根开始
思路
从根节点开始,重新进行一次中序遍历,指针q记录当前访问的节点,指针p记录上一个被访问的结点。
①当q == p时,p为前驱
②当p == p时,q为后继
方案
n个结点的二叉树,有n+1个空链域!可以用来记录前驱、后继的信息。指向前驱、后继的指针称为“线索”
前驱线索: 由左孩子指针充当
后继线索: 由右孩子指针充当
存储结构
1 2 3 4 5 6
| typedef struct ThreadNode { ElemType data; struct ThreadNode *lchild, *rchild; int ltag, rtag; } ThreadNode, * ThreadTree;
|
tag == 0, 表示指针指向孩子
tag == 1, 表示指针是“线索”
需要注意的是,先序线索二叉树是按照“先序序列”进行线索化,后续线索二叉树是按照“后序序列”进行线索化的。
代码实现
中序线索化
代码一:右线索出现了问题
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
| #include<stdio.h> #include<stdlib.h> typedef struct ThreadNode { char data; struct ThreadNode *lchild, *rchild; int ltag, rtag; }ThreadNode, *ThreadTree;
ThreadNode *pre = NULL;
bool addLeftChild(ThreadTree root, char leftData) { ThreadTree leftNode = (ThreadTree)malloc(sizeof(ThreadNode)); leftNode->data = leftData; leftNode->lchild = NULL; leftNode->rchild = NULL; root->lchild = leftNode; return true; }
bool addRightChild(ThreadTree root, char rightData) { ThreadTree rightNode = (ThreadTree)malloc(sizeof(ThreadNode)); rightNode->data = rightData; rightNode->lchild = NULL; rightNode->rchild = NULL; root->rchild = rightNode; return true; }
void visit(ThreadNode *q) { if (q->lchild == NULL) { q->lchild = pre; q->ltag = 1; } if (pre != NULL && pre->rchild == NULL) { pre->rchild = q; pre->rtag = 1; } pre = q; printf("%c ltag=%d rtag=%d\n", q->data,q->ltag,q->rtag); }
void InThread(ThreadTree T) { if (T != NULL) { InThread(T->lchild); visit(T); InThread(T->rchild); } }
void deltree(ThreadTree tree){ if (tree != NULL) { deltree(tree->lchild); deltree(tree->rchild); free(tree); } }
void CreateInThread(ThreadTree T) { pre = NULL; if (T != NULL) { InThread(T); if (pre->rchild == NULL) { pre->rtag = 1; } } }
int main() { ThreadTree root; root = (ThreadTree)malloc(sizeof(ThreadNode)); root->data = 'A'; addLeftChild(root, 'B'); addRightChild(root, 'C'); addLeftChild(root->lchild, 'D'); addRightChild(root->lchild, 'E'); addRightChild(root->lchild->lchild,'G'); addLeftChild(root->rchild, 'F'); CreateInThread(root); deltree(root); return 0; }
|
代码二:无问题
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
| #include <stdio.h> #include <stdlib.h> #define TElemType char
typedef enum { Link, Thread }PointerTag;
typedef struct ThreadNode { TElemType data; struct ThreadNode* lchild, *rchild; PointerTag ltag, rtag; }ThreadNode, *ThreadTree; ThreadTree pre = NULL;
bool addLeftChild(ThreadTree root, char leftData) { ThreadTree leftNode = (ThreadTree)malloc(sizeof(ThreadNode)); leftNode->data = leftData; leftNode->lchild = NULL; leftNode->rchild = NULL; root->lchild = leftNode; return true; }
bool addRightChild(ThreadTree root, char rightData) { ThreadTree rightNode = (ThreadTree)malloc(sizeof(ThreadNode)); rightNode->data = rightData; rightNode->lchild = NULL; rightNode->rchild = NULL; root->rchild = rightNode; return true; }
void InThreading(ThreadTree p) { if (p != NULL) { InThreading(p->lchild); if (!p->lchild) { p->ltag = Thread; p->lchild = pre; } if (pre && !pre->rchild) { pre->rtag = Thread; pre->rchild = p; } pre = p; InThreading(p->rchild); } }
void InThread(ThreadTree p) { while (p != NULL) { while (p->ltag == Link) { p = p->lchild; } printf("%c ltag=%d, rtag=%d\n", p->data, p->ltag, p->rtag); while (p->rtag == Thread && p->rchild != NULL) { p = p->rchild; printf("%c ltag=%d, rtag=%d\n", p->data, p->ltag, p->rtag); } p = p->rchild; } }
int main() { ThreadTree root; root = (ThreadTree)malloc(sizeof(ThreadNode)); root->data = 'A'; addLeftChild(root, 'B'); addRightChild(root, 'C'); addLeftChild(root->lchild, 'D'); addRightChild(root->lchild, 'E'); addRightChild(root->lchild->lchild,'G'); addLeftChild(root->rchild, 'F'); InThreading(root); printf("中序序列:\n"); InThread(root); return 0; }
|
先序线索化
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
| #include<stdio.h> #include<stdlib.h> typedef struct ThreadNode { char data; struct ThreadNode *lchild, *rchild; int ltag, rtag; }ThreadNode, *ThreadTree;
ThreadNode *pre = NULL;
bool addLeftChild(ThreadTree root, char leftData) { ThreadTree leftNode = (ThreadTree)malloc(sizeof(ThreadNode)); leftNode->data = leftData; leftNode->lchild = NULL; leftNode->rchild = NULL; root->lchild = leftNode; return true; }
bool addRightChild(ThreadTree root, char rightData) { ThreadTree rightNode = (ThreadTree)malloc(sizeof(ThreadNode)); rightNode->data = rightData; rightNode->lchild = NULL; rightNode->rchild = NULL; root->rchild = rightNode; return true; }
void visit(ThreadNode *q) { if (q->lchild == NULL) { q->lchild = pre; q->ltag = 1; } if (pre != NULL && pre->rchild == NULL) { pre->rchild = q; pre->rtag = 1; } printf("%c ltag=%d rtag=%d\n", q->data,q->ltag,q->rtag); pre = q; }
void PreThread(ThreadTree T) { if (T != NULL) { visit(T); if (T->ltag == 0) { PreThread(T->lchild); } if (T->rtag == 0) { PreThread(T->rchild); } } }
void deltree(ThreadTree tree){ if (tree != NULL) { deltree(tree->lchild); deltree(tree->rchild); free(tree); } }
void CreatePreThread(ThreadTree T) { pre = NULL; if (T != NULL) { PreThread(T); if (pre->rchild == NULL) { pre->rtag = 1; } } }
int main() { ThreadTree root; root = (ThreadTree)malloc(sizeof(ThreadNode)); root->data = 'A'; addLeftChild(root, 'B'); addRightChild(root, 'C'); addLeftChild(root->lchild, 'D'); addRightChild(root->lchild, 'E'); addRightChild(root->lchild->lchild,'G'); addLeftChild(root->rchild, 'F'); CreatePreThread(root); deltree(root); return 0; }
|
后序线索化
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
| #include<stdio.h> #include<stdlib.h> typedef struct ThreadNode { char data; struct ThreadNode *lchild, *rchild; int ltag, rtag; }ThreadNode, *ThreadTree;
ThreadNode *pre = NULL;
bool addLeftChild(ThreadTree root, char leftData) { ThreadTree leftNode = (ThreadTree)malloc(sizeof(ThreadNode)); leftNode->data = leftData; leftNode->lchild = NULL; leftNode->rchild = NULL; root->lchild = leftNode; return true; }
bool addRightChild(ThreadTree root, char rightData) { ThreadTree rightNode = (ThreadTree)malloc(sizeof(ThreadNode)); rightNode->data = rightData; rightNode->lchild = NULL; rightNode->rchild = NULL; root->rchild = rightNode; return true; }
void visit(ThreadNode *q) { if (q->lchild == NULL) { q->lchild = pre; q->ltag = 1; } if (pre != NULL && pre->rchild == NULL) { pre->rchild = q; pre->rtag = 1; } printf("%c ltag=%d rtag=%d\n", q->data,q->ltag,q->rtag); pre = q; }
void PostThread(ThreadTree T) { if (T != NULL) { PostThread(T->lchild); PostThread(T->rchild); visit(T); } }
void deltree(ThreadTree tree){ if (tree != NULL) { deltree(tree->lchild); deltree(tree->rchild); free(tree); } }
void CreatePostThread(ThreadTree T) { pre = NULL; if (T != NULL) { PostThread(T); if (pre->rchild == NULL) { pre->rtag = 1; } } }
int main() { ThreadTree root; root = (ThreadTree)malloc(sizeof(ThreadNode)); root->data = 'A'; addLeftChild(root, 'B'); addRightChild(root, 'C'); addLeftChild(root->lchild, 'D'); addRightChild(root->lchild, 'E'); addRightChild(root->lchild->lchild,'G'); addLeftChild(root->rchild, 'F'); CreatePostThread(root); deltree(root); return 0; }
|