中序线索化二叉树+遍历(带头结点):
思路:创建过程与前序大同小异,主要在遍历过程中,循环遍历结束的条件需要注意一下,然后遍历思想:最左,接着找后继,接着找右子树,然后重新循环。
代码如下:
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#define maxsize 50
typedef char elemtype;
typedef struct node{
elemtype data;
struct node *lchild;//指向左孩子
struct node *rchild;//指向右孩子
int ltag; //用来标志前驱结点
int rtag; //用来标记后继结点
}bnode;
bnode *pre;
//构造二叉树
void createtree(bnode *&b, char *str)
{
bnode *st[maxsize],*p ; //创建结构体类型的指针栈数组
int top = -1,k,j=0; //top是 数组下标,初始为-1;
char ch = str[j];
b = NULL; //空二叉树
while(ch != '\0')
{
switch(ch)
{
//下面3步是用来将数据入栈和设置k值的作用.
case '(': st[++top]=p;k=1;break;
case ')': top--;break;
case ',': k = 2;break;
default:
p = (bnode *)malloc(sizeof(bnode)); //创建一个结构体树节点指针类型
//创建完成之后,将数据赋值给创建的节点,并新创建的节点的左右指针初始化为空(NULL)
p ->data = ch;
p ->ltag = p->rtag =0;
p ->lchild =NULL;
p ->rchild =NULL;
if(b==NULL) //参数中传入的b是空,这一步用来构建根节点。
{
b = p;
}
else{
switch(k) //构建完根结点之后,将循环传入的字符元素data经过k判断是当作左孩子还是右孩子。
{
case 1:st[top]->lchild = p;break;
case 2:st[top]->rchild = p;break;
}
}
}
j++;
ch = str[j];
}
}
//输出二叉树
void disptree(bnode *b)
{
if(b!=NULL) //这里判断,如果递归的这棵树为空数,也就是没有任何元素的一棵树,就退出。
{
printf("%c",b->data);
if(b->lchild!=NULL || b->rchild!=NULL)//只要满足其中一个条件,就一定有子数
{
printf("("); //只要有孩子,就必须打印出 (
disptree(b->lchild); //先左子树递归
if(b->rchild!=NULL) printf(","); //如归要递归遍历到右子树,如果右子树为空,不用执行这一步
disptree(b->rchild);//在右子树递归
printf(")"); //只要有孩子,就必须打印出 )
}
}
}
//----————————————————————————————-————
//将二叉树线索化 与前序遍历的思路一样,主要是递归的先后顺序位置要调整一下。
void incluetree(bnode *p)
{
if(p)
{
incluetree(p->lchild);
if(p->lchild == NULL)
{
p->lchild = pre;
p->ltag = 1;
}
if(pre!=NULL && pre->rchild == NULL)//注意,pre = p;
{
pre->rchild = p;
pre->rtag= 1;
}
pre =p;
incluetree(p->rchild);
}
}
//中序构建线索二叉树
bnode *createinclues(bnode *b)
{
//创建头结点以及初始化,与前序构造的一样
bnode *root = (bnode *)malloc(sizeof(bnode));
root->ltag = 0;
root->rtag = 1;
root->rchild = root;
if(b == NULL)
{
root ->lchild = root;
}
else{
root->lchild = b;
pre = root;
incluetree(b);
//注意最后一个结点与头结点的处理
pre->rchild = root;
pre->rtag = 1;
root ->rchild = pre;
}
return root;
}
//中序遍历线索二叉树。
void incluesearch(bnode *tb)
{
bnode *b = tb->lchild;//指向根基点
while(b!=tb) //注意循环的条件
{
while(b->ltag!=1)//先找到最左边的结点
{
b = b->lchild;
}
printf("%c ", b->data);
//接着找后继结点
while(b->rtag ==1 && b->rchild !=tb)
{
b = b->rchild;
printf("%c ",b->data);
}
//然后找右子树 ,接着循环上面的操作。
b = b->rchild;
}
}
//—————————————————————————————————
int main()
{
bnode *b,*tp=NULL;
bnode *root =NULL;
printf("创建二叉树: ");
createtree(b,"a(b(d(,g)),c(e,f))");
disptree(b);
printf("\n");
printf("中序线索化遍历: ");
root = createinclues(b);
incluesearch(root);
printf("\n");
return 0;
}
/* a
b c
d e
g
*/
程序运行如下: