高级算法和数据结构(2)

高级数据结构:哈希表、树与二叉树、优先队列与堆、并查集、线段树、树状数组、伸展树、Treap、AVL树、红—黑树、SBT、块状链表与块状树、后缀树与后缀数组、树链剖分与动态树等。二叉堆 左偏树 Trie RMQ线段树 ST表  动态树 .。。 

(ACM竞赛题)
> 1.哈希表
 java中哈希表及其应用详解- https://blog.csdn.net/xiaoxik/article/details/74926090
 哈希表的java实现- https://blog.csdn.net/xiaokang123456kao/article/details/54583062
 Java8系列之重新认识HashMap- http://www.importnew.com/20386.html
哈希算法,是一类算法;哈希表(Hash Table)是一种数据结构;哈希函数,是支撑哈希表的一类函数;
Map是映射、地图的意思,在Java中Map表示一种把K映射到V的数据类型;HashMap是Java中用哈希数据结构实现的Map;

Hash/摘要/散列/切碎算法 有哪些用处呢?
  1).信息安全领域:
  Hash算法 可用作加密算法。 
如文件校验:通过对文件摘要,可以得到文件的“数字指纹”,你下载的任何副本的“数字指纹”只要和官方给出的“数字指纹”一致,那么就可以知道这是未经篡改的。例如著名的MD5 ;
  2).数据结构领域:
  Hash算法 通常还可用作快速查找。 
这是今天我想说的部分。根据Hash函数 我们可以实现一种叫做哈希表(Hash Table)的数据结构。这种结构可以实现对数据进行快速的存取。

高级语言中数据类型分为两类:
 1).原子类型:值不可分解,是什么就是什么。如整型、字符型等;
 2).结构类型:其值是由若干成分按某种结构组成的,因此可分解,并且它的成分可以是原子类型也可以是结构类型。比如数组,其值是由若干分量组成的,每个分量可以是整数,或者也可以是数组。

在编程语言中运用“数据结构”就是在使用被一层一层封装起来的某种数据类型 

 

覆盖equals方法通常有必要也覆盖hashCode方法,因为你必须保证对象equals,hashCode必须相等!

 

一致性哈希算法
  一致性哈希算法是分布式系统中常用的算法。比如,一个分布式的存储系统,要将数据存储到具体的节点上,如果采用普通的hash方法,将数据映射到具体的节点上,如key%N,key是数据的key,N是机器节点数,如果有一个机器加入或退出这个集群,则所有的数据映射都无效了。一致性哈希算法解决了普通余数Hash算法伸缩性差的问题,可以保证在上线、下线服务器的情况下尽量有多的请求命中原来路由到的服务器。

一致性哈希算法与Java实现- https://blog.csdn.net/u010558660/article/details/52767218
分布式一致性Hash算法实现java版- https://blog.csdn.net/baiyunpeng42/article/details/45339937

>  2.优先队列与堆(堆的上滤和下滤)
 堆通常是一个可以被看做一棵树的数组对象。堆是一颗被完全填满的二叉树,唯一可能的例外是在最底层。所以堆具有两个性质——堆序性和结构性。一个高为h的完全二叉树有2h或2h-1个节点,并且堆中每一个节点X的父亲的值小于或等于X中的关键字,所以堆的最小值总可以在根中找到。
  删除最小元基本的思想是将最小元置为空穴,再将堆的最后一个元素放入其中,则此时的堆是不合法的,我们需要做的就是将此时的堆顶元素下沉到合适的位置。
  二叉堆就结构性质上来说就是一个完全填满的二叉树,满足结构性和堆序性。
浅谈堆以及java优先队列的详细使用- https://blog.csdn.net/cquzhengdayday/article/details/72514900
数据结构和算法分析java--优先队列(堆实现)- https://blog.csdn.net/dexianglin/article/details/52749313

最大优先级队列和最小优先级队列的完整可以在下面的github地址处找到- https://github.com/l294265421/datastructure-common

>  3.并查集
 并查集是一种数据结构, 常用于描述集合,经常用于解决此类问题:某个元素是否属于某个集合,或者 某个元素 和 另一个元素是否同属于一个集合。并查集:快速Union,慢Find。
 并查集由一个整数型的数组和两个函数构成。数组pre[]记录了每个点的前导点是什么,函数find是查找,join是合并。

并查集(Java实现)- http://www.cnblogs.com/noKing/p/8018609.html
并查集(Union-Find) 应用举例 --- 基础篇- https://blog.csdn.net/dm_vincent/article/details/7769159
  首先在地图上给你若干个城镇,这些城镇都可以看作点,然后告诉你哪些对城镇之间是有道路直接相连的。最后要解决的是整幅图的连通性问题。比如随意给你两个点,让你判断它们是否连通,或者问你整幅图一共有几个连通分支,也就是被分成了几个互相独立的块。像畅通工程这题,问还需要修几条路,实质就是求有几个连通分支。如果是1个连通分支,说明整幅图上的点都连起来了,不用再修路了;如果是2个连通分支,则只要再修1条路,从两个分支中各选一个点,把它们连起来,那么所有的点都是连起来的了;如果是3个连通分支,则只要再修两条路……

 在对问题进行建模的时候,我们应该尽量想清楚需要解决的问题是什么。因为模型中选择的数据结构和算法显然会根据问题的不同而不同,就动态连通性这个场景而言,我们需要解决的问题可能是:
  给出两个节点,判断它们是否连通,如果连通,不需要给出具体的路径;
  给出两个节点,判断它们是否连通,如果连通,需要给出具体的路径。
