
数据结构及算法(java)
文章平均质量分 75
数据结构
ximeneschen
这个作者很懒,什么都没留下…
展开
-
基于Redisson的Redis结合布隆过滤器使用
布隆过滤器的误判是指多个输入经过哈希之后在相同的bit位置1了,这样就无法判断究竟是哪个输入产生的, 因此误判的根源在于相同的 bit 位被多次映射且置 1。这种情况也造成了布隆过滤器的删除问题,因为布隆过滤器的每一个 bit 并不是独占的,很有可能多个元素 共享了某一位。此时我们查询一个没添加过的不存在的字符串inexistent-key,它有可能计算后坑位也是1/3/5 ,这就是误判了。如果这些点, 有任何一个为零则被查询变量一定不在, 如果都是 1,则被查询变量很 可能存在。原创 2023-07-18 14:38:16 · 2207 阅读 · 2 评论 -
HashSet、TreeSet、TreeMap实现原理
一、HashSet底层实现HashSet实现了Set接口,不允许有重复元素,因为HashSet是基于HashMap实现的,HashSet中的元素都存放在HashMap的key上面,而value中的值都是统一的一个private static final Object PRESENT = new Object();。HashSet跟HashMap一样,都是一个存放链表的数组。二、HashSet构...原创 2020-04-19 16:33:31 · 650 阅读 · 0 评论 -
PriorityQueue源码解析
一、概述优先队列的作用是能保证每次取出的元素都是队列中权值最小的(Java的优先队列每次取最小元素,C++的优先队列每次取最大元素)。这里牵涉到了大小关系,元素大小的评判可以通过元素本身的自然顺序(natural ordering),也可以通过构造时传入的比较器(Comparator,类似于C++的仿函数)。Java中PriorityQueue实现了Queue接口,不允许放入null元素;其通过堆实现,具体说是通过完全二叉树(complete binary tree)实现的小顶堆(任意一个非叶子节点的权原创 2021-08-27 15:31:10 · 144 阅读 · 0 评论 -
一致性哈希算法在分布式缓存中的应用
一、应用场景假设我们有一个网站,最近发现随着流量增加,服务器压力越来越大,之前直接读写数据库的方式不太给力了,于是我们想引入Redis作为缓存机制。现在我们一共有三台机器可以作为Redis服务器,如下图所示。二、要解决的问题一般来说我们在大规模访问,大并发流量下都会使用到分布式缓存,即将廉价机器部署在同一个子网内,形成多机器集群,然后通过负载均衡以及一定的路由规则进行读请求的分流,将请求映射到对应的缓存服务器上。如何对请求与缓存服务器之间进行精准映射,以及优雅的扩展,剔除缓存服务器是分布式缓存部署的转载 2021-08-10 12:36:57 · 303 阅读 · 1 评论 -
HashMap(Java)
何为HashMap:HashMap是常用的数据结构,由数组和链表组合构成,可理解为链表构成的数组(注:jdk1.8之后如果链表长度达到阈值(默认为8),就会更改使用红黑树)关于超过阈值而使用红黑树的关键源码:1.红黑树相关关键参数//一个桶的树化阈值//当桶中元素个数超过这个值时,需要使用红黑树节点替换链表节点//这个值必须为 8,要不然频繁转换效率也不高static final i...原创 2020-04-03 17:24:06 · 272 阅读 · 0 评论 -
跳表(skipList)
一、为何有skipList这种数据结构的出现我们知道二分查找算法之所以能达到 O(logn) 这样高效的一个重要原因在于它所依赖的数据结构是数组,数组支持随机访问一个元素,通过下标很容易定位到中间元素。而链表是不支持随机访问的,只能从头到尾依次访问。但是数组有数组的局限性,比如需要连续的内存空间,插入删除操作会引起数组的扩容和元素移动,链表有链表的优势,链表不需要先申请连续的空间,插入删除操作的效率非常高。在很多情况下,数据是通过链表这种数据结构存储的,如果是有序链表,真的就没有办法使用二分查找算法了吗?转载 2020-06-19 21:21:58 · 639 阅读 · 0 评论 -
最小生成树(Kruskal和Prim算法)
一、先再次明确关于图的几个概念定义:连通图:在无向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该无向图为连通图。强连通图:在有向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该有向图为强连通图。连通网:在连通图中,若图的边具有一定的意义,每一条边都对应着一个数,称为权;权代表着连接连个顶点的代价,称这种连通图叫做连通网。生成树:一个连通图的生成树是指一个连通子图,它含有图中全部n个顶点,但只有足以构成一棵树的n-1条边。一颗有n个顶点的生成树有且仅有n-1条边,如果生成树中再原创 2020-06-19 12:44:05 · 249 阅读 · 0 评论 -
最小生成树与最短路径的区别以及实现方法
一、区别最小生成树能够保证整个拓扑图的所有路径之和最小,但不能保证任意两点之间是最短路径。最短路径是从一点出发,到达目的地的路径最小。二、实现方法最小生成树最小生成树有两种算法来得到:Prims算法和Kruskal算法。Kruskal算法:根据边的加权值以递增的方式,一次找出加权值最低的边来构建最小生成树,而且规定:每次添加的边不能造成生成树有回路,知道找到N-1个边为止。Prims算法:以每次加入一个的临界边来建立最小生成树,直到找到N-1个边为止。其规则为:以开始时生成树的集合(集转载 2020-06-18 23:18:56 · 4246 阅读 · 0 评论 -
动态规划和贪心算法的区别
要想清楚两者的区别,首先就要了解两者的基本概念与性质。1. 贪心算法基本思想:贪心算法并不从整体最优上加以考虑,它所做的选择只是在某种意义上的局部最优解。基本要素:最优子结构性质和贪心选择性质。该算法存在问题:1.不能保证求得的最后解是最佳的;2.不能用来求最大或最小解问题;3.只能求满足某些约束条件的可行解的范围。实现该算法的过程:从问题的某一初始解出发;while 能朝给定总目标前进一步 do求出可行解的一个解元素;由所有解元素组合成问题的一个可行解经典例子:原创 2020-06-18 18:10:36 · 759 阅读 · 0 评论 -
最短路径:Dijkstra算法和Floyd算法
一、Dijkstra算法(单个顶点到其他顶点的最短距离)定义概览Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。注意该算法要求图中不存在负权边。问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径。(单原创 2020-06-18 17:45:11 · 1018 阅读 · 0 评论 -
图的两种存储形式(邻接矩阵、邻接表)
图可以使用两种存储结构,分别是邻接矩阵和邻接表。注意:一个图所对应的邻接矩阵唯一,所对应的邻接表不唯一一、邻接矩阵邻接矩阵以矩阵的形式存储图所有顶点间的关系。邻接矩阵具有以下特点:1.邻接矩阵是正矩阵,即横纵维数相等。2.矩阵的每一行或一列代表一个顶点,行与列的交点对应这两个顶点的边。3.矩阵的点代表边的属性,1代表有边,0代表无边,所以矩阵的对角线都是0,因为对角线上对应的横纵轴代表相同的顶点,边没有意义。4.如果是无向图,那么矩阵是对称矩阵;如果是有向图则不一定是对称矩阵。5.如果原创 2020-06-17 22:37:05 · 21795 阅读 · 0 评论 -
图的相关概念
一、图的逻辑结构图的定义图是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G=(V,E)ps:G表示一个图,V是图G中顶点的集合,E是图G中顶点之间边的集合。二、图的基本概念1.无向边:顶点vi和vj之间的边没有方向,表示为(vi,vj)。2.无向图:图的任意两个顶点之间的边都是无向边。3.有向边:从顶点vi到vj的边有方向,表示为<vi,vj>。4.有向图:图的任意两个顶点之间的边都是有向边。5.简单图:若不存在顶点到其自身的边,且同一条边不重复出现。6.原创 2020-06-13 02:45:13 · 675 阅读 · 0 评论 -
B-Tree/B+Tree/B*Tree
一、平衡多路查找树(B-Tree)B-Tree是为磁盘等外存储设备设计的一种平衡查找树。因此在讲B-Tree之前先了解下磁盘的相关知识。系统从磁盘读取数据到内存时是以磁盘块(block)为基本单位的,位于同一个磁盘块中的数据会被一次性读取出来,而不是需要什么取什么。InnoDB存储引擎中有页(Page)的概念,页是其磁盘管理的最小单位。InnoDB存储引擎中默认每个页的大小为16KB,可通过参数innodb_page_size将页的大小设置为4K、8K、16K,在MySQL中可通过如下命令查看页的大小原创 2020-05-30 14:47:08 · 233 阅读 · 0 评论 -
红黑树
一、有了二叉平衡树,为何还要有红黑树?虽然平衡树解决了二叉查找树退化为近似链表的缺点,能够把查找时间控制在O(logn),不过却不是最佳的,红黑树的查询性能略微逊色于AVL树,因为他比avl树会稍微不平衡最多一层,也就是说红黑树的查询性能只比相同内容的avl树最多多一次比较,但是,红黑树在插入和删除上完爆avl树,avl树每次插入删除会进行大量的平衡度计算,而红黑树为了维持红黑性质所做的红黑变换和旋转的开销,相较于avl树为了维持平衡的开销要小得多。删除node引起树的不平衡时,最坏情况下,AVL需要维护原创 2020-05-26 23:50:49 · 153 阅读 · 0 评论 -
递归遵守的条件
递归需要遵守的重要规则1.执行一个方法时,就创建一个新的受保护的独立空间(栈空间)2.方法的局部变量是独立的,不会相互影响, 比如n变量3.如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据.4.递归必须向退出递归的条件逼近,否则就是无限递归,出现StackOverflowError5.当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同...原创 2020-01-20 14:54:05 · 377 阅读 · 0 评论 -
自平衡二叉树(Self-balancing binary search tree)
排序二叉树有以下缺点:同样的关键字集合有可能导致不同的树结构索引,如下图的右图所示,此时他的搜索性能已经是线性的了,为了解决这种"树一边倒的现象",自平衡二叉树就被提出来了。平衡二叉树的目的是为了减少二叉查找树层次,提高查找速度。平衡二叉树定义:平衡二叉树或为空树,又被称为AVL树(有别于AVL算法)或为如下性质的二叉排序树:(1)左右子树深度之差的绝对值不超过1;(2)左右子树仍...原创 2020-04-09 13:32:45 · 3895 阅读 · 0 评论 -
排序二叉树BST(binary search/sort tree)
之前介绍说,树这种存储结构,能提高数据的存储,读取效率。所以树的应用就可以体现在排序这一方面,比如有排序二叉树,平衡二叉树,红黑树等。本文介绍排序二叉树。1.排序二叉树是一种特殊结构的二叉树,可以非常方便地对树中所有节点进行排序和检索。2.排序二叉树要么是一棵空二叉树,要么是具有下列性质的二叉树:3.若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值;4.若它的右子树不空,则右子...原创 2020-04-08 14:38:10 · 522 阅读 · 0 评论 -
堆排序(基于完全二叉树)
1.堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。2.堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆,注意:没有要求结点的左孩子的值和右孩子的值的大小关系。3.每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆堆排序的的关键就是构建初始堆(大顶堆(升序...原创 2020-04-06 17:46:34 · 869 阅读 · 0 评论 -
线索二叉树(基于链表存储树结点)
有以下场景如果使用中序遍历,那么得到的顺序是:HDIBEAFCG,可以得知A的前驱结点为E,后继结点为F。但是,这种关系的获得是建立在完成遍历后得到的。如果我们每次想得到某个节点的前驱或者后继,都要先遍历整棵树,未免太过于麻烦了!我们为何不在生成该树的时候,就直接将结点的前驱后后继写入结点的属性中,提高在后续寻找前驱结点和后继结点的效率?这就是线索二叉树的由来。首先,得先明确以下概念:1....转载 2020-04-05 15:15:45 · 935 阅读 · 0 评论 -
顺序二叉树(基于数组存储树结点)
从数据存储来看,数组存储方式和树的存储方式可以相互转换,即数组可以转换成树,树也可以转换成数组,看下面的示意图。顺序二叉树有两个要求:1.上图的二叉树结点,以数组的方式来存放2.要求在遍历数组时,仍然可以以前序、中序、后序的方式完成节点的遍历顺序二叉树的特点:1.顺序二叉树通常只考虑完全二叉树2.第n个元素的左子节点为2*n+13.第n个元素的右子节点为2*n+24.第n个...原创 2020-04-05 00:10:44 · 1278 阅读 · 0 评论 -
树节点的遍历,查找,删除及深度优先(前序,中序,后序)、广度优先遍历
二叉树模板类:class BinaryTree { private Node root; public void setRoot(Node root) { this.root = root; } //删除结点 public void delNode(int no) {} //前序遍历 public void preOrder() {} //中序遍历 public void ...原创 2020-04-03 19:59:57 · 662 阅读 · 0 评论 -
树
首先:为何需要树这种数据结构?1)数组存储方式的分析优点:通过下标方式访问元素,速度快。对于有序数组,还可使用二分查找提高检索缺点:如果要检索具体某个值,或者插入值(按一定顺序)会整体移动,效率较低。2)链式存储方式的分析优点:在一定程度上对数组存储方式有优化(比如:插入一个数值节点,只需要将插入节点,链接到链表中即可,删除效率也很好。缺点:在进行检索时,效率仍然较低,比如(检索某...原创 2020-04-03 18:05:42 · 121 阅读 · 0 评论 -
斐波那契查找
**基本思想:**也是二分查找的一种提升算法,通过运用黄金比例的概念在数列中选择查找点进行查找,提高查找效率。同样地,斐波那契查找也属于一种有序查找算法。斐波那契查找与折半查找很相似,他是根据斐波那契序列的特点对有序表进行分割的。要求开始表中记录的个数为某个斐波那契数小1,即n=F(k)-1;如果有序表的元素个n不等于(某个斐波那契数 - 1),即n≠F[k]-1,这时必须要将有序表的元素扩展...原创 2020-03-26 19:43:50 · 251 阅读 · 0 评论 -
插值查找(按比例查找)
插值查找的一个最简单案例就是查字典,查abandon的时候,我们都是从最前面开始找的,不可能从字母m开始,然后再用二分查找吧?插值查找就是根据要查找的关键字 key 与查找表中最大最小记录的关键字比较后的查找方法,其核心在于插值的计算公式,如图:粗俗理解:目标数组大概在数组的几分之几的位置(画个相似三角形就能理解)逼格高点:自适应梯度下降值得注意的是:插值查找也有其不适合的场景,就是数值分...原创 2020-03-26 14:04:54 · 370 阅读 · 0 评论 -
二分查找
二分查找法在算法家族大类中属于“分治法”,分治法基本都可以用递归来实现的,当然也可以使用非递归的方式实现。需要注意的是:如要使用二分查找,需满足以下条件:存储在数组中有序排列线性查找和二分查找的动态对比:递归实现(解决多个相同值返回多个索引):public static List<Integer> binarySearch(int[] arr, int left, in...原创 2020-03-26 11:53:51 · 144 阅读 · 0 评论 -
排序算法
1.冒泡排序 // 第一趟排序,就是将第一大的数排在倒数第一位 for (int j = 0; j < arr.length - 1 ; j++) { // 如果前面的数比后面的数大,则交换 if (arr[j] > arr[j + 1]) { temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] ...原创 2020-03-25 17:11:29 · 269 阅读 · 0 评论 -
单向环形列表及应用场景(约瑟夫环)
一、环形列表:二、构建一个单向的环形链表思路1.先创建第一个节点让first指向该节点,并形成环形2.后面当我们每创建一个新的节点,就把该节点,加入到己有的环形链表中即可三、遍历环形链表1.先让一个辅助指针(变量)curBoy,指向first节点2.然后通过一个while循环遍历该环形链表即可curBoy.next==first结束四、环形列表节点类:// 创建一个Boy类,表...原创 2020-03-24 00:22:30 · 755 阅读 · 0 评论 -
双向链表
单向链表的缺点分析:1)单向链表,查找的方向只能是一个方向,而双向链表可以向前或者向后查找。2)单向链表不能自我删除,需要靠辅助节点,而双向链表,则可以自我删除,所以前面我们单链表删除时节点,总是找到temp,temp是待删除节点的前个节点3)示意图帮助理解删除:如下图的长红线和长蓝线双向列表节点类:class HeroNode2 { public int no; publi...原创 2020-03-23 22:59:42 · 100 阅读 · 0 评论 -
链表
链表是以节点的方式来存储,是链式存储每个节点包含域,next域:指向下一个节点如图:发现链表的各个节点不一定是连续存储链表分带头节点的链表和没有头节点的链表,根据实际的需求来确定。Java中ArrayList,其实现原理是数组。而LinkedList的实现原理就是链表。链表在进行循环遍历时效率不高,但是插入和删除时优势明显。单向链表是一种线性表,实际上是由节点(Node)组成...原创 2020-03-23 22:15:37 · 113 阅读 · 0 评论 -
环形队列
环形队列的最大优点就是,使队列可以重复使用,不会因为列尾到底,列头又有空数据,但是不能插入造成无法重复使用queue类:判空:rear == front判满:(rear + 1) % maxSize == front;//true or false插入:arr[rear] = n;//将 rear 后移, 这里必须考虑取模 rear = (rear + 1) %maxSize;出列:...原创 2020-03-23 15:58:49 · 1534 阅读 · 0 评论 -
队列
队列是一个有序列表,可以用数组或者链表来实现。遵循先入先出的原则。队列的输入输出分别是从前后端来处理,因此需要两个变量front,rear来分别记录前后端的下标,front会随着数据的输出而改变,rear则是随着数据的输入而改变。示意图:queue类:1.判空:rear == front2.判满:rear == maxSize - 13.入列:rear++; // 让rear 后移;...原创 2020-03-23 15:20:10 · 286 阅读 · 0 评论 -
稀疏数组
稀疏数组的一个比较经典的应用就是:记录棋盘。思想:通过记录第几行第几列的值,达到缩小存储内存的目的,恢复的时候就直接使用保存的稀疏数组恢复就好。关键代码:压缩棋盘:// 将二维数组 转 稀疏数组 // 1. 先遍历二维数组 得到非0数据的个数 int sum = 0; for (int i = 0; i < 11; i++) { for (int j = 0; j...原创 2020-03-23 14:59:28 · 156 阅读 · 0 评论 -
数据结构与算法绪论
一. 数据结构相关概念1.数据:用于描述客观事物的数值、字符,以及一切可以输入到计算机中的并由计算机程序加以处理的符号的集合。2.数据元素:数据的基本单位,通常作为一个整体进行考虑和处理3.数据项:是数据的不可分割的最小单位,一个数据元素可由若干个数据项组成4.数据对象:性质相同的元素的集合叫做数据对象二.逻辑结构1.概念:数据结构中描述的是数据元素之间的抽象关系(逻辑关...原创 2020-03-23 14:35:54 · 226 阅读 · 0 评论