线索化二叉树
在原来二叉树的基础上进行遍历,如果发现节点的孩子是空的,就将其改成线索,连接到前驱(左子树)或者后继(右子树),
Description
先序输入二叉树,建立二叉树,并用先序、中序、后序分别输出。
Input
先序输入二叉树,若无某子结点,输入’#’,若是子叶,输入’#’两次。
Output
后序、先序、中序、分别输出,并输出叶子节点数。
Sample Input
-+a##*b##-c##d##/e##f##
Sample Output
后序遍历线索二叉树:abcd-*+ef/-
前序遍历线索二叉树:-+a*b-cd/ef
中序遍历线索二叉树:a+b*c-d-e/f
叶子节点个数:6
#include <iostream>
#include <cstdio>
using namespace std;
#define Link 0
#define Thread 1
//Link == 0 是指针, Thread == 1 是线索
int cnt = 0;//计算根节点数
typedef struct Node{
char data;
struct Node *leftchild, *rightchild;
int LTag, RTag;//如果为1,则是线索,为0是指向孩子
Node(char x) {
data = x;
leftchild = rightchild = NULL;
LTag = RTag = Link;
}
}Node;
//按照先序构建二叉树,#代表空数
void creatBiTree(Node *&T)
{
char ch;
cin >> ch;
if (ch == '#')
T = NULL;
else
{
T = new Node(ch);//构造函数,相当于T->data=ch;
creatBiTree(T->leftchild);
creatBiTree(T->rightchild);
}
}
//对二叉树进行线索化
void InThreading(Node *& T, Node *& pre)
{
if (T)
{
InThreading(T->leftchild, pre);//左子树线索化
if (!T->leftchild)//左孩子空,则建立前驱线索
{
T->LTag = Thread;
T->leftchild = pre;
}
if (!pre->rightchild)//右孩子空,则建立后继线索
{
pre->RTag = Thread;
pre->rightchild = T;
}
pre = T;
InThreading(T->rightchild, pre);//右子树线索化
}
}
void InTraverse_Thread(Node *&T,Node *&Thrt)
{
Node *pre;
Thrt = new Node(NULL);
Thrt->LTag = Link;//头结点
Thrt->RTag = Thread;
Thrt->rightchild = Thrt;//右指针指向自己
if (!T) Thrt->leftchild = Thrt;//如果二叉树是空的,左指针就直接指自己了
else
{
Thrt->leftchild = T;
pre = Thrt;
InThreading(T, pre);//中序遍历进行中序线索化
pre->rightchild = Thrt;
pre->RTag = Thread;
Thrt->rightchild = pre;
}
}
void PreTraverse_Thr(Node *&T,Node *&Thrt)
{
Node *p;
if (Thrt->LTag == Link)//或者也可以用if (T)
{
p = Thrt->leftchild;//一开始写错写成rightchild,错了很多次
while (1)
{
while (p)//p走到这棵树最左边的子节点
{
cout << p->data;
if (p->LTag == 0)
p = p->leftchild;
else break;
}
while (p->RTag==1 && p->rightchild != T)//p走到最右边的节点
p = p->rightchild;
if (p->rightchild == T)//这个是判断是否为右子树的最后一个节点
break;
p = p->rightchild;
}
}
}
void InTraverse_Thr(Node *&T, Node *&Thrt)
{
Node *p;
if (Thrt->LTag == 0)//或者也可以用if (T)
{
p = Thrt->leftchild;
while (p!=Thrt)
{
while (p->LTag == Link) p = p->leftchild;
cout << p->data;
while (p->RTag == Thread && p->rightchild != Thrt)
{
p = p->rightchild;
cout << p->data;
}
p = p->rightchild;
}
}
cout << endl;
}
void InTraverse(Node *&T)//先输出中序,刚好可以顺便验证建树是否正确
{
if (T)
{
InTraverse(T->leftchild);
cout << T->data;
InTraverse(T->rightchild);
}
}
void PostTraverse(Node *&T)//先输出后序,刚好可以顺便验证建树是否正确
{
if (T)
{
PostTraverse(T->leftchild);
PostTraverse(T->rightchild);
cout << T->data;
if (T->leftchild == NULL&&T->rightchild == NULL)
cnt++;
}
}
int main()
{
Node *T;
creatBiTree(T);
//T是根节点,Thrt是头节点
Node *Thrt;
cout << endl << "中序遍历二叉树检验建树结果 :";
InTraverse(T);
cout << endl << "后序遍历二叉树检验建树结果 :";
PostTraverse(T);
cout << endl << "接下来线索化二叉树";
InTraverse_Thread(T,Thrt);
cout << endl << "先序遍历线索化二叉树 :";
PreTraverse_Thr(T, Thrt);
cout << endl << "中序遍历线索化二叉树 :";
InTraverse_Thr(T, Thrt);
cout << endl << "叶子节点总数为 " << cnt << endl;
}