相关概念:
哈夫曼树的定义:在含有n个带权叶结点的二叉树中,其中带权路径长度(WPL) 最小的二叉树,也称最优二叉树。
给定n个权值分别为w1, W2,..., w,的结点,构造哈夫曼树的算法描述如下:
相关概念:
由哈夫曼树得到哈夫曼编码--字符集中的每个字符作为一个叶子结点,各个字符出现的频度作为结点的权值,根据之前介绍的方法构造哈夫曼树 。
哈夫曼树不唯 一,因此哈夫 曼编码不唯一
同一子集中的 各个元素,组 织成一棵树,用互不相交的树,表示多个“集合”、
存储方法为双亲表示法。用一个数组 S[ ] 即可表示“集合”关系
集合的两个基本操作——“并”和“查”
注:并查集(Disjoint Set)是逻辑结构——集合的一种具体实现,只进行”并”和“查”两种基本操作
- #define SIZE 13
-
- int UFSets[SIZE]; //集合元素数组
-
- //初始化并查集
- void Initial(int S[])
- {
- for(int i=0; i
- S[i] = -1;
- }
-
- //Find————查操作,找到x所属集合 最坏时间复杂度:O(h)
- int Find(int S[], int x)
- {
- while(S[x]>=0)
- {
- x = S[x]; //循环找x的根
- }
- return x; // 根的S[]小于0
- }
-
- //Union————并操作,将两个集合合并 时间复杂度:O(1) 全部合并:O(n^2)
- void Union(int S[], int Root1, int Root2)
- {
- // 要求Root1和Root2是不同集合
- if(Root1 == Root2) return;
- // 将root2连接到另一个根Root1下面
- S[Root2] = Root1;
- }
2.3 时间复杂度分析
若结点数为n,Find 最坏时间复杂度为 O(n),Union时间复杂度 :O(1)
将n个独立元素通过多次Union合并为一个集合——O(n2)
2.4 优化思路:
2.4.1 Union优化思路
在每次Union操作构建树的时候,尽可能让树不长高高:
①用根节点的负值表示一棵树的结点总数
②Union操作,让小树合并到大树
合并前:
合并后:
Union操作优化后,Find 操作最坏时间复杂度 :O(log2n) ,
- #define SIZE 13
-
- int UFSets[SIZE]; //集合元素数组
-
- //初始化并查集
- void Initial(int S[])
- {
- for(int i=0; i
- S[i] = -1;
- }
-
- //Find————查操作,找到x所属集合 最坏时间复杂度:O(h)
- int Find(int S[], int x)
- {
- while(S[x]>=0)
- {
- x = S[x]; //循环找x的根
- }
- return x; // 根的S[]小于0
- }
-
- //Union————并操作,将两个集合合并
- void Union(int S[], int Root1, int Root2)
- {
- // 要求Root1和Root2是不同集合
- if(Root1 == Root2) return;
- if (S[Root2]>S[Root1]) { // Root2结点数更少
- S[Root1] += S[Root2]; // 累加结点总数
- S[Root2] = Root1; // 小树合并到大树
- } else {
- S[Root2] += S[Root1]; // 累加结点总数
- S[Root1] = Root2; // 小树合并到大树
- }
- }
2.4.2 Find优化思路:压缩路径,
先找到根节点,再将查找路径上所有节点都挂到根节点下。
每次 Find 操作,先找根,再 “压缩路径”,可使树的高度不超过O(α(n))。 α(n)是一个增长很缓慢
的函数,对于常见的n值,通常α(n)≤4,因此优化后并查集的Find、Union操作时间开销都很低
- #define SIZE 13
-
- int UFSets[SIZE]; //集合元素数组
-
- //初始化并查集
- void Initial(int S[])
- {
- for(int i=0; i
- S[i] = -1;
- }
-
- //Find————查操作,找到x所属集合 最坏时间复杂度:O(h)
- int Find(int S[], int x)
- {
- int root = x;
- while(S[root]>=0) root = S[root]; //循环找x的根
- while(x !=root)
- {
- int t = S[x]; // t指向x的父结点
- S[x] = root; // x直接挂靠到根节点下面
- x=t; // 循环处理x的祖先结点
- }
- return x; // 返回根节点编号
- }
-
- //Union————并操作,将两个集合合并
- void Union(int S[], int Root1, int Root2)
- {
- // 要求Root1和Root2是不同集合
- if(Root1 == Root2) return;
- if (S[Root2]>S[Root1]) { // Root2结点数更少
- S[Root1] += S[Root2]; // 累加结点总数
- S[Root2] = Root1; // 小树合并到大树
- } else {
- S[Root2] += S[Root1]; // 累加结点总数
- S[Root1] = Root2; // 小树合并到大树
- }
- }
2.4.3 并查集的优化前后对比
-
相关阅读:
GraphQL(1):GraphQL简介
java-net-php-python-ssm儿童演出礼服租赁网站计算机毕业设计程序
uniapp——第2篇:编写vue语法
正则验证用户名和跨域postmessage
php服装商城网站毕业设计源码241505
【Git-请求】
【Unity3D】动态路径特效
微信小程序 prettier 格式化
实现一个极简的字节数组对象池
LVGL_基础控件滚轮roller
-
原文地址:https://blog.csdn.net/zhendong825/article/details/134478225