本文是作者整理网上代码得到!
输入先序序列:ABDH##I##EJ###CF##G##
#include <stdio.h>
#include <malloc.h>
#include <iostream>
#define max 100
using namespace std;
typedef char datatype;
typedef enum PointerTag { Link, Thread };
struct node
{
struct node *lchild;
struct node *rchild;
datatype data;
//int level;//层级
PointerTag ltag;
PointerTag rtag;
};
typedef struct node *BTREE;
void CreateBT(BTREE &T)//建树,按先序顺序输入节点
{
char ch;
scanf_s("%c", &ch);
if (ch == '#')
{
T = NULL;
return;
}
else
{
T = (BTREE)malloc(sizeof(node));
if (!T)
exit(1);
T->data = ch;
T->ltag = Link;
T->rtag = Link;
CreateBT(T->lchild);
CreateBT(T->rchild);
}
}
BTREE pre = (node*)malloc(sizeof(node));
//实现二叉链表的先序线索化;
void PreThreading(BTREE P) {
if (P) {
if (!P->lchild) {
P->ltag = Thread;
P->lchild = pre;
}
else P->ltag = Link;
if (!pre->rchild) {
pre->rtag = Thread;
pre->rchild = P;
}
else P->rtag = Link;
pre = P;
if (Link == P->ltag)
PreThreading(P->lchild);
if (Link == P->rtag)
PreThreading(P->rchild);
}
}
//加入头结点,先序线索二叉树
void PreOrderThread_Head(BTREE &head, BTREE &P) {
head = (node*)malloc(sizeof(BTREE));
head->rchild = head;//右指针回指
head->ltag = Link;
head->rtag = Thread;//建立头结点
if (!P) {
head->lchild = head;//空树
}
else {
head->lchild = P;
pre = head;
PreThreading(P);//先序遍历进行先序线索化
pre->rtag = Thread;
pre->rchild = head;
head->rchild = pre;
}
}
//求先序线索二叉树中结点p 的先序顺序的后继结点p*
BTREE PreNext(BTREE p)
{
BTREE q;
if (p->ltag == Link) q = p->lchild;
else q = p->rchild;
return q;
}
//实现先序线索链表的先序遍历。
void ForOrderTraverse_Thr(BTREE T) {
BTREE p = T->lchild;
while (p != T)
{
printf("%c", p->data);
p = PreNext(p);
}
}
//----------------------------------------------------------------------------------------------------------------------------
//实现二叉链表的中序线索化;
void InThreading(BTREE P) {
if (P) {
InThreading(P->lchild);
if (!P->lchild) {
P->ltag = Thread;
P->lchild = pre;
}
else P->ltag = Link;
if (!pre->rchild) {
pre->rtag = Thread;
pre->rchild = P;
}
else P->rtag = Link;
pre = P;
InThreading(P->rchild);
}
}
//加入头结点,中序线索二叉树
void InOrderThread_Head(BTREE &head, BTREE &P) {
head = (node*)malloc(sizeof(BTREE));
head->rchild = head;//右指针回指
head->ltag = Link;
head->rtag = Thread;//建立头结点
if (!P) {
head->lchild = head;//空树
}
else {
head->lchild = P;
pre = head;
InThreading(P);//中序遍历进行中序线索化
pre->rtag = Thread;
pre->rchild = head;
head->rchild = pre;
}
}
//在中序线索二叉树中求一个结点p的中序后继p$
BTREE InNext(BTREE p)
{
BTREE q;
if (p->rtag == Thread)
{
q = p->rchild;
}
else
{
q = p->rchild;
while (q->ltag == Link) q = q->lchild;//右子树的最左节点
}
return q;
}
//实现中序线索链表的中序遍历。
void InOrderTraverse_Thr(BTREE T) {
BTREE p = T->lchild;
while (p->ltag == Link)
{
p = p->lchild;
}
while (p != T)
{
printf("%c", p->data);
p = InNext(p);
}
}
//-------------------------------------------------------------------------------------------------------------------------------------
//实现二叉链表的后序线索化;
void PostThreading(BTREE P) {
if (P) {
if (Link == P->ltag)
PostThreading(P->lchild);
if (Link == P->rtag)
PostThreading(P->rchild);
if (!P->lchild) {
P->ltag = Thread;
P->lchild = pre;
}
else P->ltag = Link;
if (!pre->rchild) {
pre->rtag = Thread;
pre->rchild = P;
}
else P->rtag = Link;
pre = P;
}
}
//加入头结点,后序线索二叉树
void PostOrderThread_Head(BTREE &head, BTREE &P) {
head = (node*)malloc(sizeof(BTREE));
head->rchild = head;//右指针回指
head->ltag = Link;
head->rtag = Thread;//建立头结点
if (!P) {
head->lchild = head;//空树
}
else {
head->lchild = P;
pre = head;
PostThreading(P);//后序遍历进行后序线索化
head->rchild = pre;
}
}
//在后序线索二叉树中求一个结点p的父节点
BTREE parent(BTREE &T, BTREE &p)
{
BTREE temp;
temp = T;
if (temp->lchild == p)
return temp; //父节点是头结点
else
{
temp = temp->lchild;
while (temp->lchild != p && temp->rchild != p)
{
if (Link == temp->rtag)
temp = temp->rchild; //如果节点有右节点,那么往右
else
temp = temp->lchild; //如果节点没有右孩子,那么去左孩子,没有左孩子,去前驱,也是走往左
}
return temp;
}
}
//求后序线索二叉树中结点p 的后序顺序的后继结点p*
BTREE PostNext(BTREE &T,BTREE &p)
{
BTREE par;
par = parent(T, p); //parent是p的双亲:
if (T == par) return T; //1.若parent是T,即p是根节点,则无后继
else if (p == par->rchild || Thread == par->rtag) //2.若p是双亲的右孩子,或者是独生左孩子,则后继为双亲
return par;
else
{
while (par->rtag == Link) //3.若p是有兄弟的左孩子,则后继为双亲的右子树上按照后续遍历访问的第一个节点。
{
par = par->rchild;
while (par->ltag == Link)
{
par = par->lchild;
}
}
return par;
}
}
//实现后序线索链表的后序遍历。
void PostOrderTraverse_Thr(BTREE T) {
BTREE p = T->lchild;
while (1)
{
while (Link == p->ltag) p = p->lchild;
if (Link == p->rtag) p = p->rchild;
else break; //p指向第一个被访问的节点
}
while (p != T)
{
printf("%c", p->data);
p = PostNext(T,p);
}
}
int main()
{
BTREE a, s;
pre->rtag = Thread;
pre->rchild = NULL;
printf("先序建立二叉链表,请输入: ");
CreateBT(a);
int i;
printf("输入1先序线索化,输入2中序线索化,输入3后序线索化: ");
scanf_s("%d", &i);
getchar();
if (i == 1) {
printf("先序线索化ing\n");
PreOrderThread_Head(s, a);
printf("先序线索化后先序输出此树:");
ForOrderTraverse_Thr(s); printf("\n");
}
else if (i == 2)
{
printf("中序线索化ing\n");
InOrderThread_Head(s, a);
printf("中序线索化后先序输出此树:");
InOrderTraverse_Thr(s); printf("\n");
}
else {
printf("后序线索化ing\n");
PostOrderThread_Head(s, a);
printf("后序线索化后先序输出此树:");
PostOrderTraverse_Thr(s); printf("\n");
}
system("pause");
return 0;
}
输出: