数据结构-并查集和堆、哈夫曼树

一、并查集的定义

  1. 并查集是一种维护集合的数据结构,它的名字中“并”、“查”、“集”。分别取自Union(合并)、Find(查找)、Set(集合)。
  • 合并:就是合并两个集合
  • 查找:判断两个元素是否在一个集合
  • 那么并查集是用什么实现的,就是一个数组,
  • 对于同一个集合来说只存在一个根结点,且将其作为所属集合的标识。

二、并查集的基本操作

  1. 初始化,每个元素都是一个独立的集合,因此需要令所有的father[i] = i;
for(int i = 1; i <= N; i++){
    father[i] = i;
}
  1. 查找,就是查找反复寻找父亲结点。
int findFather(int x){
    while(x != father){
        x = father[x];
    }
    return x;
}

int findFather(int x){
    if(x == father[x]) return x;
    else return findFather(father[x]);
}
  1. 合并,就是把两个集合合并成一个集合。
void Union(int a, int b){
    int faA = findFather(a);
    int faB = findFather(b);
    if(faA != faB){
        father[faA] = faB;
    }
}

三、路径压缩

  • 把当前查询结点的路径上的所有结点的父亲都指向根结点。
int findFather(int x){
    //由于x在下面的while中会变成根结点,因此先把原先的x保存一下
    int a = x;
    while(x != father[x]){
        x = father[x];
    }
    //到这里,x存放的是根结点,下面把路径上所有的结点的father都改成根结点
    while(a != father[a]){
        int z = a;
        a = father[a];//a回溯父亲结点
        father[z] = a;//把原来的结点a的父亲改为根结点
    }
    return x;//返回根结点
}

四、堆的定义

  1. 堆是一棵完全二叉树,树中每个结点的值都不小于(或不大于)其左右孩子结点的值。
  2. 如果父亲结点的值大于或等于孩子结点的值,那么称这样的堆为大顶堆,反之为小顶堆。
  3. 堆一般用于优先队列的实现,而优先队列默认情况下使用大顶堆。

五、堆的基本操作

