文章目录:
- 线索树
- 树,森林,二叉树的转换
- 树的应用之并查集
- 哈夫曼树
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.