github编辑

6、堆(Stack)& 哈夫曼树 & 并查集

堆与哈夫曼树与并查集

一、堆

1.堆是什么

堆(Heap),是一个可以被看做一棵完全二叉树的数组对象,有以下性质:

  • 任意节点的值是其子树所有结点中的最大值/最小值(有序性)

  • 堆总是一棵用数组表示的完全二叉树。 在这里插入图片描述

2.最大堆的操作函数

定义

typedef struct HeapStruct *MaxHeap;
struct HeapStruct {
	ElementType *Elements;//存储堆元素的数组
	int Size;//当前元素个数
	int Capacity;//最大容量
};

(1)空最大堆的创建(Create函数)

MaxHeap Create(int MaxSize) {
	MaxHeap H = malloc(sizeof(struct HeapStruct) );
	H->Elements = malloc( (MaxSize+1) * sizeof(ElementType));//+1是由于我们从下标1开始存储
	H->Size = 0;
	H->Capacity = MaxSize;
	H->Elements[0] = MaxData;//下标0设为"哨兵" 为大于堆中所有可能元素的值,便于之后的操作
	return H;
}

(2)最大堆的插入(Insert函数)

插入一个元素时与其父结点比较,若插入元素更大则两者交换,再与其父节点比较,如此直到插入元素比父结点小为止。 在这里插入图片描述

(3)最大堆的删除(Delete函数)

取出根节点(最大值)元素,同时在堆中删除根结点,保证其新的根节点仍是堆中的最大值。

  • 用最大堆中最后一个元素,作为新的根节点,删除原来的最后一个元素

  • 看根结点左右儿子是否比其大,是则继续往下过滤

(3)从已有元素创建最大堆

将已经存在的N个元素按最大堆的要求存放在一个一维数组中。

  • 法1 通过插入操作,将N个元素一个个插入到一个空的最大堆中,时间复杂度最大为O(NlogN)。

  • 法2 在线性时间复杂度下建立最大堆。

  • (1)将N个元素按输入顺序存入,使其先满足完全二叉树的结构特性

  • (2)调整各结点位置,使其满足最大堆的有序特性

建堆时间复杂度O(n),为书中各结点的高度和 从倒数第一个有儿子的结点开始,其肯定有左儿子 将定义中的Elements数组改成Data数组存储已有元素

二、哈夫曼树

1.哈夫曼树是什么

带权路径长度(WPL):设二叉树有n个叶子结点,每个叶子结点带有权值wk,从根结点到每个叶子结点的长度为lk,则每个叶子结点的带权路径长度之和就是:WPL = $\sum_{k=1}^n$wk lk. 最优二叉树,也称为哈夫曼树(Huffman Tree):WPL最小的二叉树,其特点为:

  • 没有度为1的结点

  • n个叶子结点的哈夫曼树共有2n-1个结点

  • 哈夫曼树的任意非叶结点的左右子树交换后仍是哈夫曼树

  • 同一组权值,是可能存在不同构的两棵哈夫曼树的 在这里插入图片描述

2.哈夫曼树的操作

哈夫曼树的构造,每次将权值最小的两棵二叉树合并 主要问题:如何选取两个最小的?利用最小堆!

3.哈夫曼树的应用——哈夫曼编码

如何进行编码,可以使总编码空间最少? 出现频率高的字符用的编码短些,出现频率低的字符编码可以长一些,同时要避免二义性。 前缀码(prefix code): 任何字符的编码都不是另一字符的前缀,即可避免二义性 可以构造一个二叉树用于编码,左右分支分别为0、1,当所有的字符都在叶结点上的时候即可 在这里插入图片描述 就可以用哈夫曼树!

三、集合

关于集合这一块主要就是并查集,之前有学过这篇博客写的超棒:超有爱的并查集~(原博挂了,转载)arrow-up-right 所以在这儿就不多说啦~ 在这里插入图片描述 在这里插入图片描述

~ 并查集板子 ~

最后更新于

这有帮助吗?