小甲鱼课程笔记
为什么需要线索二叉树呢?
二叉树存在比较严重的空间的浪费,设一共有n个结点,那么有一个孩子结点的结点就会有一个空间的浪费,而叶子结点就会有两个空间的浪费,那么每个二叉树都会有
n
+
1
n+1
n+1个空间的浪费!
那么此时就需要线索二叉树
而中序遍历可以解决这种麻烦。
引用自小甲鱼数据结构课程
上图的二叉树经过中序遍历之后的结果就会是:
HDIBEAFCG
我们发现换色的结点就是刚才空的地方浪费的结点,利用中序遍历刚好他们能处于字符中间,可以很好的利用这个空间来存放前驱和后继的指针。
但是对于上图的二叉树中序遍历过后的结果是: FDGBACE
黄色部分说明是只有一个空指针位粗体部分才右两个指针位。此时就需要扩容,用两个个bool类型的数字表示左右指针是否已经右了孩子结点。
代码:
#include <stdio.h>
#include <stdlib.h>
typedef char ElemType;
//线索存储表值位
// Link(0):表示指向左右孩子的指针
// Thread(1):表示指向前驱后继的线索
typedef enum {Link,Thread} PointerTag;
typedef struct BiThrNode{
char data;
struct BiThrNode *lchild,*rchild;
PointerTag ltag;
PointerTag rtag;
}BiThrNode , *BiThrTree;
// 全局变量,始种指向刚刚访问过的结点
BiThrTree pre;
//创建一棵二叉树,约定用户遵照前序遍历的方式输入数据
//前序输入例如输入ABC D E F
//中序遍历:CBDAEF
void CreateBiThrTree( BiThrTree *T){
char c;
scanf("%c",&c);
if(' '==c){
*T = NULL;
}else{
*T = (BiThrNode *)malloc(sizeof(BiThrNode));
(*T)->data = c;
(*T)->ltag = Link;
(*T)->rtag = Link;
CreateBiThrTree(&(*T)->lchild);
CreateBiThrTree(&(*T)->rchild);
}
}
//中序遍历线索化
InThreading(BiThrTree T){
if(T){
InThreading( T-> lchild );//递归左孩子线索化
//结点处理
if( !T->lchild ){ //如果该结点没有左孩子,设置ltag为Thread,并把lchild指向刚刚访问的结点。
T->ltag = Thread;
T->lchild = pre;
}
if( !pre->rchild){
pre->rtag = Thread;
pre->rchild = T;
}
pre = T;
InThreading( T-> rchild );//递归右孩子线索化
}
}
InOrderThreading( BiThrTree *p ,BiThrTree T){//创建前置指针
*p = (BiThrTree)malloc(sizeof(BiThrNode));//初始化
(*p)->ltag = Link;
(*p)->rtag = Thread;
(*p)->rchild = *p;
if(!T){
(*p)->lchild = *p;//如果T是空树,就连回自己
}else{
(*p)->lchild = T;
pre = *p;
InThreading(T);//线索化
pre->rchild = *p; //把指针连到和*P相连,构成循环
pre->rtag = Thread;
(*p)->rchild = pre;
}
}
void visit(char c){
printf("%c",c);
}
//中序遍历二叉树,非递归
void InOrderTraverse( BiThrTree T){
BiThrTree p;
p = T->lchild;
while( p!=T ){
while( p->ltag == Link){
p = p->lchild;
}
visit(p->data);
while(p->rtag == Thread && p->rchild != T){
p = p->rchild;
visit(p->data);
}
p = p->rchild;
}
}
int main()
{
BiThrTree P , T = NULL;
CreateBiThrTree( &T );
InOrderThreading(&P,T);
printf("中序遍历输出结果为:");
InOrderTraverse( P );
printf("\n");
return 0;
}
``