1. 建堆向下调整
//对于heap数组在[low, high]的范围进行向下调整
//其中low为欲调整结点的数组下标,high一般为堆的最后一个元素的数组下标
void downAdjust(int low, int high){
    int i = low, j = i * 2;
    while(j <= high){
        if(j+1 <= high && heap[j+1] > heap[j]){
            j = j + 1;
        }
        if((heap[j] > heap[i]){
            swap(heap[j], heap[i]);
            i = j;
            j = i * 2;
        }else{
            break;
        }
    }
}
2. 建堆
  • 假设序列中元素的个数为n,根据完全二叉树的特性,知道叶子结点个数为n/2个,因此数组下标在[1, n/2]的范围内是非叶子结点。于是可以从n/2号位开始倒着枚举结点,对每个遍历到结点i进行[i, n]范围的调整。
void createHeap(){
    for(int i = n / 2; i >= 1; i--){
        downAdjust(i, n);
    }
}
3. 删除堆中最大元素
  • 只需要最后一个元素覆盖堆顶元素,然后对根结点进行调整。
void deleteTop(){
    heap[1] = heap[n--];
    downAdjust(1, n);
}
4. 添加元素
  • 也就是把添加的元素放在数组的最后一个位置,然后进行上调操作。
//对于heap数组在[low, high]的范围进行向上调整
//其中low为欲调整结点的数组下标设置为1,high一般为堆的最后一个元素的数组下标
void upAdjust(int low, int high){
    int i = high, j = i / 2;//i为欲调整结点,j为其父亲
    while(j >= low){
        if(heap[j] < heap[i]){
            swap(heap[j], heap[i]);
            i = j;
            j = i / 2;
        }else{
            break;
        }
    }
}

//添加元素
void insert(int x){
    heap[++n] = x;//让元素个数加1,然后将数组末尾赋值为x
    upAdjust(1, n);//向上调整新加入的结点n
}
5. 堆排序
  • 是使用堆结构对一个序列进行排序。
void heapSort(){
    createHeap();
    for(int i = n; i > 1; i--){
        swap(heap[i], heap[1]);
        downAdjust(1, i - 1);
    }
}

六、哈夫曼树的相关定义

  1. 其中叶子结点的路径长度是指从根结点出发到达结点的边数。
  2. 把叶子结点的权值乘以其路径长度的结果称为这个叶子结点的带权路径长度。
  3. 树的带权路径长度(WPL)等于它所有叶子结点带权路径的长度之和。
  4. 带权路径长度最小的就是称为哈夫曼树(最优二叉树),显然对于同一组叶子结点来说,哈夫曼树可以是不唯一的,但是带权路径长度一定是唯一的。

七、哈夫曼编码

  1. 对于任何一个叶子结点,其编码一定不会成为其任何一个结点编码前缀。
  2. 其中任何一个字节编码都不是另一个字符编码的前缀,同时满足这种方式的编码方式称为前缀编码,意义不产生混淆。
  3. 哈夫曼编码,就是使得字符串编码成01串后长度最短的前缀编码。
  4. 哈法曼编码是针对于特定的字符串来讲的。

原文地址:https://www.cnblogs.com/tsruixi/p/12347871.html

时间: 2024-11-02 21:50:56

数据结构-并查集和堆、哈夫曼树的相关文章

数据结构学习笔记04树(堆 哈夫曼树 并查集)

一.堆(heap) 优先队列(Priority Queue):特殊的“队列”,取出元素的顺序是依照元素的优先权(关键字)大小,而不是元素进入队列的先后顺序. 数组 : 插入 — 元素总是插入尾部 ~ O ( 1 ) 删除 — 查找最大(或最小)关键字 ~ O ( n ) 从数组中删去需要移动元素 ~ O( n ) 链表: 插入 — 元素总是插入链表的头部 ~ O ( 1 ) 删除 — 查找最大(或最小)关键字 ~ O ( n ) 删去结点 ~ O( 1 ) 有序数组: 插入 — 找到合适的位置

数据结构之---C语言实现哈夫曼树和编码

//哈夫曼树 //杨鑫 #include <stdio.h> #include <stdlib.h> typedef int ElemType; struct BTreeNode { ElemType data; struct BTreeNode* left; struct BTreeNode* right; }; //遍历哈夫曼树 void PrintBTree_int(struct BTreeNode* BT) { if (BT != NULL) { printf("

看数据结构写代码(32) 赫夫曼树编码以及译码

杂谈:最近有点慵懒,不好不好.好几天都没写代码,原本准备上星期完结 树 这一章节的.现在 又耽误了.哎.要抓紧时间啊. 下面直接上代码: 可以到我的网盘下载源代码,或者 直接拷贝下面的源代码 运行 网盘地址:点击打开链接 // HuffmanTree.cpp : 定义控制台应用程序的入口点. //哈弗曼编码,译码 #include "stdafx.h" #include <stdlib.h> #include <cstring> enum E_State { E

数据结构——哈夫曼树

转自:http://www.cnblogs.com/skywang12345/p/3706833.html 哈夫曼树的介绍 Huffman Tree,中文名是哈夫曼树或霍夫曼树,它是最优二叉树. 定义:给定n个权值作为n个叶子结点,构造一棵二叉树,若树的带权路径长度达到最小,则这棵树被称为哈夫曼树. 这个定义里面涉及到了几个陌生的概念,下面就是一颗哈夫曼树,我们来看图解答. (01) 路径和路径长度 定义:在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径.通路中分支的数目称

哈夫曼树(三)之 Java详解

前面分别通过C和C++实现了哈夫曼树,本章给出哈夫曼树的java版本. 目录 1. 哈夫曼树的介绍 2. 哈夫曼树的图文解析 3. 哈夫曼树的基本操作 4. 哈夫曼树的完整源码 转载请注明出处:http://www.cnblogs.com/skywang12345/ 更多内容:数据结构与算法系列 目录 哈夫曼树的介绍 Huffman Tree,中文名是哈夫曼树或霍夫曼树,它是最优二叉树. 定义:给定n个权值作为n个叶子结点,构造一棵二叉树,若树的带权路径长度达到最小,则这棵树被称为哈夫曼树. 这

哈夫曼树(一)之 C语言详解

本章介绍哈夫曼树.和以往一样,本文会先对哈夫曼树的理论知识进行简单介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现:实现的语言虽不同,但是原理如出一辙,选择其中之一进行了解即可.若文章有错误或不足的地方,请帮忙指出! 目录 1. 哈夫曼树的介绍 2. 哈夫曼树的图文解析 3. 哈夫曼树的基本操作 4. 哈夫曼树的完整源码 转载请注明出处:http://www.cnblogs.com/skywang12345/ 更多内容:数据结构与算法系列 目录 哈夫曼树的介绍 Huffman

哈夫曼树的证明

简述:在学习慕课<数据结构>时,关于哈夫曼树仅给出了算法描述,并没有给出哈夫曼树就是最优树的证明,查阅教材也没发现相关信息,通过上网浏览博客解决了该问题. 参考博客:1)https://blog.csdn.net/xiyanxiyan10/article/details/17580599    2)https://blog.csdn.net/BigLeo/article/details/41243779    3)http://blog.sina.com.cn/s/blog_cf5c8eae0

哈夫曼树——c++

哈夫曼树的介绍 Huffman Tree,中文名是哈夫曼树或霍夫曼树,它是最优二叉树. 定义:给定n个权值作为n个叶子结点,构造一棵二叉树,若树的带权路径长度达到最小,则这棵树被称为哈夫曼树. 这个定义里面涉及到了几个陌生的概念,下面就是一颗哈夫曼树,我们来看图解答. (01) 路径和路径长度 定义:在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径.通路中分支的数目称为路径长度.若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1. 例子:100和80的路径长度

哈夫曼树+哈夫曼编码

前天acm实验课,老师教了几种排序,抓的一套题上有一个哈夫曼树的题,正好之前离散数学也讲过哈夫曼树,这里我就结合课本,写一篇关于哈夫曼树的博客. 哈夫曼树的介绍 Huffman Tree,中文名是哈夫曼树或霍夫曼树,它是最优二叉树. 定义:给定n个权值作为n个叶子结点,构造一棵二叉树,若树的带权路径长度达到最小,则这棵树被称为哈夫曼树. 这个定义里面涉及到了几个陌生的概念,下面就是一颗哈夫曼树,我们来看图解答. (01) 路径和路径长度 定义:在一棵树中,从一个结点往下可以达到的孩子或孙子结点之