二叉搜索树的线索化及遍历

本篇创建的是二叉搜索树,代码包含二叉搜索树的建树以及树的线索化和线索化后的遍历。

完整代码如下:

#include<stdio.h>
#include<stdlib.h>

typedef struct LinkedTree
{
	int data, ltag, rtag; // 数据域,左线索,右线索
	struct LinkedTree* rchild;
	struct LinkedTree* lchild;
}TNode;


TNode* CreatNode(int data)//创建一个节点并初始化
{
	TNode* p = NULL;
	p = (TNode*)malloc(sizeof(TNode));
	if (p)
	{
		p->data = data;
		p->ltag = 0;
		p->rtag = 0;
		p->lchild = NULL;
		p->rchild = NULL;
	}
	else
	{
		printf("Malloc Error!\n");
		return NULL;
	}
	return p;
}

void AddNode(int data, TNode* p)//递归插入数据
{
	if (data == p->data)
	{
		return;
	}
	if (data < p->data)
	{
		if (p->lchild)
		{
			AddNode(data, p->lchild);
		}
		else
		{
			p->lchild = CreatNode(data);
		}
	}
	else
	{
		if (p->rchild)
		{
			AddNode(data, p->rchild);
		}
		else
		{
			p->rchild = CreatNode(data);
		}
	}
}

TNode* CreateTree(void)//建树
{
	int data = 0;
	TNode* root = NULL;
	printf("请输入数据(输入-1结束):");
	while (1)
	{
		scanf_s("%d", &data);
		if (-1 == data)
		{
			break;
		}
		if (root)
		{
			AddNode(data, root);
		}
		else
		{
			root = CreatNode(data);
		}
	}
	return root;
}

void InOrder(TNode* p)//中序遍历
{
	if (p)
	{
		InOrder(p->lchild);
		printf("%d ", p->data);
		InOrder(p->rchild);
	}
}

void InThreadTree(TNode* p, TNode** pre)//中序线索化二叉树,在中序遍历的过程中线索化二叉树	
{                                    //*pre记录前驱,使用二级指针,也可以声明一个为全局变量pre指针
	if (p)
	{
		InThreadTree(p->lchild, pre);
		if (!p->lchild)
		{
			p->ltag = 1;
		}
		if (!p->rchild)
		{
			p->rtag = 1;
		}
		if ((*pre) != NULL)
		{
			if (1 == (*pre)->rtag)//前驱(*pre)的右线索为1,前驱的右孩子为空
			{
				(*pre)->rchild = p;//设置(*pre)的后继
			}
			if (1 == p->ltag)//当前节点左孩子为为空
			{
				p->lchild = (*pre);//设置当前节点的前驱
			}
		}
		(*pre) = p;//保存当前节点为前驱
		InThreadTree(p->rchild, pre);
	}
}

void InOrderThred(TNode* p)//遍历线索化后的二叉树树
{
	while (p->ltag != 1)//遍历找到左下节点
	{
		p = p->lchild;
	}
	while (p)
	{
		printf("%d ", p->data);
		if (1 == p->rtag)//右子树为空
		{
			p = p->rchild;
		}
		else //右子树不为空的情况
		{
			p = p->rchild;
			while (p->ltag != 1)//遍历找到该子树的左下节点
			{
				p = p->lchild;
			}
		}
	}
}

void FreeTree(TNode* p)//释放二叉树,根据InThred(List* p)函数改动,在遍历的时候free节点
{
	TNode* q = NULL; //使用q指针记录p的下一节点
	while (p->ltag != 1)
	{
		p = p->lchild;
	}
	while (p)
	{
		if (1 == p->rtag) //右子树为空
		{
			q = p->rchild; //记录下一节点
			free(p);
			p = q;
		}
		else
		{
			q= p->rchild; //记录下一节点
			free(p);
			p = q;
			while (p->ltag != 1)
			{
				p = p->lchild;
			}
			q = p;
		}
	}
}


int main(void)
{
	TNode* pre = NULL;
	TNode* root = CreateTree();
	printf("中序遍历:");
	InOrder(root);
	putchar('\n');
	InThreadTree(root, &pre);
	printf("线索化后的遍历:");
	InOrderThred(root);
	putchar('\n');
	FreeTree(root);
	return 0;
}

运行环境vs2019,有问题的地方还请指出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值