#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
/*
本程序实现二叉树的建立和前序线索化,并输出前序遍历的结果。
测试输入:ABD##EF###C#G##
A
/ \
B C
/\ /\
D E # G
/\ /\ /\
# # F # # #
/\
# #
*/
//二叉树节点
typedef struct BinaryTreeNode{
char value; //节点的存储内容,一个字符
int ltag; //二叉树节点的坐标记,1表示指针指向孩子,0表示指针指向前驱
struct BinaryTreeNode * lchild; //二叉树节点的左孩子
int rtag; //二叉树节点的右标记,1表示指针指向孩子,0表示指针指向后继
struct BinaryTreeNode * rchild; //二叉树节点的右孩子
}BTnode,*BTnodePointer;
//由前序序列创建普通二叉树,是最基础的二叉树
BTnodePointer createBinaryTree(void) {
BTnodePointer T; //用于返回创建的子树的指针
char temp;
cin >> temp; //获取用户输入
if (temp == '#') T = NULL; //用户输入#表示没有孩子,指针为NULL,子树就是NULL。(这里的T指代所有将要被赋值的位置的指针变量)
else { //用户输入了其他内容,那么输入什么什么就是节点的值
T = (BTnodePointer)malloc(sizeof(BTnode));
T->value = temp;
T->ltag = T->rtag = 1; //每个节点初始都认为是既有左孩子又有右孩子的,哪怕孩子是空,以后线索化的时候再改tag
T->lchild = createBinaryTree(); //根据前序序列创建二叉树的顺序是,先本节点赋值,再递归创建左子树,再递归创建右子树
T->rchild = createBinaryTree();
}
return T; //如果用户什么也没输入或者是已经将“以本节点为根节点的子树”赋值完成,那么就return T,结束本层的递归,回到上一层的递归中去
}
//将给定的二叉树前序线索化
BTnodePointer pre = NULL; //pre表示前驱节点,初始化为NULL
void preThreading(BTnodePointer T) {
if (T == NULL) return; //当前节点是空什么也不做
if (T->lchild == NULL){ //当前节点左孩子为空,那么左孩子应指向前驱pre
T->lchild = pre;
T->ltag = 0;
}
if (pre != NULL && pre->rchild == NULL) { //pre结点右孩子为空,那么右孩子应指向后继节点,也就是当前节点T
pre->rchild = T;
pre->rtag = 0;
}
pre = T; //更新pre为当前节点
if (T->ltag == 1) preThreading(T->lchild); //有左孩子递归线索化左子树
if (T->rtag == 1) preThreading(T->rchild); //有右孩子递归线索化右子树
return;
}
//根据前序线索二叉树输出前序序列
void preThreadingPrint(BTnodePointer T) {
while (T != NULL) { //只要当前节点不为空
cout << T->value << " "; //输出当前节点的内容
if (T->ltag == 1) T = T->lchild; //如果有左孩子,那么左孩子必为后继节点
else T = T->rchild; /*如果没有左孩子,那么左孩子指向了当前节点的前驱。
如果右孩子存在,那么右孩子就是后继,
如果右孩子不存在,那么右孩子肯定指向后继节点,
除非是最后一个节点右孩子会指向NULL,
那么此时恰好跳出while循环,输出结束*/
}
cout << endl;
return;
}
//主运行函数
void binaryTree(void) {
//T就是创建的二叉树的根节点的指针,定义的时候还没有这个树,先赋值为NULL
BTnodePointer T, pre = NULL;
cout << "输入二叉树的前序序列,输入#表示空指针,程序会根据输入自动创建一棵二叉树(建议输入内容不要超过20个字符)。" << endl;
T = createBinaryTree();
cout << "二叉树创建完成!接下来进行前序线索化。" << endl;
preThreading(T);
cout << "线索化完成!按照前序线索二叉树的性质输出前序序列:" << endl;
preThreadingPrint(T);
return;
}
int main() {
binaryTree();
system("pause");
return 0;
}