摘要:
连续写了几天排序了。。写完这个换换口味。。 之前5篇BLOG的排序算法都是基于比较的方法,这种比较排序有运行时间的下界:T(n) = Ω(nlgn)。因此需要别的算法模型来实现更快速的排序。 计数排序是一种运行时间在输入的某种假设情况下可以为Θ(n)的算法,它的过程中没有比较环节。 基本的思路就是假设输入序列中任意的元素x都满足x∈[0, k],且x和k都为整数。然后对每一元素x,都确定出序列中比...
阅读全文
posted @ 2012-01-08 19:50
LeavingQ
阅读(398)
推荐(0)
摘要:
今天是最后一个比较排序。堆排序使用了一种特殊的数据结构——堆,和C语言里的用于动态内存分配的堆不是一个概念。堆排序里的堆事实上是二叉树,因而又叫二叉堆。除了最后一层以外它是个满二叉树,最后一层剩余的数据从左边开始向右填。可以很容易看出一些性质:对于一个结点i,它的父结点索引为 floor(i/2),左子女为2i,右子女为2i + 1,在树图的右边还有它在数组中的存储方式。另外堆可以分成两类:最大堆和最小堆。最大堆的性质是对于除了根结点之外的每个结点i都有A[parent(i)] ≥ A[i],因此根结点具有最大值,左图中就是一个最大堆的例子。而最小堆的情况相反。堆排序中使用的是最大堆。另外还有
阅读全文
posted @ 2012-01-08 03:33
LeavingQ
阅读(456)
推荐(0)
摘要:
微困啊。。贴完这篇赶快睡觉去。。OK, Let’s get started…快速排序和上一篇归并排序一样也是使用DIVIDE AND CONQUER的策略。但不同之处是快排是就地排序的,也就是说在每一时刻只有常数个元素会存储在原序列之外,对于空间复杂度来说比Merge Sort要好。同样的对于基于分治法策略的算法来说都有三个基本步骤:DIVIDE:快排的分治步骤是通过一个Partition的子程序完成的,它基于一个随机选择的pivot元素将原序列分成两个部分,其中左半边的元素均小于pivot,而右半边均大于,pivot中间位置。CONQUER:与归并排序一样,CONQUER的步骤都是递归的调用
阅读全文
posted @ 2012-01-07 03:14
LeavingQ
阅读(437)
推荐(0)
摘要:
归并排序使用的是名叫DIVIDE AND CONQUER的分治策略。将一个规模为n的问题分解为a个规模为n/b的子问题,然后递归地CONQUER它们,最后将各个子问题的解COMBINE就可以得到原来规模为n的原始问题的解。归并排序是递归地处理两个规模为floor(n/2)和ceil(n/2)的数组,然后再把它们合并起来。 说实话递归一直是让我头疼的问题,脑子总是转不过弯来。对于归并排序来说,递归的...
阅读全文
posted @ 2012-01-06 00:23
LeavingQ
阅读(336)
推荐(0)
摘要:
选择排序的思路就是每第i迭代都找出序列中第i小的数,然后放在位置i上。对于一个长度为n的序列,迭代过程只要n - 1次,因为最后一个数必然是所有数中最大的。代码中用了一个min_val和min_index来保存当前迭代中找到的最小的数和它的索引,在过程中不断更新直到迭代完毕,最后和相应位置的元素交换。代码如下def selectionSort(L, n): i = 0 while(i < n - 1): min_val = L[i] min_index = i j = i ...
阅读全文
posted @ 2012-01-05 23:09
LeavingQ
阅读(129)
推荐(0)
摘要:
考试考完了,想安下心来看看算法。不知道自己在这条路上能走多远,但不管怎么样,加油吧,Leaving。首先是插入排序。它的过程算法导论比喻得很好,就如同打牌一样,手中有一些已经排好序的牌,然后从牌堆中抓一张新牌,从右到左依次比较,直到找到合适的位置放下。每次迭代的过程中,数组左边已排序好的数据长度逐渐增大,直到整个数组都排序好。左边已排好序的部分可以看成是手牌,而右边未排序的部分可以看做是牌堆,循环不变量在每次迭代过程中都得以保持。因为不想纠结于太多的语言细节,因此用Python来实现,下面是代码:def insertionSort(L, n): j = 1 while(j < n)...
阅读全文
posted @ 2012-01-05 22:47
LeavingQ
阅读(114)
推荐(0)