数据结构之树(篇5)

文章目录:

  • 线索树
  • 树,森林,二叉树的转换
  • 树的应用之并查集
  • 哈夫曼树

1.线索树

之前二叉树的非递归遍历算法避免了系统栈的调用,提高了一定的执行效率,而线索二叉树可以将用户栈也省掉,把二叉树的遍历过程线性化,进一步提高效率,二叉树被线索化之后近似一个线性结构,分支操作的遍历操作就转化为了近似于线性结构的遍历操作,通过线索的辅助使得寻找当前结点前驱或者后继的平均效率大大提高。

引言

1.三种遍历方式下的线索化

在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述
2.线索二叉树的结点结构及核心代码

在这里插入图片描述在这里插入图片描述

在这里插入图片描述

在这里插入图片描述在这里插入图片描述在这里插入图片描述

在这里插入图片描述

3.具体代码

//完整代码
#include<stdio.h>
#include<stdlib.h>
 
/*中序线索二叉树*/
typedef struct bitree{
	struct bitree *lchild , *rchild;
	char ch;
	int LTag, RTag; 
}BiTreeNode,*LkBiTree;
 
/*全局变量pre,始终指向刚刚访问过的结点*/
LkBiTree pre;
 
/*一般使用先序创建*/
void PreCreBiTree(LkBiTree *T)
{
	char temp;
	scanf("%c",&temp);
	/*叶子结点判定*/
	if(temp=='#')
	{
		*T = NULL;
	}
	else
	{
		/*生成新节点,先赋值,再生成左右节点*/
		*T = (LkBiTree)malloc(sizeof(BiTreeNode));
		(*T)->ch = temp;
		/*表达式的书写要注意*/
		PreCreBiTree(&(*T)->lchild);
		PreCreBiTree(&(*T)->rchild);
	}
}
 
/*中序遍历线索化*/
void InThreading(LkBiTree T)
{
	if(T!=NULL)
	{
		InThreading(T->lchild);//首先进行左递归 
		//结点处理 
		if(!T->lchild)//如果没有左孩子 //建立当前结点的前驱线索 
		{
			T->LTag = 1;//置1创建前驱 
			T->lchild = pre;//把lchild指向刚刚访问的结点 
		}
		else
		{
			T->LTag = 0;//否则是正常的二叉树,有左孩子 
		}
		if(!pre->rchild)//建立前驱结点的后继线索 
		{
			pre->RTag = 1;
			pre->rchild = T;
		}
		else
		{
			pre->RTag = 0;
		}
		pre = T;//刚刚访问的结点赋值到T,然后进行右递归 
		//pre指向当前的 T,作为T将要指向的下一个结点的前驱结点指示指针 
		InThreading(T->rchild);
	}
}
 
/*带头结点的中序线索化*/
void InorderThreading(LkBiTree *headptr, LkBiTree T)
{
	*headptr = (LkBiTree)malloc(sizeof(BiTreeNode));
	pre = *headptr;
	pre->LTag = 0;
	pre->RTag = 1;
	pre->rchild = pre;
	if(!T)
	{
		pre->lchild = pre;
	}
	else
	{
		pre->lchild = T;
		InThreading(T);
		pre->rchild = *headptr;
		pre->RTag = 1;
		(*headptr)->rchild = pre;
	}
 } 
 
/*中序遍历线索二叉树,非递归算法*/
void InThTraverse(LkBiTree head)
{
	LkBiTree p = head->lchild;
	while(p!=head)
	{
		while(p->LTag==0)
		{
			p = p->lchild;
		}
		//visit();   
		printf("%c",p->ch);
		while(p->RTag==1&&p->rchild!=head)
		{
			p = p->rchild;
			printf("%c",p->ch);
		}
		p = p->rchild;
	}
}
 
 
/*中序线索化遍历释放*/
void DestroyBiTree(LkBiTree head)
{
	LkBiTree p = head->lchild;
	LkBiTree temp = head;
	while(p!=head)
	{
		while(p->LTag==0)
		{
			p = p->lchild;
		}
		free(temp);
		temp = p;
		while(p->RTag==1&&p->rchild!=head)
		{
			p = p->rchild;
			free(temp);
			temp = p;
		}
		p = p->rchild;
	}
	free(temp);
}
 
int main()
{
	LkBiTree T,head;
	PreCreBiTree(&T);
	printf("首节点为%c\n",T->ch);
	InorderThreading(&head, T);
	InThTraverse(head);
	DestroyBiTree(head);
	return 0;
}

2.树,森林,二叉树的转换

1.树转换为二叉树

在这里插入图片描述在这里插入图片描述2.森林转化为二叉树

在这里插入图片描述

在这里插入图片描述
3.树和森林的遍历

①树的两种遍历方式

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

②森林的两种遍历方式

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

③遍历的对应关系

在这里插入图片描述

3.树的应用之并查集

1.概念
在这里插入图片描述
2.双亲表示法的存储结构

在这里插入图片描述
在这里插入图片描述
3.并查集的初始化,查找子集根结点,合并的操作

在这里插入图片描述

4.哈夫曼树(赫夫曼树)

1.带权路径长度及哈夫曼树的概念

在这里插入图片描述
在这里插入图片描述
2.哈夫曼树的构造方法

在这里插入图片描述

3.哈夫曼树的性质

在这里插入图片描述

4.哈夫曼编码(赫夫曼编码)

在这里插入图片描述
注意:哈夫曼编码以字符为根结点,以对应的字符的出现次数作为权值,构造一棵哈夫曼树,所构造的哈夫曼树的每个结点的左右分支进行编号,左0右1,则从根结点到每个结点的路径上的数字序列即为每个字符的编码。

在这里插入图片描述

在这里插入图片描述
到这里树的章节的基本内容整理完成,后续如果有补充内容再相继补充,之后会更新串的相关知识,重点的kmp算法。
2020.8.23.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值