在内部排序算法中比较常用的排序算法应该算快速排序了。时间复杂度为N*lgN。然而快排算法的实现又有很多的版本。下面总结一下。
一、常规快排算法(以数组中一个元素作为旋转点)
// quicksort the subarray from a[lo] to a[hi]
private static void sort(Comparable[] a, int lo, int hi) {
if (hi <= lo) return;
int j = partition(a, lo, hi);
sort(a, lo, j-1);
sort(a, j+1, hi);
assert isSorted(a, lo, hi);
}
划分方法如下
// partition the subarray a[lo .. hi] by returning an index j
// so that a[lo .. j-1] <= a[j] <= a[j+1 .. hi]
private static int partition(Comparable[] a, int lo, int hi) {
int i = lo;
int j = hi + 1;
Comparable v = a[lo];
while (true) {
// find item on lo to swap
while (less(a[++i], v))
if (i == hi) break;
// find item on hi to swap
while (less(v, a[--j]))
if (j == lo) break; // redundant since a[lo] acts as sentinel
// check if pointers cross
if (i >= j) break;
exch(a, i, j);
}
// put v = a[j] into position
exch(a, lo, j);
// with a[lo .. j-1] <= a[j] <= a[j+1 .. hi]
return j;
}
其中,划分方法中的选择点的选择对算法的性能影响比较大。基于这个原因,有些改进算法,有的选择数组的中间项作为旋转点,但这样的改进等于没改进,因为选第一个和选中间那个效果是一样的,觉得是一种自欺欺人的方法。有一种比较合理的改进是,先用shuffle算法(洗牌算法)对原始数组进行处理,使得数组中的各项值均匀地随机排列,然后再用常规快排算法。
// quicksort the array
public static void sort(Comparable[] a) {
StdRandom.shuffle(a);
sort(a, 0, a.length - 1);
}
// quicksort the subarray from a[lo] to a[hi]
private static void sort(Comparable[] a, int lo, int hi) {
if (hi <= lo) return;
int j = partition(a, lo, hi);
sort(a, lo, j-1);
sort(a, j+1, hi);
assert isSorted(a, lo, hi);
}
还有一种改进旋转点的方法是采用三者取中划分。就是从数组选出三个元素,使用这三个元素的中间值的那个元素作为划分点。
二、三路划分快速排序算法。改算法将数组划分为3部分,比划分元素小的元素,与划分元素相等的元素,比划分元素大的元素。然后递归处理比划分元素小的元素和比划分元素大的元素。
// quicksort the subarray a[lo .. hi] using 3-way partitioning
private static void sort(Comparable[] a, int lo, int hi) {
if (hi <= lo) return;
int lt = lo, gt = hi;
Comparable v = a[lo];
int i = lo;
while (i <= gt) {
int cmp = a[i].compareTo(v);
if (cmp < 0) exch(a, lt++, i++);
else if (cmp > 0) exch(a, i, gt--);
else i++;
}
// a[lo..lt-1] < v = a[lt..gt] < a[gt+1..hi].
sort(a, lo, lt-1);
sort(a, gt+1, hi);
assert isSorted(a, lo, hi);
}
三、快排的综合改进版。当递归调用快速排序算法时,处理的数组的规模会越来越小,当小的一定程度时,采用比较简单的插入排序算法会比快速排序更有优势;同时采用前面讲到的三者取中划分方法和三路快排。
private static void sort(Comparable[] a, int lo, int hi) {
int N = hi - lo + 1;
// cutoff to insertion sort
if (N <= CUTOFF) {
insertionSort(a, lo, hi);
return;
}
// use median-of-3 as partitioning element
else if (N <= 40) {
int m = median3(a, lo, lo + N/2, hi);
exch(a, m, lo);
}
// use Tukey ninther as partitioning element
else {
int eps = N/8;
int mid = lo + N/2;
int m1 = median3(a, lo, lo + eps, lo + eps + eps);
int m2 = median3(a, mid - eps, mid, mid + eps);
int m3 = median3(a, hi - eps - eps, hi - eps, hi);
int ninther = median3(a, m1, m2, m3);
exch(a, ninther, lo);
}
// Bentley-McIlroy 3-way partitioning
int i = lo, j = hi+1;
int p = lo, q = hi+1;
while (true) {
Comparable v = a[lo];
while (less(a[++i], v))
if (i == hi) break;
while (less(v, a[--j]))
if (j == lo) break;
if (i >= j) break;
exch(a, i, j);
if (eq(a[i], v)) exch(a, ++p, i);
if (eq(a[j], v)) exch(a, --q, j);
}
exch(a, lo, j);
i = j + 1;
j = j - 1;
for (int k = lo+1; k <= p; k++) exch(a, k, j--);
for (int k = hi ; k >= q; k--) exch(a, k, i++);
sort(a, lo, j);
sort(a, i, hi);
}
// sort from a[lo] to a[hi] using insertion sort
private static void insertionSort(Comparable[] a, int lo, int hi) {
for (int i = lo; i <= hi; i++)
for (int j = i; j > lo && less(a[j], a[j-1]); j--)
exch(a, j, j-1);
}
// return the index of the median element among a[i], a[j], and a[k]
private static int median3(Comparable[] a, int i, int j, int k) {
return (less(a[i], a[j]) ?
(less(a[j], a[k]) ? j : less(a[i], a[k]) ? k : i) :
(less(a[k], a[j]) ? j : less(a[k], a[i]) ? k : i));
}
分享到:
相关推荐
此为一个利用Java语言编写的排序分析程序,程序中统计了各种排序算法(冒泡排序、选择排序、插入排序、希尔排序、快速排序、堆排序、归并排序、基数排序)的分析,ppt中包含各种排序算法的分析,附上动画演示(来自...
各种排序算法(插入排序、冒泡排序、二叉树排序、二路归并排序,选择排序、希尔排序、快速排序、堆排序)的简单排序
计算机专业以及数学专业的人们,都会学计算机快速编程算法,而算法又有好多种,而这里就是将各种算法讲解透彻,对比说明,是非常值得一看的
各种排序算法的实现,桶排序,快速排序、归并排序、希尔排序等
各种排序算法大全排序 各种排序算法大全全是c语言的,运行效率高。
采用速度快的快速排序节省时间,数据结构中快速排序需要时间相对时很短的。
实现合并排序,插入排序,希尔排序,快速排序,冒泡排序,桶排序算法的java实现。
用Java语言实现的各种排序,包括插入排序、冒泡排序、选择排序、Shell排序、快速排序、归并排序、堆排序、SortUtil等。 插入排序: package org.rut.util.algorithm.support; import org.rut.util.algorithm....
本程序实现各种排序算法并分析与比较 直接插入排序, SHELL排序,冒泡排序,快速排序,简单选择排序,堆排序,归并排序
排序算法是一种基本并且常用的算法。... 第四部分是我送给大家的一个餐后的甜点——一个基于模板的通用快速排序。由于是模板函数 可以对任何数据类型排序(抱歉,里面使用了一些论坛专家的呢称)。
C++实现的各种排序算法的实验(源代码+实验报告),包括快速排序,堆排序等的实现
采用c++描述了各种排序算法,包括选择排序 冒泡排序 插入排序 基数排序 快速排序 归并排序 。实验内容 1、创建排序类。 2、提供操作:选择排序、冒泡排序、插入排序、*基数排序、*快速排序、*归并排序。 3、*能够...
关于c++的各种排序算法,快速,归并,选择,桶排,冒泡,插入等
该程序包括常用的排序算法代码:直接插入排序,二分插入排序,...同时通过产生一个指定个数的随机数组,调用各种不同排序算法对其进行排序,记录各种算法的耗时,写入一个文本文件进行对比分析各种排序算法的时间性能。
各种排序算法合集,可编译, 包括冒泡,选择,快速,归并,基数,桶排序,堆排序各种算法
使用简单数组实现下面各种排序算法的功能,并进行比较, 排序算法如下: a) 插入排序; b) 希尔排序; c) 冒泡排序; d) 快速排序; e) 简单选择排序; f) 堆排序; g) 归并排序; h) 基数排序(选作); i) 其他; ...
随机产生n个1~99的正整数序列,分别采用直接插入排序、折半插入排序、希尔排序、冒泡排序、快速排序、直接选择排序、堆排序和二路归并排序对其进行递增排序
常见的排序算法进行整理,包括:插入排序、选择排序、冒泡排序、快速排序、堆排序、归并排序、希尔排序、二叉树排序、计数 排序、桶排序、基数排序。
排序算法 冒泡 、快速、直接插入、堆排序、希尔排序、归并排序
各种基本排序算法:冒泡排序、计数排序、堆排序、插入排序、归并排序递归版与非递归版、快速排序递归版与非递归版、选择排序、随机选择递归版与非递归版。