//线索化规则为
//叶子结点指向NULL的两个指针利用起来
//结点的左指针,指向其当前遍历顺序的前驱结点
//结点的右指针,指向其当前遍历顺序的后继结点
//此外还需要左右加一个标志位,来表示左右指针是指孩子还是遍历线索
#include<stdio.h>
#include<stdlib.h>
typedef char E;//树结点的储存元素类型
typedef struct TreeNode{
E element;//存储数据
struct TreeNode* left;//左指针
struct TreeNode* right;//右指针
int leftflag;//左标志位
int rightflag;//右标志位
struct TreeNode* parent;//后序遍历线索化使用,存父结点
//当标志位为1代表指向孩子,不为1代表指向线索
}*Node;
//创建树结点
Node creatTreeNode(E element)
{
Node node =malloc(sizeof(struct TreeNode));
node->left=node->right=NULL;
node->leftflag=node->rightflag=0;
node->element=element;
return node;
}
//前序遍历线索化函数
//函数外面存一下上一个结点,等到遍历到空的时候可以用指针返回
Node pre = NULL;
void preOrderThreaded(Node root)
{
if(root==NULL)
{
return;
}
if(root->left==NULL)//当遍历到左指针为空时意味着到了叶子结点
{
root->left=pre;//指向上一个结点
root->leftflag=1;
}
if(pre&&pre->right==NULL)//上一个结点右结点如果为空指向下一个结点(保证上一个结点不为空防止刚开始报错)
{
pre->right=root;//指向下一个结点
pre->rightflag=1;
}
pre = root;
if(root->leftflag==0)//没有建立线索继续走
preOrderThreaded(root->left);
if(root->rightflag==0)//没有建立线索继续走
preOrderThreaded(root->right);
}
//快速遍历一个前序遍历线索化的二叉树
void preOrder(Node root)
{
while(root)
{
printf("%c",root->element);
if(root->leftflag==0)
{
root=root->left;
}
else
{
root=root->right;
}
}
}
//中序遍历线索化函数
//函数外存一个变量指向上一个结点
Node in = NULL;
void inOrderThreaded(Node root)
{
if(root==NULL)
{
return;
}
//如果左标志为0则说明左边为子结点,往下遍历直到为空代表到了叶子结点
if(root->leftflag==0)
{
inOrderThreaded(root->left);//到空时返回上一个结点(叶子结点)
}
if(root->left==NULL)
{
root->left=in;//上一个结点值给in
root->leftflag=1;//左边标记为1即被线索化
}
if(in&&in->right==NULL)
{
in->right=root;//如果in不为空且in的右边为空,则in为上一个结点,将in的右结点指向下一个结点
in->rightflag=1;//右标记线索化
}
in = root;//in变为下一个结点
if(root->rightflag==0)
inOrderThreaded(root->right);//向右遍历
}
//快速遍历一个中序遍历线索化的二叉树
void inOrder(Node root)
{
while(root)
{
//向左遍历直到左标记不等于0即线索化
while(root&&root->leftflag==0)
{
root=root->left;
}
printf("%c",root->element);//打印这个结点
//如果右为线索化向右继续遍历
while(root&&root->rightflag==1)
{
root=root->right;
printf("%c",root->element);
}
//如果右有子节点不是线索化则向右走
root=root->right;
}
}
//后序遍历线索化函数
//函数外存一个变量指向上一个结点
Node post = NULL;
void postOrderThreaded(Node root)
{
if(root==NULL)
{
return;
}
if(root->leftflag==0)
{
postOrderThreaded(root->left);
if(root->left)
{
root->left->parent = root;
}
}
if(root->rightflag==0)
{
postOrderThreaded(root->right);
if(root->right)
{
root->right->parent = root;
}
}
if(root->left==NULL)
{
root->left=post;
root->leftflag=1;
}
if(post&&post->right==NULL)
{
post->right=root;
post->rightflag=1;
}
post = root;
}
//快速遍历一个后序遍历线索化的二叉树
void postOrder(Node root)
{
Node last = NULL;//暂存指针,记录上一次遍历结点
Node node = root;//记录根结点
while(node)
{
//左遍历一直找到左结点为空且未被线索化的叶子结点
while(node->left!=last&&node->rightflag==0)
{
node = node->left;
}
//如果右边是线索直接打印走
while(node&&node->rightflag==1)
{
printf("%c",node->element);
last = node;
node = node->right;
}
//如果是根结点直接返回
if(node==root)
{
printf("%c",node->element);
return;
}
//如果当前结点的右孩子是上一个结点
while(node&&node->right==last)
{
printf("%c",node->element);//直接打印
last = node;
node = node->parent;//继续找父结点
}
if(node&&node->rightflag==0)
{
//右边不是线索往右走
node=node->right;
}
}
}
int main()
{
//创建一棵简单的二叉树
Node a = creatTreeNode('A');
Node b = creatTreeNode('B');
Node c = creatTreeNode('C');
Node d = creatTreeNode('D');
Node e = creatTreeNode('E');
a->left=b;
a->right=c;
b->left=d;
b->right=e;
postOrderThreaded(a);
postOrder(a);
return 0;
}
数据结构笔记(十八)线索化二叉树
于 2024-03-28 14:52:09 首次发布