代码改变世界

优雅数据结构-BloomFilter

2012-07-31 20:14 by coodoing, 337 阅读, 0 推荐, 收藏, 编辑
摘要:Bloom Filter是由Bloom在1970年提出的一种多哈希函数映射的快速查找算法。通常应用在一些需要快速判断某个元素是否属于集合,但是并不严格要求100%正确的场合。一. 实例为了说明Bloom Filter存在的重要意义,举一个实例:假设要你写一个网络蜘蛛(web crawler)。由于网络间的链接错综复杂,蜘蛛在网络间爬行很可能会形成“环”。为了避免形成“环”,就需要知道蜘蛛已经访问过那些URL。给一个URL,怎样知道蜘蛛是否已经访问过呢?稍微想想,就会有如下几种方案:1. 将访问过的URL保存到数据库。2. 用HashSet将访问过的URL保存起来。那只需接近O(1)的代价就可以 阅读全文

回溯算法-8皇后问题

2012-07-31 19:53 by coodoing, 533 阅读, 0 推荐, 收藏, 编辑
摘要:8皇后问题表述:在n×n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n后问题等价于在n×n格的棋盘上放置n个皇后,任何2个皇后不放在同一行或同一列或同一斜线上。求不同的解的个数。 解向量:(x1, x2, … , xn) 显约束:xi = 1,2, … ,n 隐约束: 1)不同列:xi != xj ... 阅读全文

回溯算法-算法介绍

