【1】个人想法:前后看了2~3周吧感觉真难。不参考别人的代码,要自己想出来难度很大。但也可以试着想一想
代码是用C写的。
【2】重点知识:
(1)二叉树并不难理解
(2)n个节点的二叉树,有空域n+1个。证明:n个节点有域2n个;那个树形图里面,一条线代表占用了一个域,只有根上面没线,所以共占用n-1个域。那剩下的域就是n+1个了。
(3)给二叉树加上线索后,感觉就像是个循环链表一样的。但并不是,具体像什么并不能直观地想象出来,或许不需要
【3】关于代码:代码里面比较有意思的函数是:
create_tree(二叉树初始化。一开始觉得这个函数挺简单,后来觉得有点意思);
thrTree_mid_inner(中序线索化。它把前驱,后继分在2个循环里面赋值,这个想法很重要);
last_ergodic(后序线索化二叉树遍历。我想了一阵后序到底该怎么遍历,看到可以反过来遍历才觉得醍醐灌顶)
【4】代码
#include <stdio.h>
#include <malloc.h>
typedef char ElemType;
typedef enum {
OK=1,
ERROR=0
}Status;
typedef enum {Link=0,Thread=1}clue;
typedef struct Tnode{
ElemType data;
struct Tnode *lchild,*rchild;
clue ltag,rtag;
}TNode,*thrBitTree;
thrBitTree pre;
void create_tree(thrBitTree *T,char **arr){
char c;
sscanf(*arr,"%c",&c);
(*arr)++;
if(c=='.'){
*T=NULL;
}else{
*T=(thrBitTree)malloc(sizeof(TNode));
(*T)->data=c;
(*T)->ltag=(*T)->rtag=Link;
create_tree(&(*T)->lchild,arr);
create_tree(&(*T)->rchild,arr);
}
}
void visit(TNode* T){
if(T){
printf("%c ",T->data);
}
}
void visit_d(TNode* T){
if(T){
printf("%d|%c|%d\n",T->ltag,T->data,T->rtag);
}
}
//递归前序遍历
void pre_ergodic_r(thrBitTree T){
if(T){
visit(T);
pre_ergodic_r(T->lchild);
pre_ergodic_r(T->rchild);
}
}
//递归中序遍历
void mid_ergodic_r(thrBitTree T){
if(T){
mid_ergodic_r(T->lchild);
visit(T);
mid_ergodic_r(T->rchild);
}
}
//递归后序遍历
void last_ergodic_r(thrBitTree T){
if(T){
last_ergodic_r(T->lchild);
last_ergodic_r(T->rchild);
visit(T);
}
}
//-----------------------------前序线索化----
void pre_ergodic(thrBitTree P){
thrBitTree T=(thrBitTree)malloc(sizeof(TNode));
T=P->lchild;
while(T!=P){
visit(T);
if(T->ltag==Link){
T=T->lchild;
}
else{
T=T->rchild;
}
}
}
void thrTree_pre_inner(thrBitTree T){
if(T){
if(T->lchild==NULL){
T->lchild=pre;
T->ltag=Thread;
}
if(pre->rchild==NULL){
pre->rchild=T;
pre->rtag=Thread;
}
pre=T;
if(T->ltag==Link)
thrTree_pre_inner(T->lchild);
if(T->rtag==Link)
thrTree_pre_inner(T->rchild);
}
}//-----------------------------endl----
//-----------------------------中序线索化----
void mid_ergodic(thrBitTree P){
thrBitTree T=(thrBitTree)malloc(sizeof(TNode));
T=P->lchild;
while(T!=P){
while(T->ltag==Link){
T=T->lchild;
}
visit(T);
while(T->rtag==Thread && T->rchild!=P){
T=T->rchild;
visit(T);
}
T=T->rchild;
}
}
void thrTree_mid_inner(thrBitTree T){
if(T){
thrTree_mid_inner(T->lchild);
if(T->lchild==NULL){
T->lchild=pre;
T->ltag=Thread;
}
if(pre->rchild==NULL){
pre->rchild=T;
pre->rtag=Thread;
}
pre=T;
thrTree_mid_inner(T->rchild);
}
}//-----------------------------endl----
//-----------------------------后序线索化----
typedef struct SNode{
ElemType data;
struct SNode* next;
}SNode,*StackList;
//带头节点的栈初始化
void initStack(StackList *S){
*S=(StackList)malloc(sizeof(SNode));
(*S)->next=NULL;
}
void Push(StackList S,ElemType e){
if(S==NULL) return;
SNode* newNode=(SNode*)malloc(sizeof(SNode));
newNode->data=e;
newNode->next=S->next;
S->next=newNode;
}
void printStack(StackList S){
if(S==NULL) return;
SNode* p=S->next;
while(p){
printf("%c ", p->data);
p=p->next;
}
printf("\n");
}
//可以按 根-右-左 再倒过来
//倒过来这个,用栈实现吧
void last_ergodic(thrBitTree P){
thrBitTree T=P->rchild;
StackList S=NULL;
initStack(&S);
while(T!=P){
//visit(T);
Push(S,T->data);
if(T->rtag==Link){
T=T->rchild;
}
else{
T=T->lchild;
}
}
printStack(S);
}
void thrTree_last_inner(thrBitTree T){
if(T){
if(T->ltag==Link)
thrTree_last_inner(T->lchild);
if(T->rtag==Link)
thrTree_last_inner(T->rchild);
if(T->lchild==NULL){
T->lchild=pre;
T->ltag=Thread;
}
if(pre->rchild==NULL){
pre->rchild=T;
pre->rtag=Thread;
}
pre=T;
}
}
//-----------------------------endl----
//给树加头节点
void thrTree(thrBitTree *P,thrBitTree T,void (*thrTree_inner)()){
*P=(thrBitTree)malloc(sizeof(TNode));
(*P)->rchild=*P;
(*P)->rtag=Thread;
(*P)->ltag=Thread;
if(T==NULL){
(*P)->lchild=*P;
}
else{
(*P)->lchild=T;
pre=*P;
thrTree_inner(T);
//防止后续线索化中根节点的右孩子被污染
if(pre!=(*P)->lchild){
pre->rtag=Thread;
pre->rchild=*P;
}
(*P)->rchild=pre;
}
}
void main(){
thrBitTree P,T;
//char *arr="ab.c..de...";
char *arr="HDA..C.B..GF.E....";
create_tree(&T,&arr);
//递归 遍历
printf("recrution:\n");
printf("pre_r:");
pre_ergodic_r(T);
printf("\n");
printf("mid_r:");
mid_ergodic_r(T);
printf("\n");
printf("last_r:");
last_ergodic_r(T);
printf("\n\n");
//无递归 遍历
printf("no-recrution:\n");
thrTree(&P,T,thrTree_pre_inner);
printf("pre:");
pre_ergodic(P);
printf("\n");
free(P);free(T);
arr="HDA..C.B..GF.E....";
create_tree(&T,&arr);
thrTree(&P,T,thrTree_mid_inner);
printf("mid:");
mid_ergodic(P);
printf("\n");
free(P);free(T);
arr="HDA..C.B..GF.E....";
create_tree(&T,&arr);
thrTree(&P,T,thrTree_last_inner);
printf("last_reverse:");
last_ergodic(P);
printf("\n");
}
【5】结果
C:\Users\xxx>gcc D:/testP/cc.c -o D:/testP/cc.o
C:\Users\xxx>D:/testP/cc.o
recrution:
pre_r:H D A C B G F E
mid_r:A D C B H F E G
last_r:A B C D E F G H
no-recrution:
pre:H D A C B G F E
mid:A D C B H F E G
last_reverse:A B C D E F G H