#include <stdio.h>
#include <stdlib.h>
//线索二叉树实现
//利用空闲的n+1个空链域 解决 中序、先序、后序访问序列的 某个结点找前驱 和 找和后继的问题
typedef struct {
int value;
} ElemType;
typedef struct ThreadNode {
ElemType data;
struct ThreadNode *lchild, *rchild;
int ltag = 0, rtag = 0;//左有标志位 为0的时候为指向左右孩子结点,为1的时候表示指针是线索
struct ThreadNode *parent;
} BiTNode, ThreadNode, *BiTree, *ThreadTree;
//初始化一颗空树
void InitBiTNode(BiTree &bt) {
bt = NULL;
}
ThreadNode *pre = NULL;//全局变量 pre 指向当前访问结点的前驱
void visit(ThreadNode *q) {
printf("%d ", q->data);
//pre此时指向的是当前访问结点的前驱
if (q->lchild == NULL) { //当前结点的 左孩子为不存在
q->lchild = pre; //设置 q 的左线索 指向 pre
q->ltag = 1;
}
if (pre != NULL && pre->rchild == NULL) {//前驱结点的右孩子如果为空
pre->rchild = q; // 设置前驱结点的 右线索指向 q
pre->rtag = 1; //修改标志位
}
pre = q;
}
//中序线索化
void InThread(ThreadTree &T) {
if (T != NULL) {
InThread(T->lchild);
visit(T);
InThread(T->rchild);
}
}
//创建中序线索化
void CreateInThread(ThreadTree T) {
printf("构建中序线索二叉树\n");
pre = NULL;//pre指针指向NULL
if (T != NULL) {
InThread(T);//中序线索化
if (pre->rchild == NULL) {//如果最后一个访问结点没有右孩子,设置 右线索为 NULL,同时修改标志位
pre->rtag = 1;
}
}
printf("\n");
}
//找到p为根的子树中,第一个被中序遍历的结点
ThreadNode *InFirstNode(ThreadNode *p) {
while (p->ltag == 0) {
p = p->lchild;
}
return p;
}
//中序线索二叉树中找到结点p的后继结点
ThreadNode *InNextNode(ThreadNode *p) {
if (p->rtag == 0) {
//中序遍历顺序为左 根 右
//下一个要访问的结点为 右子树 最左边的结点
return InFirstNode(p->rchild);//左子树中最左下结点
} else {
return p->rchild;
}
}
//对中序线索二叉树进行中序遍历(利用线索实现的非递归算法)
void Inorder(ThreadNode *T) {
for (ThreadNode *p = InFirstNode(T); p != NULL; p = InNextNode(p)) {
printf("%d ", p->data);
}
printf("\n");
}
//找到p为根的子树中,最后一个被中序遍历的结点
ThreadNode *InLastNode(ThreadNode *p) {
while (p->rtag == 0) {
p = p->rchild;
}
return p;
}
//中序线索二叉树中找到结点p的前驱结点
ThreadNode *InPreNode(ThreadNode *p) {
if (p->ltag == 0) {
//中序遍历顺序为根 左 右
//当前结点为结点,前一个被访问的结点为左子树中最靠右的结点
return InLastNode(p->lchild);//左子树中最左下结点
} else {
return p->lchild;
}
}
//对中序线索二叉树进行逆向中序遍历(利用线索实现的非递归算法)
void RevInorder(ThreadNode *T) {
for (ThreadNode *p = InLastNode(T); p != NULL; p = InPreNode(p)) {
printf("%d ", p->data);
}
printf("\n");
}
//先序线索化
void PreThread(ThreadTree T) {
if (T != NULL) {
visit(T);
if (T->ltag == 0) {//防止T的指针左指针被修改为前驱线索而产生循环
PreThread(T->lchild);
}
if (T->rtag == 0) {
PreThread(T->rchild);
}
}
}
//创建先序线索化
void CreatePreThread(ThreadTree T) {
printf("构建先序线索二叉树\n");
pre = NULL;//pre指针指向NULL
if (T != NULL) {
PreThread(T);//中序线索化
if (pre->rchild == NULL) {//如果最后一个访问结点没有右孩子,设置 右线索为 NULL,同时修改标志位
pre->rtag = 1;
}
}
printf("\n");
}
//先序线索二叉树中找到结点p的后继结点
ThreadNode *PreNextNode(ThreadNode *p) {
if (p->rtag == 0) {
//先序遍历顺序为根 右 左
//一定有右孩子
if (p->ltag == 0 && p->lchild != NULL) {//如果有左孩子,先序后继为左孩子
return p->lchild;
} else {
return p->rchild;
}
} else { //如果是线索
return p->rchild;
}
}
ThreadNode *LeftDeepestNode(ThreadNode *p);
ThreadNode *RightDeepestNode(ThreadNode *p);
//因为先序遍历顺序为根 左 右,所有,如果 p->ltg == 0时候,无法通过找到前驱,需要通过重新遍历或者三叉链表实现
//三叉链表寻找先序线索前驱结点
ThreadNode *PrePreNode(ThreadTree root, ThreadNode *p) {
if (p->ltag == 0) {
//4.如果p 是根结点,没有前驱
if (p == root)
return NULL;
if (p->parent != NULL) {
ThreadNode *parent = p->parent;
//先序访问顺序:根 左 右
//1.如果p结点为父结点的左孩子,那么父结点为前驱结点
//2.如果p结点为右孩子,且左兄弟为NULL,那么父结点为前驱结点
if (parent->lchild == p ||
(parent->lchild == NULL && parent->rchild == p)) {
return parent;
} else {
//3.如果p是右孩子,且左兄弟非空
//找到左兄弟子树中按照先序遍历最后一个访问的结点
//先往右走,右边没了往左走,左边没了往右走,直到找到最深处的叶子结点
return RightDeepestNode(parent->lchild);
}
} else {
return NULL;
}
} else {
return p->lchild;
}
}
//后序线索化
void PostThread(ThreadTree &T) {
if (T != NULL) {
PostThread(T->lchild);
PostThread(T->rchild);
visit(T);
}
}
//创建后序线索化
void CreatePostThread(ThreadTree &T) {
printf("构建后序线索二叉树\n");
pre = NULL;//pre指针指向NULL
if (T != NULL) {
PostThread(T);//中序线索化
if (pre->rchild == NULL) {//如果最后一个访问结点没有右孩子,设置 右线索为 NULL,同时修改标志位
pre->rtag = 1;
}
}
printf("\n");
}
//后序线索找前驱
ThreadNode *PostPreNode(ThreadNode *p) {
if (p->ltag == 0) {
//p 一定有左孩子
//因为后序访问顺序为: 左 右 根
//若p 有右孩子结点q,那么前驱为按照后序遍历最后一个访问的结点
//如果q没有孩子,那么前驱就是q,如果q有孩子,按照后序遍历访问顺序 左右根,在q这颗子树中,q为根结点,所有前驱是q
if (p->rtag == 0 && p->rchild != NULL) {
return p->rchild;
} else {
//如果p 没有右孩子,那么前驱为左孩子
return p->lchild;
}
} else {
return p->lchild;
}
}
ThreadNode *RightDeepestNode(ThreadNode *p) {
while (p->rtag == 0) {
p = p->rchild;
}
if (p->ltag == 1) {
return p;
} else {
return LeftDeepestNode(p);
}
}
ThreadNode *LeftDeepestNode(ThreadNode *p) {
while (p->ltag == 0) { //寻找最左边的结点
p = p->lchild;
}
if (p->rtag == 1) { // 如果该结点没有右结点
return p;
} else {
return RightDeepestNode(p);
}
}
//因为后序遍历顺序为左 右 根,所有,如果 p->rtg == 0时候,无法通过找到后继,需要通过重新遍历或者三叉链表实现
//三叉链表寻找后序线索后继结点
ThreadNode *PostPostNode(ThreadTree root, ThreadNode *p) {
if (p->rtag == 0) {
//4.如果p 是根结点,没有前驱
if (p == root)
return NULL;
if (p->parent != NULL) {
ThreadNode *parent = p->parent;
//后序访问顺序:左 右 根
//1.如果p结点为父结点的右孩子,那么父结点为前驱结点
//2.如果p结点为左孩子,且右兄弟为NULL,那么父结点为前驱结点
if (parent->rchild == p ||
(parent->rchild == NULL && parent->lchild == p)) {
return parent;
} else {
//3.如果p是左孩子,且右兄弟非空
//找到右兄弟子树中按照后序遍历第一个访问的结点
//先往左走,左边没了往右走,右边没了往左走,直到找到最深处的叶子结点
return LeftDeepestNode(parent->rchild);
}
} else {
return NULL;
}
} else {
return p->rchild;
}
}
int main() {
BiTree bt;
InitBiTNode(bt);
//插入根结点
BiTNode *root = (BiTNode *) malloc(sizeof(BiTNode));
root->data = {1};
root->lchild = NULL;
root->rchild = NULL;
root->ltag = 0;
root->rtag = 0;
bt = root;
BiTNode *t1 = (BiTNode *) malloc(sizeof(BiTNode));
t1->data = {6};
t1->ltag = 0;
t1->rtag = 0;
root->lchild = t1;
BiTNode *t11 = (BiTNode *) malloc(sizeof(BiTNode));
t11->data = {3};
t11->ltag = 0;
t11->rtag = 0;
t1->lchild = t11;
t11->lchild = NULL;
t11->rchild = NULL;
BiTNode *t12 = (BiTNode *) malloc(sizeof(BiTNode));
t12->data = {9};
t12->ltag = 0;
t12->rtag = 0;
t1->rchild = t12;
BiTNode *t121 = (BiTNode *) malloc(sizeof(BiTNode));
t121->data = {8};
t121->ltag = 0;
t121->rtag = 0;
t12->lchild = t121;
t12->rchild = NULL;
BiTNode *t1211 = (BiTNode *) malloc(sizeof(BiTNode));
t1211->data = {7};
t1211->ltag = 0;
t1211->rtag = 0;
t1211->lchild = NULL;
t1211->rchild = NULL;
t121->lchild = t1211;
t121->rchild = NULL;
BiTNode *t2 = (BiTNode *) malloc(sizeof(BiTNode));
t2->data = {13};
t2->ltag = 0;
t2->rtag = 0;
root->rchild = t2;
BiTNode *t21 = (BiTNode *) malloc(sizeof(BiTNode));
t21->data = {11};
t21->ltag = 0;
t21->rtag = 0;
t2->lchild = t21;
BiTNode *t211 = (BiTNode *) malloc(sizeof(BiTNode));
t211->data = {10};
t211->ltag = 0;
t211->rtag = 0;
t21->lchild = t211;
t211->lchild = NULL;
t211->rchild = NULL;
t21->rchild = NULL;
BiTNode *t22 = (BiTNode *) malloc(sizeof(BiTNode));
t22->data = {14};
t22->ltag = 0;
t22->rtag = 0;
t2->rchild = t22;
t22->lchild = NULL;
t22->rchild = NULL;
root->parent = NULL; //1
t1->parent = root;//1->6 左
t2->parent = root;//1->13 右
t11->parent = t1;//6->3 左
t12->parent = t1;//6->9 有
t121->parent = t12; //9->8 左
t1211->parent = t121;//8->7 左
t21->parent = t2;//13->11 左
t22->parent = t2;//13->14 右
t211->parent = t21;//11->10 左
ThreadNode *t0 = t121;
// CreateInThread(bt);
// ThreadNode *n1 = InPreNode( t0);
// ThreadNode *n2 = InNextNode(t0);
// if (n1 != NULL && n2 != NULL) {
// printf("%d 的线索前驱结点:%d,线索后继结点:%d\n", t0->data, n1->data, n2->data);
// } else if (n1 == NULL && n2 != NULL) {
// printf("%d 的线索后继结点:%d\n", t0->data, n2->data);
// } else if (n1 != NULL && n2 == NULL) {
// printf("%d 的线索前驱结点:%d\n", t0->data, n1->data);
// }
// printf("对中序线索二叉树进行中序遍历(利用线索实现的非递归算法):\n");
// Inorder(bt);
// printf("对中序线索二叉树进行逆向中序遍历(利用线索实现的非递归算法):\n");
// RevInorder(bt);
// CreatePreThread(bt);
// ThreadNode *n1 = PrePreNode(root, t0);
// ThreadNode *n2 = PreNextNode(t0);
//
// if (n1 != NULL && n2 != NULL) {
// printf("%d 的线索前驱结点:%d,线索后继结点:%d\n", t0->data, n1->data, n2->data);
// } else if (n1 == NULL && n2 != NULL) {
// printf("%d 的线索后继结点:%d\n", t0->data, n2->data);
// } else if (n1 != NULL && n2 == NULL) {
// printf("%d 的线索前驱结点:%d\n", t0->data, n1->data);
// }
CreatePostThread(bt);
ThreadNode *n1 = PostPreNode(t0);
ThreadNode *n2 = PostPostNode(root, t0);
if (n1 != NULL && n2 != NULL) {
printf("%d 的线索前驱结点:%d,线索后继结点:%d\n", t0->data, n1->data, n2->data);
} else if (n1 == NULL && n2 != NULL) {
printf("%d 的线索后继结点:%d\n", t0->data, n2->data);
} else if (n1 != NULL && n2 == NULL) {
printf("%d 的线索前驱结点:%d\n", t0->data, n1->data);
}
return 0;
}
“相关推荐”对你有帮助么?
-
非常没帮助
-
没帮助
-
一般
-
有帮助
-
非常有帮助
提交