2012-07-31 17:24 by coodoing, 1927 阅读, 0 推荐, 收藏, 编辑
摘要:回溯法 1、有许多问题,当需要找出它的解集或者要求回答什么解是满足某些约束条件的最佳解时,往往要使用回溯法。 2、回溯法的基本做法是搜索,或是一种组织得井井有条的,能避免不必要搜索的穷举式搜索法。这种方法适用于解一些组合数相当大的问题。 3、回溯法在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。算法搜索至解空间树的任意一点时,先判断该结点是否包含问题的解。如果肯定不包含(剪枝过... 阅读全文

贪心算法-单源最短路径

2012-07-31 17:09 by coodoing, 2054 阅读, 0 推荐, 收藏, 编辑
摘要:给定带权有向图G =(V,E),其中每条边的权是非负实数。另外,还给定V中的一个顶点,称为源。现在要计算从源到所有其它各顶点的最短路长度。这里路的长度是指路上各边权之和。这个问题通常称为单源最短路径问题。Dijkstra算法是解单源最短路径问题的贪心算法。其基本思想是,设置顶点集合S并不断地作贪心选择来扩充这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。初始时,S中仅含有源。设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度。Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u 阅读全文

贪心算法-最优装载问题

2012-07-31 10:20 by coodoing, 5472 阅读, 0 推荐, 收藏, 编辑
摘要:贪心选择算法为算法分析中一种常用算法,通过一系列的选择来得到一个问题的解。它所作的每一个选择都是当前状态下某种意义的最好选择,即贪心选择。希望通过每次所作的贪心选择导致最终结果是问题的一个最优解。这种启发式的策略并不总能奏效,然而在许多情况下确能达到预期的目的。对于可利用贪心算法解决的问题需要同时满足:最优子结构性质和贪心选择性质。1.贪心选择性质所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。在动态规划算法中,每步所作的选择往往依赖于相关子问题的解。因而只有在解出相关子问题后,才能 阅读全文

动态规划-最长公共子序列的备忘录算法

2012-07-30 17:25 by coodoing, 1536 阅读, 0 推荐, 收藏, 编辑
摘要:LCS问题是常见的可利用动态规划算法进行解决的问题。这里利用备忘录算法对求解过的子问题进行备份存储,避免了相同子问题的重复求解。LCS问题子问题的递归关系式如下:具体代码实现如下: 1: static int LCS_Memo(int[][] c,char[] X,char[] Y,int i,int j) 2: { 3: if( (i == 0) || (j == 0) ) 4: c[i][j]=0; 5: else if(X[i-1] == Y[j-1]) 6: ... 阅读全文

动态规划-矩阵连乘

2012-07-30 16:41 by coodoing, 710 阅读, 0 推荐, 收藏, 编辑
摘要:给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2,…,n-1。考察这n个矩阵的连乘积A1A2…An。由于矩阵乘法满足结合律,故计算矩阵的连乘积可以有许多不同的计算次序,这种计算次序可以用加括号的方式来确定。若一个矩阵连乘积的计算次序完全确定,则可以依此次序反复调用2个矩阵相乘的标准算法(有改进的方法,这里不考虑)计算出矩阵连乘积。若A是一个p×q矩阵,B是一个q×r矩阵,则计算其乘积C=AB的标准算法中,需要进行pqr次数乘。 矩阵连乘积的计算次序不同,计算量也不同,举例如下: 先考察3个矩阵{A1,A2,A3}连乘,设这三个矩阵的维数分别为10 阅读全文

部分面试题分析

2012-07-29 20:24 by coodoing, 391 阅读, 0 推荐, 收藏, 编辑
摘要:1、两个数组a[N],b[N],其中A[N]的各个元素值已知,现给b[i]赋值,b[i] = a[0]*a[1]*a[2]...*a[N-1]/a[i]; 要求: 1.不准用除法运算 2.除了循环计数值,a[N],b[N]外,不准再用其他任何变量(包括局部变量,全局变量等)3.满足时间复杂度O(n),空间复杂度O(1) 1: private static int[] transform(int[] a, int[] b) { 2: int i = 0; 3: b[b.length - 1] = 1; 4: for (i = b.lengt... 阅读全文

冒泡排序

2012-07-29 13:39 by coodoing, 292 阅读, 0 推荐, 收藏, 编辑
摘要:1、原理介绍冒泡排序算法也是一种非常简单的排序算法,第一趟排序:n个数中,K1开始,依次比较两个相邻的关键字Ki和Ki+1(i=1,2,…,n-1),若Ki>Ki+1,则交换相应记录Ri和Ri+1的位置, 否则,不进行交换。经过这样一遍处理后,其中关键字最大的记录移到了第n个位置上。第二趟排序:对前面的n-1个记录进行第2遍排序,重复上述处理过程,第2遍之后,前n-1个记录中关键字最大的记录移到了第n-1个位置上,继续进行下去,直到不需要再交换记录为止。(最少比较次数为n-1是因为设置了change变量)2.可视化演示具体实现:First Pass: ( 5 1 4 2 8 ) ( 1 阅读全文

选择排序

2012-07-29 13:17 by coodoing, 227 阅读, 0 推荐, 收藏, 编辑
摘要:1、算法原理介绍: 选择排序思路,第一趟排序:从n个数中选择最小的1个放在第一个位置,第二趟:从剩下的n-1个数中选择一个最小的数放在第2个位置,依次类推。冒泡排序是比较相邻的交换相邻的,而选择排序不是。 2、可视化操作: 3、java代码 1: static void selectionSort(int[] arr,int len) 2: { ... 阅读全文

【转】各种树:trie树、B树、B-树、B+树、B*树

2012-07-29 12:56 by coodoing, 564 阅读, 0 推荐, 收藏, 编辑
摘要:红黑树rbtree 二叉排序树map 就是采用红黑树存储的,红黑树(RB Tree)是平衡二叉树,其优点就是树到叶子节点深度一致,查找的效率也就一样,为logN.在实行查找,插入,删除的效率都一致,而当是全部静态数据时,没有太多优势,可能采用hash表各合适。hash_map是一个hash table占用内存更多,查找效率高一些,但是hash的时间比较费时。总 体来说,hash_map 查找速度会比map快,而且查找速度基本和数据数据量大小,属于常数级别;而map的查找速度是log(n)级别。并不一定常数就比log(n)小, hash还有hash函数的耗时,明白了吧,如果你考虑效率,特别是在元 阅读全文

插入排序

2012-07-29 12:39 by coodoing, 414 阅读, 0 推荐, 收藏, 编辑
摘要:1、算法原理介绍: 直接插入排序是一种最简单的排序方法,通过把序列中的值插入一个已经排序好的序列中,直到该序列的结束。即先将第1个记录看作是一个有序的记录序列,然后从第2个记录开始,依次将未排序的记录插入到这个有序的记录序列中去,直到整个文件中的全部记录排序完毕。 2、可视化操作: 具体的实现步骤为: 插入x之前: 插入x之后: 伪代码如下: 1: ... 阅读全文

排序算法

2012-07-29 11:14 by coodoing, 718 阅读, 0 推荐, 收藏, 编辑
摘要:先给出比较有意思的一些网址:可视化的数据结构和算法和一些有意思的算法代码以及排序算法的动画演示。后续主要对常见的几种算法进行研究和分析,在分析的同时并适当的配以简单的可视化教程,方便理解。1、插入排序2、选择排序3、冒泡排序4、快速排序5、堆排序6、归并排序7、计数排序,基数排序和桶排序常见几种算法的比较,详细可参考算法性能比较: 阅读全文

整数划分问题

2012-07-29 10:28 by coodoing, 503 阅读, 0 推荐, 收藏, 编辑
摘要:所谓整数划分,就是将一个正整数n划分为一系列的正整数之和,如将n可以划分为:{m1,m2,m3,m4,m5..mk}(1=<k<=n),则{m1,m2,m3,m4,m5..mk}就是n的一个整数划分。下面我们要做的是,要找到所有的n的正整数划分。 我们该如何找出所有的划分呢? 我们可以先来看看整数划分的规律: 譬如正整数:6 划分情况如下: 6 5+1 4+2 4+1+1 3+3 3+2+1 3+1+1+1 2+2+2 2+2+1+1 2+1+1+1+1 1+1+1+1+1+1 观察第一列的数字发现,我们划分过程中总是按照比6小1,小2,小3,小k,的顺序来依次排列它的划分,第一列 阅读全文

Permutation&Combination递归实现

2012-07-28 21:20 by coodoing, 802 阅读, 0 推荐, 收藏, 编辑
摘要:(1)关于字符串排列的问题输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则输出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。解题思路:固定第一个字符a,求后面两个字符bc的排列。当两个字符bc的排列求好之后,我们把第一个字符a和后面的b交换,得到bac,接着我们固定第一个字符b,求后面两个字符ac的排列。现在是把c放到第一位置的时候了。记住前面我们已经把原先的第一个字符a和后面的b做了交换,为了保证这次c仍然是和原先处在第一位置的a交换,我们在拿c和第一个字符交换之前,先要把b和a交换回来。在交换b和a之后,再拿c和处在第一位置 阅读全文

DFS应用:SCC

2012-07-12 18:31 by coodoing, 576 阅读, 0 推荐, 收藏, 编辑
摘要:本文利用Kosaraju’s Two-Pass Algorithm 解决强连通子图问题。 Kosaraju算法是求解有向图强连通分量(strong connected component)的三个著名算法之一(另两个算法为Tarjan和Gabow),能在线性时间求解出一个图的强分量。三种算法具体的差别可参考:http://www.cppblog.com/koson/archive/2010/04/27/113694.html 什么是强连通分量?在这之前先定义一个强连通性(strong connectivity)的概念:有向图中,如果一个顶点s到t有一条路径,t到s也有一条路径,即s与t互相可达. 阅读全文

图的DFS遍历

2012-07-12 17:39 by coodoing, 732 阅读, 0 推荐, 收藏, 编辑
摘要:深度优先搜索(Depth-First Search—DFS)是指按照深度方向搜索,它类似于树的先根遍历,是树的先根遍历的推广 深度优先搜索连通子图的基本思想是: 假设图G初态为所有顶点未被访问(visited[i]=false),从G中任选一顶点vi :从该顶点vi出发,首先访问vi,,置visited [vi ]=true;然后依次搜索vi的每一个邻接点vj ;若vj未被访问过,则以vj为新的初始出发点,重复1;若vj已被访问过,则返回到vi另一个邻接点,重复3如果经过1、2、3后,图中仍有未被访问的顶点,再从中任选一顶点,重复1、2、3,直至所有顶点都被访问过,遍历结束。以无向连通图为例. 阅读全文

图的邻接表实现

2012-07-11 22:49 by coodoing, 1301 阅读, 0 推荐, 收藏, 编辑
摘要:邻接表相关介绍 邻接表(Adjacency List)是图的一种链式存储方式。在邻接表中,对每个顶点(即表头节点)建立一个单链表,第i个单链表中节点表示依附于顶点vi 的边(对有向图而言,是以顶点vi为尾的弧)。所以在邻接表中,除了节点外,还有表头节点。 数据结构定义如下节点和表头节点的结构定义如下具体数据结构定义如下:ArcNode表示表节点,VNode表示头节点,ALGraph表示图class ArcNode { int vex; //弧指向的顶点的位置 ArcNode next; //指向下一条弧的指针 String info; //该弧相关信息 double ... 阅读全文

贪心算法之哈夫曼编码

2012-07-10 15:48 by coodoing, 8364 阅读, 0 推荐, 收藏, 编辑
摘要:哈夫曼编码是广泛地用于数据文件压缩的十分有效的编码方法。其压缩率通常在20%~90%之间。哈夫曼编码算法用字符在文件中出现的频率表来建立一个用0,1串表示各字符的最优表示方式。给出现频率高的字符较短的编码,出现频率较低的字符以较长的编码,可以大大缩短总码长。定长码:3*(45+13+12+16+9+5) = 300 千位变长码:1*45+3*13+3*12+3*16+4*9+4*5 = 224 千位1、前缀码对每一个字符规定一个0,1串作为其代码,并要求任一字符的代码都不是其它字符代码的前缀。这种编码称为前缀码。编码的前缀性质可以使译码方法非常简单。表示最优前缀码的二叉树总是一棵完全二叉树,. 阅读全文

JAVA-二叉线索树(Threaded binary tree)

2012-07-10 11:27 by coodoing, 1331 阅读, 0 推荐, 收藏, 编辑
摘要:二叉线索树(Threaded binary tree)基础知识二叉树是一种非线性结构,对二叉树进行遍历时,实际上那个是将二叉树这种非线性结构按某种需要转化成线性序列,但每次遍历二叉树时,都要用递归对其进行遍历,当二叉树的节点较多时,这样的效率是很低的。所以我们有没有办法把我们遍历的二叉树保存,方便以后遍历呢?在一棵只有n个结点的二叉树中,假设有n个结点,那么就有2n个指针域,因为二叉树只用到了其中的n-1个结点,所以只要利用剩下的n+1个节点,我们就能把中需遍历时所得到的中序二叉树保存下来,以便下次访问。中序二叉树的指针域有两种类型:一是用于链接二叉树本身;二是用于链接中序遍历序列。这类型的指 阅读全文