博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
学习小结(二) —— 基础数据结构
阅读量:6852 次
发布时间:2019-06-26

本文共 2654 字,大约阅读时间需要 8 分钟。

1.学习内容

主要学习内容为树形数据结构。知识点有:

  • 最小生成树:Prim算法,Kruskal算法
  • 二叉堆,堆排序,优先队列
  • 哈夫曼树,哈夫曼编码
  • 树状数组,线段树
  • 并查集

    2.知识小结

    (1)最小生成树:
      求最小生成树的常规算法有两种:Prim和Kruskal,Prim以点为主,Krukal以边为主。Prim以点开展遍历,寻求权值最小的点,并将之加入到集合中(接在树上)。核心代码:
for(int i=1; i<=n; i++)        dis[i]=w[1][i]; //w[i][j]表示i,j直接距离    dis[1]=0; //从节点1开始遍历    for(int i=1; i

Kruskal先将边权排序,将边权最小并且所连接节点未在树上的边依次接在树上。核心代码:

//Kruskal算法需要用并查集维护,下文会有对并查集的介绍sort(edge+1, edge+m+1, CMP);  //将边权排序,CMP函数比较边权大小for(int i=1; i<=m; i++)        if(find(edge[i].x)!=find(edge[i].y)){  //并查集,find函数用来寻找父节点.            ans+=edge[i].w; //ans为最小生成树的边权和            f[find(edge[i].x)]=edge[i].y; //并查集,将该边两个节点合并        }

(2)二叉堆,堆排序,优先队列:

  我们平时所说的“堆”即为二叉堆,二叉堆是完全二叉树。二叉堆分为小根堆和大根堆,小根堆为父节点的值总是小于等于任意一个子节点的值,大根堆则恰好相反。关于二叉堆主要有三种操作:添加,删除,修改元素,具体实现就不多说了。二叉堆的主要作用为,以logN(N为数组元素个数)的复杂度求动态数组(数组中元素可以修改)中的最值。堆排序也是利用了堆的思想,用NlogN的复杂度将数组排序。STL中关于堆的函数包含在algorithm库中,有:make_heap()、pop_heap()、push_heap()、sort_heap()四个函数。
  优先队列是将队列中每个元素赋一个优先级,每次优先级最高元素出队的一种队列。不难看出,二叉堆是一种特殊的优先队列,大根堆是元素大的优先级高的优先队列,小根堆则相反。优先队列的实现比较复杂,但STL中有关于优先队列的函数,包含在queue库中,定义如下:
// 声明一个叫q的int型优先队列 priority_queue <int, vector<int>, greater<int> > q; //小根堆 priority_queue <int, vector<int>, less<int> > q; //大根堆 priority_queue <int > q; //大根堆,与上一种等价有 empty( ),pop( ) ,push( ) ,size( ) ,top( )四种操作,用法与普通队列类似。
  介绍一种黑科技!有一个叫pb_ds(平板电视)的库,当中有优先队列,平衡二叉树,红黑树,Splay,哈希表等内容。重要的是它们的复杂度出奇的低,优先队列远快于STL中的,甚至比手打的还要快!而且在OI的比赛中允许使用,需要以下定义:

#include 
__gnu_pbds::priority_queue

例如,小根堆的声明为:

__gnu_pbds::priority_queue <int, std::greater<int>, __gnu_pbds::pairing_heap_tag> minheap;
用法与STL中的类似,使用起来很方便。

(3)哈夫曼树,哈夫曼编码:

  哈夫曼树也叫最优二叉树,是一种带权路径(叶子节点权值乘该节点到根节点路径长度)之和最短的二叉树。构造哈夫曼树一种基于贪心的算法,通过哈夫曼树可以构造出哈夫曼编码,可以用于数据压缩和数据加密。

(4)树状数组,线段树:

  树状数组是主要用于查询数组中任意两位之间所有元素之和的数据结构,查询和修改的复杂度都是logN。树状数组可以拓展出区间修改,单点查询等功能。树状数组能解决的问题都可以使用线段树解决,但是树状数组的效率会高一些。树状数组的主要思想为二进制,它的操作尤为神奇。
  如前文所说,线段树可以代替树状数组,同时也可以解决一些树状数组无法解决的问题。线段树运用了二分的思想,将一个大区间通过二分,分为若干个小区间,通过维护这些小区间,利用小区间合并出查询的结果。一般有查询,修改删除的操作,它们的复杂度都为log2N。线段树是一种极其重要的数据结构,内容也有很多,需要好好掌握。

(5)并查集:

  并查集是一种维护集合合并和查询的数据结构。一般有合并,查询等操作,可以通过路径压缩来优化时间复杂度,实现的代码如下:

//初始化for(int i=1; i<=n; i++)    f[i]=i;  //f[x]表示x的父节点,意思即为每个节点均无父节点(父节点为自己)    //查找父亲节点(路径压缩)int find(int x){    if(f[x]!=x) f[x]=find(f[x]); //如果f[x]==x则没有父节点,跳过此句,如果f[x]!=x,则继续寻找父节点    return f[x];  //返回父节点值}//合并void Union(int x, int y){    int fx=find(x),fy=find(y); //寻找父节点    if(fx!=fy) f[fx]=fy; //若fx==fy则在同一集合,fx!=fy则合并    return;}//查询(询问x,y是否在同一集合)if(find(x)==find(y)) printf("YES\n");else printf("NO\n");

3.题目归纳

  • 最小生成树:BZOJ1050 旅行
  • 二叉堆:lg1801 黑匣子
  • 优先队列:BZOJ1216 操作系统
  • 哈夫曼树,哈夫曼编码: BZOJ4198 荷马史诗
  • 树状数组,线段树: lg3372 3372 【模板】线段树 1
  • 并查集:BZOJ4195 程序自动分析机

转载于:https://www.cnblogs.com/CrazyDave/p/8337513.html

你可能感兴趣的文章
Java程序员这样优化简历,一投制胜!
查看>>
runtime(消息转发)
查看>>
设计模式——建造者模式
查看>>
Async & generator & Promise
查看>>
解决vagrant ssh登录时permission deny的问题
查看>>
Dapper,大规模分布式系统的跟踪系统
查看>>
Spring源码之XMLBeanFactory
查看>>
PopupWindow 点击外部区域无法关闭的问题
查看>>
jQuery 遍历
查看>>
开源的丰富的flutter Icons库
查看>>
内存管理Release和Retain实现原理
查看>>
(JVM 笔记)Java虚拟机:Java 内存管理
查看>>
一分钟读懂兼容报告——行业对标数据助你定位产品状况
查看>>
Axure RP 7.0从入门到精通 Web+APP产品经理原型设计 彩色pdf扫描版
查看>>
点击H5页面的时候出现阴影
查看>>
js实现一个按照权重抽奖函数
查看>>
Java程序员必会的13种热门技能
查看>>
HTTP请求详解
查看>>
企业分布式微服务云SpringCloud SpringBoot mybatis (六)分布式配置中心(Spring Cloud Config)...
查看>>
java B2B2C springmvc mybatis多租户电子商城系统-(四)断路器(Hystrix)
查看>>