在二叉树的2n个链中,有n+1个空链。用线索即指向其他结点的指针来利用这些空链。
1.左儿子为空,将指向左儿子的指针指向中序遍历的前驱结点
2.右儿子为空,将指向右儿子的指针指向中序遍历的后继结点
使用left_thread和right_thread来标记当前结点的左右指针指向线索还是左右儿子。
结点结构如下:
typedef struct node{
struct node *left;
struct node *right;
int data;
short int left_thread;
short int right_thread;
}BinaryNode;
将二叉树线索化
需要使用一个全局变量pre记录中序遍历的前一个结点.
若当前结点p的左儿子为空,p->left=pre,p->left_thread=1
若pre的右儿子为空,pre->right=p,pre->right_thread=1 (pre的后继必须在访问p时才能确定)
二叉树第一个访问的结点的left指针和最后一个访问的right指针的线索不确定,需要添加一个总的头指针,使不确定的线索指向该指针。将头结点的right指向该二叉树。
BinaryNode *pre=NULL;
void ThreadInOrder(BinaryNode *p){
if(p){
ThreadInOrder(p->left);
if(p->left==NULL){
p->left=pre;
p->left_thread=1;
}
if(pre->right==NULL){
pre->right=p;
pre->right_thread=1;
}
pre=p;
ThreadInOrder(p->right);
}
}
BinaryNode* ThreadRoot(BinaryNode *tree){
BinaryNode *root;
root=(BinaryNode *)malloc(sizeof(BinaryNode));
root->left=root;
root->right=tree;
root->right_thread=0;
root->left_thread=1;
pre=root;
ThreadInOrder(tree);
pre->right=root;
pre->right_thread=1;
return root;
}
查找某一个结点的后继结点
如果该结点p的right_thread为1,则p->right为p的后继
否则为p的右子树沿着左儿子链的最后一个结点即left_thread为1的结点
BinaryNode* FindSucceed(BinaryNode *tree){
BinaryNode *succ=tree->right;
if(tree->right_thread==0){
while(succ->left_thread==0)
succ=succ->left;
}
return succ;
}
中序非递归遍历
void InOrder(BinaryNode *root){
BinaryNode *p;
p=root;
while(1){
p=FindSucceed(p);
if(p==root)
break;
printf("%d\t",p->data);
}
}