内部排序算法学习总结

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

radixSort(array, low, mid, bit); radixSort(array, mid+1, high, bit); } 基数排序的时间复杂度和快速排序一样,但是据说比快速排序要快一点。
Sorting By Selection 选择排序
排序算法中另外一个比较重要的方式就是选择,通过不断的选择来求得最终有序的序列,最简单
} //assume array h stores the group number Shell(array A, int N, array h, int g_num) {
for(i = 1; i <= g_num; i++) ShellSort(A, N, h[i]);
} shell 排序最关键的就是分组数目的选取,我们可以想象,当分组为 N 的时候,该算法就退化成
for(i = 1; i < h; i++) for(j = i + h; j < N; j+=h) pivote = A[j]; for(k = j - h; k >0; k-=h) if (A[k] > A[j]) A[k+h] = A[k]; else break; A[k+h] = pivote;
mid = partition(array, low, high); quicksort(array, low, mid -1); quicksort(array, mid+1, high); } 快速排序最坏情况下的时间复杂度需要 O(n^2),但是一般情况下,快速排序的时间复杂度为 O (n*log2n),在比较排序中,快速排序是性能最好的一种排序方式,另外也可以对其进行改进, 当划分后的子数组个数小于 8 个的时候,可以使用直接排序,而不必再进行划分了。 Radix Exchanging sorting 基数交换排序
来进行划分,左边的数都小于这个值,右边的数都大于这个值,然后对左边和右边的数继续划分。
partition(array, low, high) {
if (array == NULL) return -1;
if (low >= high) return low;
pivote = array[low]; i = low; j = high; while( true) {
了直接插入排序算法。
理论上证明当数组 hi = 2^i -1 的时候,算法时间为 N^(3/2)
Sortin来自百度文库 by Exchanging
交换排序的基本思想是交互一对 out of order 的数,直到待排序列中没有 out of order 的对
为止 直接插入排序也可以看成是交换排序:对于 A[i]每次和它的邻居比较,如果不是 order,则交
对数据进行部分排序时,通常使用该算法。 Binary Insertion and two-way Insertion 对于第 i 个数,因为前 i-1 个数都是有序的了,我们需要找到合适的位置来将 i 插入进去,因此 我们可以使用二分查找的方式在 i-1 中寻找合适的位置,例如对于 i=64,则比较 A[32],如果 大于 A[64]则比较 A[16]否则比较 A[48],这样查找相应的插入位置只需要 log2N 次比较。但是即使我们找到了合适的插入位置, 我们仍然需要将后面的记录往后挪一个位置,来腾出空间给要插入的数 A[i],因此总的时间复
pivote = A[i]; for( j = i-1; j >= 1; j--)
if (A[j] > A[i]) A[j+1] = A[j];
else break;
A[j + 1] = pivote;
该算法最坏情况就是输入数组为逆序的情况,则比较和移动的次数为 1+2+...+N-1= N*(N-1) /2 O(n^2) 平均下来,对于 i,每次比较和移动次数为 i/2,则总的次数为 N*(N-1)/4 约为(N^2)/4 该算法在 N 不是很大,且数组基本有序的情况下,可以获得最好的效率,因此很多排序算法在
for(j = 1; j <= N-i; j++) {
if(A[j] > A[j+1]) {
exchange(A[j], A[j+1); } } } 此处给出的是最简单的实现方法,显然这个方法还有很多改进的地方,比如说不一定非要循环 N -1 次,如果某次循环的时候发现没有进行交换了,则表明序列已经是顺序的了,可以跳出,比 如每次也不一定非要循环到 N-i 的地方,而是循环到上次最后一次做 exchange 操作的下标处 就可以了,因为后面没有再进行 exchange,则表明后面已经是有序的了。 exchange_bound = N-1; is_exchange = 0; for(i = 1; i < N; i++) { for(j = 1; j <= exchange_bound; j++) { if(A[j] > A[j+1]) {
exchange(A[j], A[j+1); is_exchage++; exchange_bound = j; } } if (is_exchange == 0) break; } QuickSort 快速排序
快速排序的基本思想是通过 partition,partition 是从待排序列中选取某个值,然后按照这个值
杂度并没有降低。 Shell Sorting 希尔排序 如果某个排序算法,一次只移动一个位置的话,那么其时间复杂度是 O(n),因此如果我们要提
高效率的话,那么每次比较不能只是移动一个位置,而应该移动尽可能多的位置。希尔排序就是 这样的算法,也称为 Diminishing increment sortion 例如对于 16 条记录,我们将其分为 8 组(A1,A9) (A2, A10)...(A8, A16)分别对每一组进行
exchange(array[i], array[j]; else {
return j; } } } radixSort(array, low, high, bit) { if(array == NULL || low >= high)
return; mid = radixPartition(array, low, high, bit); bit = bit >> 1;
换,直到交换到合适的位置为止。
因此,插入、交换、选择排序之间并没有严格的区分。 交换排序主要有四种方式:Exchange selection(bubble sort 冒泡法)merge exchage(归 并排序) partition exchange(快速排序) radix exchange(基数排序) bubble sort 最显然的方法就是 A1 和 A2 比较,如果 A1 大,则交换,继续比较 A2 A3, A3 A4,一次下 来之后,最大的元素则在最右边。接下来对 N-1 个元素继续这样操作 for(i = 1; i < N; i++) {
另一种实现方法是一头查找
partition(array, low, high) {
if (array == NULL) return -1;
if (low >= high) return low;
i = low - 1; j = low; while(j < high) {
if (array[j] < array[high]) {
的方法一般是:
1、从序列中找到最小的数,输出,将这个为止置为无穷大;
2、继续步骤 1
3、直到 N 个记录都已经选取出来了
选择排序要求所有待排列的数据都是已知的,其最终结果是一次一次累计产生出来的,而上面提
到的其它排序方式,在排序中间我们始终是没有办法得到一个有序的序列,直到排序完成之后才
最终得到有序的序列,而选择排序则排序过程中生成的结果都已经是有序的了。
count[A[i] += 1; 3 for (i = min+1; i <= max; i++)
count[i] = count[i] + count[i-1]; 该方法不需要进行任何比较操作,有点像后面要提到的 Radix Sorting
Sorting by Insertion
插入排序,该算法的基本思想和我们打扑克牌的时候插牌的方法类似,当我们要接到第 i 个牌的 时候,我们手上的 i-1 个牌已经是有序的了,那么我们找到合适的位置,把第 i 张牌插进去。 Straight insertion 直接插入 for(i = 2; i <= N; i++)
一位
这样最终就得到了有序的序列了。 radixPartition(array, low, high, bit) {
if (array == NULL) return -1;
if (low >= high) return low;
i = low; j = high; while(true) {
while(array[j] &b && i < j) j--; while(!(array[i] &b) && i < j) i++; if (i < j)
基数交换排序是利用每个数的二进制表示来进行排序的,同一般的比较不同,它是通过二进制相 应的位为 0 或 1 来比较。它有点类似与快速排序,其过程是: 1、将序列按照最高位来划分,左边的数该位都为 0,右边的数该位都为 1. 2、继续对最高位为 0 的新序列按照下一位为 0 还是 1 继续划分,右边序列也一样,直到最后
i++; exchage(array[i], array[j]; } j++; } exchange(array[i+1], array[high]); return i+1; }
quicksort(array, low, high) {
if(array == NULL || low >= high) return;
排序 之后分为 4 组(A1, A5, A9, A 13)...(A4, A8, A12, A16)分别对每一组进行排序 然后分为 2 组,分别对每一组排序
最后对整个数组排序
对于每一个小组的排序可以使用直接插入排序。对于组的选取可以根据数据的不同来选取,但是 最后一定是 1,例如此处是 8 4 2 1 当然也可以划分为 7 5 3 1 等等。 //h is the group number ShellSort(array A, int N, int h) {
while(array[j] >= pivote && i < j) j--; while(array[i] <= pivote && i < j) i++; if (i < j)
exchange(array[i], array[j]; else {
exchange(array[low], array[j]); return j; } } }
Sorting algorithm
Sorting by Counting
通过计数的方式来排序 Comparison Counting 假设对 A[1...N]数组进行排序,用一个数组 count[1...N]来统计每个数应该出现的位置, 1 Set count[1...N] = 0; 2 for i = N; i > 1; i-2 for j = i-1; j >=1; j--;
if A[j] > A[i] count[j]++;
else count[i]++;
例如对于数组 2 3 4 1 5 第一次统计后 count 为:0 0 0 0 4 第二次统计后 count 为:1 1 1 0 4 第三次统计后 count 为:1 1 3 0 4 第四次统计后 count 为:1 2 3 0 4 最后的 count 则对应了其出现的下标值 显然该算法时间复杂度为 O(n^2)空间复杂度为 O(n),很烂的算法,没啥用处,不过不需要 移动记录 Distribution Counting 该方法是对上面方法的改进,假设数组 A 的最大值和最小值分别为 min max,设置一个 coun t[min...max]数组来统计每个数应该出现的位置 1 Set count[min...max] = 0; 2 for( i = 1; i <= N; i++)
相关文档
最新文档