第一种情况,即不需要给出具体路径的Union-Find算法,而第二种情况可以使用基于DFS的算法。

>  4.线段树,树状数组
  树一般有两种形式:1、以点为结点。2、以线段为结点。
  树状数组是对一个数组改变某个元素和求和比较实用的数据结构。两中操作都是O(logn)。
  线段树主要用来求某一区间的最小值、最大值或者和等,都可以在O(lgN)时间内解决,类似于区间树。树状数组和线段树很像,但能用树状数组解决的问题,基本上都能用线段树解决,而线段树能解决的树状数组不一定能解决。相比较而言,树状数组效率要高很多。树状数组有时比较难以理解,比如用树状数组求逆序数,所以个人建议树状数组就行了,没必要透彻,我就不用树状数组。
  线段树(interval tree) 是把区间逐次二分得到的一树状结构,它反映了包括归并排序在内的很多分治算法的问题求解方式。
java代码实现线段树- https://blog.csdn.net/u010953266/article/details/42774247

树状数组与线段树- https://www.2cto.com/kf/201504/387144.html
一个用JAVA实现的线段树类--泛型 重构.- https://blog.csdn.net/judyge/article/details/41175447
【第一个线段树+第一个Java程序!】- https://blog.csdn.net/cclsoft/article/details/5496273

>  5.伸展树
  伸展树(Splay Tree)是特殊的二叉查找树。它的特殊是指,它除了本身是棵二叉查找树之外,它还具备一个特点: 当某个节点被访问时,伸展树会通过旋转使该节点成为树根。这样做的好处是,下次要访问该节点时,能够迅速的访问到该节点。
  伸展树的旋转有六种类型,如果去掉镜像的重复,则为三种:zig(zag)、zig-zig(zag-zag)、zig-zag(zag-zig)。

伸展树特性
 1.和普通的二叉查找树相比,具有任何情况下、任何操作的平摊O(log2n)的复杂度,时间性能上更好 
 2.和一般的平衡二叉树比如 红黑树、AVL树相比,维护更少的节点额外信息,空间性能更优,同时编程复杂度更低 
 3.在很多情况下,对于查找操作,后面的查询和之前的查询有很大的相关性。这样每次查询操作将被查到的节点旋转到树的根节点位置,这样下次查询操作可以很快的完成 
 4.可以完成对区间的查询、修改、删除等操作,可以实现线段树和树状数组的所有功能

Java数据结构与算法解析(八)——伸展树- https://blog.csdn.net/u012124438/article/details/78067998
使用伸展树(SplayTree)统计单词频率的Java实现- https://blog.csdn.net/cuiods/article/details/52562967
伸展树与半伸展树Java实现- http://www.blogjava.net/javacap/archive/2007/12/19/168627.html

>  6.随机二叉树Treap
  AVL树,伸展树,它们都是二叉搜索树,二叉搜索树的主要问题就是其结构与数据相关,树的深度可能会很大;Treap树就是一种解决二叉搜索树可能深度过大的另一种数据结构。
   Treap=Tree+Heap。Treap本身是一棵二叉搜索树,它的左子树和右子树也分别是一个Treap,和一般的二叉搜索树不同的是,Treap纪录一个额外的数据,就是优先级。Treap在以关键码构成二叉搜索树的同时,还满足堆的性质。这些优先级是是在结点插入时,随机赋予的,Treap根据这些优先级满足堆的性质。这样的话,Treap是有一个随机附加域满足堆的性质的二叉搜索树,其结构相当于以随机数据插入的二叉搜索树。其基本操作的期望时间复杂度为O(logn)。相对于其他的平衡二叉搜索树,Treap的特点是实现简单,且能基本实现随机平衡的结构。
Treap维护堆性质的方法只用到了旋转,只需要两种旋转,编程复杂度比Splay要小一些。

  Treap是一棵二叉搜索树,只是每个节点多了一个优先级fix,对于每个节点,该节点的优先级小于等于其所有孩子的优先级。
当然,引入优先级fix的目的就是防止BST退化成一条链,从而影响查找效率。

  Treap跟笛卡尔树几乎是一模一样的,只是用途不同。笛卡尔树是把已有的一些(key, fix)二元组拿来构造树,然后利用构树过程和构造好的树来解决LCA,RMQ等等问题。而Treap的目的只是对一些key进行二叉搜索,但是为了保证树的平衡性,为每个key随机地额外增加了一个fix属性,这样从概率上来讲可以让这棵树更加平衡。
  对于Treap来说,主要有几大操作:插入,删除,查找,旋转,找第K大元素,找关键字x的排名,计算Treap的高度,删除Treap,其它的操作比如合并,分离,反转等等以后再说,另外,对于Treap来说,它的中序遍历的结果就是按照关键字从小到大的顺序排列的。

随机二叉树(Treap) Java实现- http://www.blogjava.net/xmatthew/archive/2012/05/16/347297.html

 

Java基础 - 树堆(Treap = tree+heap)- https://blog.csdn.net/apathecrazyfan/article/details/53439065

 

> 后缀树与后缀数组
后缀树和后缀数组是字符串处理的两大神器,几乎可处理掉一切的字符串处理问题,但是在实际中,后缀数组比后缀树更好写、好调,同时时间上也不差(常数很小),所以后缀数组绝对是OI竞赛之必备神器。

你可能感兴趣的:((高级)算法和数据结构)