线索二叉树的定义如下:
https://www.jianshu.com/p/3965a6e424f5
程序实现:
//线索二叉树
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
typedef char ElemType;
typedef struct BITNODE //二叉树的结点
{
ElemType Data;
struct BITNODE *leftchild; //指向左孩子地址的指针
struct BITNODE *rightchild; //指向右孩子地址的指针
int ltag; //ltag为0时leftchild指向该结点的左孩子,为1时指向该结点的前驱
int rtag; //rtag为0时rightchild指向该结点的右孩子,为1时指向该结点的后继
}BiTNode, *BiTree;
BiTree pre; //表示刚刚遍历过的前一个结点
int sum; //记录叶结点数
//创建二叉树—前序创建,约定用户遵照前序遍历的方式输入数据
void CreatBinaryTree_first(BiTree *T)
{
ElemType c;
scanf("%c", &c);
if (c == ' ')
{
*T = NULL;
}
else
{
*T = (BiTNode*)malloc(sizeof(BiTNode));
(*T)->Data = c;
(*T)->ltag = 0;
(*T)->rtag = 0; //先初始化leftchild和rightchild指向结点的左孩子和右孩子,在遍历线索化过程中更改
CreatBinaryTree_first(&(*T)->leftchild);
CreatBinaryTree_first(&(*T)->rightchild);
}
}
//遍历二叉树过程要进行的操作
void visit(ElemType c)
{
//显示各结点
printf("%c", c);
}
//叶子结点总数
void leafnodenum(BiTree T)
{
if (T->ltag == 1 && T->rtag ==1)
{
sum += 1;
}
}
//中序遍历线索化—遍历线索二叉树要采用中序遍历
void inorder(BiTree T)
{
if (T)
{
inorder(T->leftchild);
//visit(T->Data);
//leafnodenum(T);
if (!T->leftchild)
{
T->ltag = 1;
T->leftchild = pre;
}
if (!pre->rightchild) //不能是T->rightchild,因为还没走过后继结点,不知道后继结点是哪个
{
pre->rtag = 1;
pre->rightchild = T;
}
pre = T;
inorder(T->rightchild);
}
}
//初始化一个头指针-pre,指向树的根节点
void InOrderThreading(BiTree *p, BiTree T)
{
*p = (BiTNode *)malloc(sizeof(BiTNode));
(*p)->ltag = 0;
(*p)->rtag = 1;
(*p)->rightchild = *p;
if (!T) //如果二叉树不存在
{
(*p)->leftchild = *p;
}
else
{
(*p)->leftchild = T;
pre = *p;
inorder(T);
//令头指针和树的最后结点连接起来
pre->rightchild = *p;
pre->rtag = 1;
(*p)->rightchild = pre;
}
}
//中序遍历—执行需要的操作
void inordertree(BiTree P)
{
BiTree T;
T = P->leftchild;
while (T != P)
{
while (T->ltag == 0)
{
T = T->leftchild;
}
visit(T->Data);//输出结点
leafnodenum(T);//计算叶结点总数
while (T->rtag == 1 && T->rightchild != P)
{
T = T->rightchild;
visit(T->Data);
leafnodenum(T);
}
T = T->rightchild;
}
}
int main()
{
BiTree T = NULL;
BiTree P = NULL;
CreatBinaryTree_first(&T);
InOrderThreading(&P, T); //总的初始化结束
printf("中序遍历的顺序为:\n");
inordertree(P); //执行操作
printf("\n叶结点数为:%d \n", sum);
system("pause");
return 0;
}
注意:在创建二叉树时要使用二级指针作为参数传入。 因为如果希望在一个函数的参数中改变一个指针的值,只能传这个指针的指针给这个函数。我理解的意思就是,如果我们调用函数时传入一个指针参数,我们在这个函数中不能修改这个指针的值,只能修改这个指针指向的内容,如果想要修改它的值,就必须把这个指针的指针作为参数传进去。
运行结果: