最初版本:利用链表保存二叉树
不足:浪费指针位置。
二叉树结构体
typedef char TElemType;
typedef struct BiTree{
TElemType data;
struct BiTree *Lchild,*Rchild;
}*BiTree,BiTNode;
每一个结点保存数据,左孩子和右孩子的数据。
创建二叉树
利用前序遍历法输入二叉树,没有的结点用#补全
注意传入的参数 是指向指针的指针 这样才能改变指针的值
c++的话也可以用引用代替
void Create_Bitree(BiTree *T){ //前序输入
TElemType data;
scanf("%c",&data);
if(data == '#') T = NULL;
else{
if(!(*T = (BiTree)malloc(sizeof(BiTNode)))) exit(1);
(*T)->data = data;
Create_Bitree(&(*T)->Lchild);
Create_Bitree(&(*T)->Rchild);
}
}
前序遍历法遍历树
void Pre_Order(BiTree T){
if(T!=NULL){
printf("%c",T->data);
Pre_Order(T->Lchild);
Pre_Order(T->Rchild);
}
}
中序遍历法遍历
void In_Order(BiTree T){
if(T!=NULL){
In_Order(T->Lchild);
printf("%c",T->data);
In_Order(T->Rchild);
}
}
后序遍历法遍历
void Post_Order(BiTree T){
if(T!=NULL){
Post_Order(T->Lchild);
Post_Order(T->Rchild);
printf("%c",T->data);
}
}
主函数
int main(){
BiTree T;
printf("请前序遍历输入树\n");
Create_Bitree(&T);
printf("前序输出这个二叉树为:\n");
Pre_Order(T);
printf("\n");
printf("中序输出这个二叉树为:\n");
In_Order(T);
printf("\n");
printf("后序输出这个二叉树为:\n");
Post_Order(T);
printf("\n");
return 0;
}
进阶版本:(线索二叉树)
利用空指针位置储存前驱和后续;创造头节点,左孩子为树根,右孩子为中序最末结点(投影最后结点)。
结构体中加入Tag位保存是否该指针指向子结点。
若为Link则指向子结点,若为Thread则指向前驱或后续结点。
中序排序第一个(最左孩子)的左指针指向头结点,最后一个(最右孩子)的右指针指向头结点。
结构体创建如下
typedef char TElemType;
typedef enum { Link,Thread } PointerTag;
typedef struct BiTree{
TElemType data;
struct BiTree *Lchild,*Rchild;
PointerTag LTag,RTag;
}*BiTree,BiTNode;
先来看看主函数
注意头结点由于是连接整个头尾的
所以如果在建立前序后继指针之前创建的话,就会进入死循环。
int main(){
BiTree T,THead;
printf("请前序遍历输入树\n");
THead = (BiTree) malloc(sizeof(BiTNode));
Create_Bitree(&T);//创建树
pre = THead;
In_Threading(T);//给树加上前驱和后续指针
Create_Head(&THead,T);//创建头结点
printf("中序输出树\n");
In_Order_Traverse(THead);//中序遍历树
printf("\n");
return 0;
}
创建输入树时与原先一样
void Create_Bitree(BiTree *T){ //前序输入
TElemType data;
scanf("%c",&data);
if(data == '#') T = NULL;
else{
if(!(*T = (BiTree)malloc(sizeof(BiTNode)))) exit(1);
(*T)->data = data;
Create_Bitree(&(*T)->Lchild);
Create_Bitree(&(*T)->Rchild);
}
}
令空余指针分别指向前驱和后继结点。
其中pre用来保存上一个结点的信息。
BiTree pre;
void In_Threading(BiTree T){
if(T){
In_Threading(T->Lchild);
if(!T->Lchild){
T->LTag = Thread;
T->Lchild = pre;
}
if(!pre->Rchild){
pre->RTag = Thread;
pre->Rchild = T;
}
pre = T;
In_Threading(T->Rchild);
}
}
创建头结点
void Create_Head(BiTree *THead,BiTree T){
(*THead)->LTag = Link;
(*THead)->Lchild = T;//左孩子指向树根
(*THead)->RTag = Thread;
while(T->Rchild->Rchild) T = T->Rchild;
T->Rchild->Rchild = (*THead); //最右结点的右孩子指向头结点
T->Rchild->RTag = Thread;
(*THead)->Rchild = T; //头结点的右孩子指向最右结点
}
遍历函数
void In_Order_Traverse(BiTree T){
BiTree P = T->Lchild;
while(P!=T){
while(P->LTag == Link){
P = P->Lchild;
}//到达最左孩子
printf("%c",P->data);
while(P->RTag == Thread &&P->Rchild !=T){
P = P->Rchild;//后继指针开始起作用了 一路遍历下去。
printf("%c",P->data);
}//该结点的左子树遍历完毕
P = P->Rchild;//开始该结点的的右子树
}
}
举个例子 各结点保存如下
线索二叉树相较于普通二叉树,其优势在于能更高效的保存信息。 在树中任意一个叶子结点,都可以知道其前驱和后继结点,而不占更多的储存空间。
最后附上完整代码
#include <stdio.h>
#include <stdlib.h>
typedef char TElemType;
typedef enum { Link,Thread } PointerTag;
typedef struct BiTree{
TElemType data;
struct BiTree *Lchild,*Rchild;
PointerTag LTag,RTag;
}*BiTree,BiTNode;
void Create_Bitree(BiTree *T){ //前序输入
TElemType data;
scanf("%c",&data);
if(data == '#') T = NULL;
else{
if(!(*T = (BiTree)malloc(sizeof(BiTNode)))) exit(1);
(*T)->data = data;
Create_Bitree(&(*T)->Lchild);
Create_Bitree(&(*T)->Rchild);
}
}
BiTree pre;
void In_Threading(BiTree T){
if(T){
In_Threading(T->Lchild);
if(!T->Lchild){
T->LTag = Thread;
T->Lchild = pre;
}
if(!pre->Rchild){
pre->RTag = Thread;
pre->Rchild = T;
}
pre = T;
In_Threading(T->Rchild);
}
}
void In_Order_Traverse(BiTree T){
BiTree P = T->Lchild;
while(P!=T){
while(P->LTag == Link){
P = P->Lchild;
}
printf("%c",P->data);
while(P->RTag == Thread &&P->Rchild !=T){
P = P->Rchild;
printf("%c",P->data);
}
P = P->Rchild;
}
}
void Create_Head(BiTree *THead,BiTree T){
(*THead)->LTag = Link;
(*THead)->Lchild = T;
(*THead)->RTag = Thread;
while(T->Rchild->Rchild) T = T->Rchild;
T->Rchild->Rchild = (*THead);
T->Rchild->RTag = Thread;
(*THead)->Rchild = T;
}
int main(){
BiTree T,THead;
printf("请前序遍历输入树\n");
THead = (BiTree) malloc(sizeof(BiTNode));
Create_Bitree(&T);
pre = THead;
In_Threading(T);
Create_Head(&THead,T);
printf("后序输出树\n");
In_Order_Traverse(THead);
printf("\n");
return 0;
}