
算法与数据结构
文章平均质量分 78
Jae_Wang
~
展开
-
位运算及在算法中的技巧(一)
位运算: 程序中所有数在计算机内存中都是以二进制的形式存储的,就是直接对整数在内存中的二进制位进行操作,由于直接对内存进行操作,不需要转成十进制,因此处理速度非常快。常见的小规则: 1. & 按位与 (and运算): 两位同时为1才返回1 一个数&1 结果就是取二进制最末尾。可以判断一个整数的奇偶,二进制末尾为0表示偶数,为1表示奇数。 2. |...原创 2018-04-24 22:59:59 · 3496 阅读 · 0 评论 -
算法与数据结构(18)—— 二叉搜索树中删除指定的节点
删除一个节点就是看有没有其孩子节点可以代替它,一般的可以找后继节点(右子树最小值)或前继节点(左子树的最大值)理清楚思路: d是删除的点,左右都有孩子,s是d的右孩子最小的点1. 找d的后继节点s2. s.right = delMin(d.right),在d的右子树删除最小的并返回其子树的根节点3. s.left = d.left 4. 删除d, s是新树的子树的根主要是二种情况:当左右子树有...原创 2018-06-08 15:43:20 · 746 阅读 · 0 评论 -
算法与数据结构(22)—— 并查集 Quick Union
之前的quick find中,union操作必选要全部一遍才能找到各个元素属于哪个集合,实际中并不常用quick find。而在quick union中,设置每个节点初始指向自己,类似于树的结构,这样在合并时,只需要判断这两个元素的根是否相同,由根指向就好了。优化:两个集合合并时,少的指向多的,但是不绝对,会有极端情况,于是又有一种优化,基于层数来比较。当然了,基于size和基于rank两者相差区...原创 2018-06-15 13:44:39 · 250 阅读 · 0 评论 -
算法与数据结构(23)—— 并查集 路径压缩
在查找根节点,我们需要一个一个查找parent以得到这个集合的根节点。那么我们在查找的时候,如果父节点不是根节点的话,可以指向父节点的父节点,这样就节省了不少树的高度(非递归版)。当然,因为节点是有指向父节点的,所以可以让每一个都指向根节点,根节点可以有无数个孩子(递归版)。理论上,递归版树的高度要低点,效率好,但是实际上,由于递归过程会产生额外的开销~实际中,使用非递归的就可以了,面试的时候讲讲...原创 2018-06-15 14:02:41 · 890 阅读 · 0 评论 -
算法与数据结构(19)—— 二叉搜索树中前驱和后驱
一个节点的前驱节点是其左子树中的最大值,若无左子树,其前驱节点在从根节点到key的路径上,比key小的最大值。一个节点的后继节点是右子树的最小值,若无右子树,其后继节点在从根节点到key的路径上,比key大的最小值。代码实现:如果key所在的节点不存在,则key没有前驱, 返回NULL如果key所在的节点左子树不为空,则其左子树的最大值为key的前驱否则,key的前驱在从根节点到key的路径上,在...原创 2018-06-08 17:05:11 · 2156 阅读 · 0 评论 -
算法与数据结构(20)—— 二叉搜索树中的ceil、floor方法以及总结
寻找floor , ceil无需保证。若key值存在,那么floor , ceil就是key值自身。若key值不存在: floor:是最接近key值且**小于**key的节点ceil:是最接近key值且**大于**key的节点例如下图,举几个例子来了解:节点41的floor , ceil是41;45的floor是42,ceil是50;64无ceil,floor是61;11无floor,ceil是1...原创 2018-06-08 18:20:43 · 2499 阅读 · 2 评论 -
算法与数据结构(24)—— 邻接表表示稀疏图
应用:交通运输,社交网络,互联网,工作安排,脑区活动图的分类:无向图和有向图(无向图是一种特殊的有向图)无权图和有权图简单图不包括自环边和平行边。自环边:自己指向自己平行边:两个点有多条边图的表示: 邻接矩阵:适用稠缪图(Dense Graph,每个点几乎与每个点相连,即完全图)邻接表:适用稀疏图(Sparse Graph)public class SparseGraph { priva...原创 2018-06-16 16:33:52 · 2595 阅读 · 0 评论 -
算法与数据结构(25)—— 邻接矩阵表示稠密图
邻接表是一个list数组,数组中每个元素都是list,可扩展。而临界矩阵是一个二维矩阵public class DenseGraph { private int n; // 节点数 private int m; // 边数 private boolean directed; // 是否为有向图 private boolean[][] g; // ...原创 2018-06-16 16:41:04 · 783 阅读 · 0 评论 -
算法与数据结构(1)—— 选择、插入排序 及 优化
一、前言算法和语言无关、学习路径从线性(排序),树形结构,图形结构慢慢学~1. 算法思想:在强调数据结构的重要性后,其中算法思想也是不容忽略:分治算法:归并排序、快速排序……贪心算法:最小生成树……动态规划:最短路径……递归搜索:树形结构……以上所举的例子可以看出数据结构和算法之间的互相依托程度,例如在学习归并、快速排序时,实则也在探究分治算法……每个细分领域都是算法,例如以下例子:图形学机器学习...原创 2018-06-02 13:23:32 · 1746 阅读 · 0 评论 -
算法与数据结构(2)—— 冒泡、希尔排序 及 优化
前言:之前介绍了选择,插入以及它们的优化,发下在几乎有序的情况下,插入排序的高效性~一、冒泡排序数组中第一个元素开始两两比较,前者比后者大就交换一下第一趟的最大值已经排上去后,那么接着从第一个元素开始比较到n-1个数,以此类推~ public static void sort(Comparable[] arr){ int n = arr.length; // n-1...原创 2018-06-02 16:04:35 · 507 阅读 · 0 评论 -
算法与数据结构(26)—— dfs的基本应用
深度优先遍历:其实就是往一个往死里走,直到这个点不再指向其他或已经遍历过了,就退出来,接着往下一个点,直到所有的就访问过了。 应用:求一个图的连通分量,求两个点之前的路径dfs核心代码: public void dfs(int v) { visited[v] = true; // 节点 i 已被访问 for (int node : g...原创 2018-06-16 16:56:39 · 582 阅读 · 0 评论 -
算法与数据结构(27)—— bfs的最短路径
从一个点出发, 与这个点相连的点都入队,类似于树的层次遍历就好了~核心代码: Queue<Integer> q = new LinkedList<Integer>(); q.add(s); visited[s] = true; ord[s] = 0; while(!q.isEmpty()){ ...原创 2018-06-16 18:29:05 · 545 阅读 · 0 评论 -
算法与数据结构(28)—— Lazy Prim
这个比较简单,利用堆的思想,寻找该节点相邻节点最短的边,但是有个判断时一条边的两个点不能同时在一个阵营,即这条边就不是横切边了。核心代码: private void visit(int v){ marked[v] = true; // 将和节点v相连接的所有未访问的边放入最小堆中 for( Edge<Weight> e : G.adj(...原创 2018-06-16 23:35:17 · 317 阅读 · 0 评论 -
算法与数据结构(29)—— Prim实现最小生成树
实现的基础是索引堆,不过有数据结构基础的实现上还是比较能理解的~新建了一个edge数组,初始大小为节点个数,类型为边,专门用来存边了。作用是每次访问点的临界点所构成的边存在里面。marked标记数组,仍是看是否在同一个阵营,来判断是否是横切边索引堆,初始大小仍是节点个数,依据权值来判断。核心代码:public PrimMST(WeightedGraph graph){ G = g...原创 2018-06-16 23:43:27 · 235 阅读 · 0 评论 -
算法与数据结构(21)—— 并查集基础 Quick Find
高效的解决连接问题。主要两类:1.网络中节点间的连接状态。 2.数学中集合类实现连接问题:相对容易,只需要解决是否相连。路径问题:两个点之间连接路径,具体的路径。实现:用数组来实现,10个数据,值相同就为1组,那么两个数相连后,其所在的组也合并成一个组了。主要两个操作:find(p):时间复杂度为O(1), union(p,q) 时间复杂度O(n),isConnection(p,q)public...原创 2018-06-15 10:39:08 · 440 阅读 · 0 评论 -
算法与数据结构(17)—— 二叉树的最大、最小子节点的搜索和删除
删除最小值:有两种情况,一直访问到左节点为null,有两种情况,当有节点不为null时,需要将其右孩子替换过去。但是在递归时,不管右孩子有没有我们都可以将其赋值过去。同理最大值~返回的都是当前数的根节点寻找最小节点private Node minimun(Node node){ if(node.left == null) return node; return minimun(n...原创 2018-06-08 11:21:18 · 1215 阅读 · 0 评论 -
算法与数据结构(15)—— 二叉树的基础,节点插入,查找
二分搜索树常见的应用:字典数据结果, 以键值对形成了表。每个节点的键值大于左孩子,小于右孩子。二分搜索树可以不是一颗完全二叉树,堆是一颗完全的二叉树。代码实现:public class BST<Key extends Comparable<Key>, Value> { // 树中的节点为私有的类, 外界不需要了解二分搜索树节点的具体实现 private c...原创 2018-06-07 19:45:01 · 2581 阅读 · 0 评论 -
算法与数据结构(3)—— 归并排序
前言:前面介绍的几个时间复杂度为 O(n^2)的几个排序算法(选择、插入、冒泡、希尔排序),其中尤为需要注意的是插入排序,在近乎有序的测试用例条件下,此算法的效率会高于O(n*logn)的排序算法,几乎是O(n), 一、O(n*logn) 和 O(n^2)算法比较: O(n*logn)可以在1s内轻松处理百万数量级的数据,当n=10^5时,其实这个测试数量也不是很大,O(n*logn)比O...原创 2018-06-03 09:02:29 · 776 阅读 · 0 评论 -
算法与数据结构(4)—— 归并排序(自底向上)
前言:之前考虑的是自顶向下的思路,当然也可以反过来~算法思想:将此数组按照从坐到右的顺序两两划分成多个小组来进行归并排序的过程(一个组有2个元素)。在两个元素归并排序完成后,再按照从坐到右的顺序将两个组进行归并到一个组(即1个组有4个元素)。依次类推。public static void sort(Comparable[] arr){ int n = arr.length;...原创 2018-06-03 10:22:52 · 1190 阅读 · 0 评论 -
算法与数据结构(5)—— 归并排序(手摇算法)
何为手摇算法空间复杂度降低,但是时间复杂度会提高,实际中不适用~ 了解即可public static void mergeSort(int[] a){ sort(a, 0, a.length - 1);}public static void sort(int[] a, int left, int right){ if(left < right){ int mid ...原创 2018-06-03 10:50:52 · 535 阅读 · 1 评论 -
算法与数据结构(6)—— 快速排序(随机化及优化)
前言:快速排序和归并排序其实是差不多的,只不过就是归并不管数组内容是什么,直接一分为二,而快排是选择一个元素,将其放在合适的位置,使左边的元素小于它,右边的大于它~这样逐渐递归~它的核心就是Partition过程:通常使用数组的第一个元素来作为分界的标志点(基点),记为l(left)之后逐渐遍历右边所有未被访问元素在遍历的过程中逐渐整理让整个数组左部分小于 v 这个元素值,右部分大于 v。在此过程...原创 2018-06-03 13:24:37 · 515 阅读 · 0 评论 -
算法与数据结构(7)—— 快速排序(二路、三路)
前言:介绍了快排分界的标志点,选取的随机性会大大降低快排退化成O(n^2)算法的概率。问题:当包含大量相同的元素的数组时快排仍会退化成O(n^2)级别的算法我们之前判断的时候,并没有判断等于的情况~ 这样会造成一个结果,把相同的放入左右任何一部分,会造成极其的不平衡,仍会退化成O(n^2)算法~二路快速排序(Quick Sort 2 Ways)算法思路:然后从左到右逐渐遍历整个数组。现在将这两...原创 2018-06-03 15:08:50 · 1936 阅读 · 0 评论 -
算法与数据结构(12)—— 索引堆
一. 索引堆(Index Heap)可是在构建堆的过程中有局限性:如果元素是非常复杂的结构,例如字符串(一篇十万字的文章)等等,这样交换的代价是十分大的。不过这可以通过一些基本手段解决,更加致命的是元素在数组中的位置发生改变,使得在堆中很难索引到它!例如元素下标是任务ID,元素值是优先级别。当将数组构建成堆后,下标发生改变,则意味着两者无法产生联系!在原来数组中寻找任务只需O(1),但是构建成堆后...转载 2018-06-05 15:51:21 · 438 阅读 · 0 评论 -
算法与数据结构(8)——逆序对(归并排序)
逆序对关于归并排序和快速排序的第一个衍生问题就是逆序对,例如下图中的数组{8,6,2,3,1,5,7,4},其中{2,3}就是一个顺序对,而{2,1}就是一个逆序对。归并排序要解决此问题此时可以依赖于归并过程,例如以下动画,两个分别排好序的子数组{2,3,6,8,}和{1,4,5,7,}:首先1比2小,意味1比2后面的所有元素都小,计数器可直接加4,指向1的下标后移。4大于2,不考虑,指向2的下标...原创 2018-06-05 13:05:28 · 823 阅读 · 0 评论 -
算法与数据结构(9)——取数组中第n小的元素(快排)
此问题的解决思路很简单,就是给整个数组排序再通过下标索引取出元素即可,算法复杂度为O(n*logn),但是!在本篇博文中学习了快速排序后,可使用O(n)时间获取。快速排序的核心过程每次找到一个标志点,将此点挪到数组中合适的位置,注意此合适位置恰好是数组中排序好后所处的位置。示例引导例如下图示例中的标志点4,最后挪到的位置恰好就是数组最后有序的位置,比如此时我们要获取第6个位置上的元素,那么标志位4...原创 2018-06-05 13:07:19 · 712 阅读 · 0 评论 -
算法与数据结构(10)—— 二叉堆(堆排序、Heapify)
一. 堆结构1.优先队列普通队列:先进先出,后进后出。优先队列:优先级高的先出来,与时间无关、应用:优先队列在OS的使用,CPU调度时间片,每次优先选择优先级最高的任务执行,注意是动态的~;不仅仅适用于OS,还有在请求某个网页,服务器按需要返回,回应的一般是按照优先队列决定的~处理问题:之前的排序算法,N个元素选前M个元素,时间复杂度O(nlogn),使用优先队列时,可将时间复杂度降低为O(Nlo...原创 2018-06-05 13:34:52 · 521 阅读 · 0 评论 -
算法与数据结构(11)—— 堆排序(原地排序)以及排序算法总结
原地排序:之前两种的都是从索引1开始计算的,而原地排序不需要额外的辅助空间,即不用去创造堆,那么索引从0开始的~注意一下 最后一个非叶子结点的索引是(count - 2)/ 2public class HeapSort { private HeapSort() { } public static void sort(Comparable[] arr){ ...原创 2018-06-05 13:35:38 · 1494 阅读 · 0 评论 -
算法与数据结构(13)—— 二分查找(递归与非递归)
递归private static int find(Comparable[] arr, int l, int r, Comparable target){ if(l > r) return -1; int mid = (r-l)/2 + l; if(arr[mid].compareTo(target) == 0) r...原创 2018-06-06 23:35:02 · 1044 阅读 · 0 评论 -
算法与数据结构(14)—— 二分查找变种(ceil与floor)
当存在大量重复的元素时,floor找的是第一个,ceil找的是第一个。当不存在指定的元素时,floor是比其小最大的一个,而ceil是比其大最小的一个。static int floor(Comparable[] arr, Comparable target){ // 寻找比target小的最大索引 int l = -1, r = arr.length-1; ...原创 2018-06-07 15:53:40 · 1515 阅读 · 1 评论 -
算法与数据结构(16)—— 二叉树的深度遍历(递归与非递归)与广度遍历
二叉树的深度优先遍历前序遍历:先访问当前节点,再依次递归访问左右子树中序遍历:先递归访问左子树,再访问自身,再递归访问右子树后续遍历:先递归访问左右子树,再访问自身节点前序:private void preOrder(Node node){ if(node == null) return; visit(node); preOrder(node.lef...原创 2018-06-07 22:58:17 · 307 阅读 · 0 评论 -
算法与数据结构(30)—— Kruskal实现最小生成树
这个算法实现起来相对比较简单,有个原则,最小生成树是权值最小的边构成的。那么每次都找最小的一条边就可以了,只要不构成环就行了。那么对边进行排序,然后判断把边加入最小树中是否构成环,即并查集的思想。没有Prim的高效,但是思想比较简单,也容易实现。 public KruskalMST(WeightedGraph graph){ mst = new ArrayList<Edge&...原创 2018-06-17 00:04:36 · 413 阅读 · 0 评论