前言
唠叨一下:半夜实在睡不着,起床敲了一个 快速排序 的代码,讲真这是大学第一次亲手敲出这个代码,代码使用Java实现,但算法和数据结构一样,其本身和编程语言是没有关系的。
简单介绍
算法思想
基于分治的思想,是 冒泡排序 的改进型。
1.首先在数组中选择一个基准点
(该基准点的选取可能影响快速排序的效率,后面讲解选取的方法);
2.然后分别从数组的两端扫描数组,设两个指示标志
(low 指向起始位置,high 指向末尾);
3.首先从后半部分开始,如果发现有元素比该基准点的值小,就交换low和high位置的值,然后从前半部分开始搜索,发现有元素大于基准点的值,就交换low和high位置的值,如此往复循环,直到 low>=high,然后把基准点的值放到high这个位置。
一次排序就完成了。
以后采用递归的方式分别对前半部分和后半部分排序,当前半部分和后半部分均有序时该数组就自然有序了。
算法特点
快速排序的时间主要耗费在划分操作上,对长度为k的区间进行划分,共需k-1次关键字的比较;
最坏情况
每次划分选取的基准都是当前无序区中关键字最小(或最大)的记录,划分的结果是基准左边的子区间为空(或右边的子区间为空),而划分所得的另一个非空的子区间中记录数目,仅仅比划分前的无序区中记录个数减少一个。时间复杂度为O(n2);
最好情况
每次划分所取的基准都是当前无序区的"中值"记录,划分的结果是基准的左、右两个无序子区间的长度大致相等。总的关键字比较次数:O(nlogn);
尽管快速排序的最坏时间为O(n2),但就平均性能而言,它是基于关键字比较的内部排序算法中速度最快者,快速排序亦因此而得名。它的平均时间复杂度为O(nlogn)。
源码
package nono.sort;
import java.util.Arrays;
/**
* 快速排序
*
* @author Nonoas
*/
public class QuikSorter {
/**
* 快速排序
*
* @param arry 进行排序的数组
* @param low 数组的起始下标
* @param high 数组的终止下标
*/
public static void quikSort(int[] arry, int low, int high) {
if (low >= high)
return; // 递归出口,当起始下标大于等于终止下标时,结束排序
int temp = arry[low]; // 临时变量用于保存参考元素的值
int left = low; // 左端指针
int rigth = high; // 右端指针
while (left < rigth) {// 当左标小于右标时执行循环
while (left < rigth && arry[rigth] > temp)
rigth--; // 从后往前搜索小于中间值的数
if (left < rigth)
arry[left++] = arry[rigth]; // 将小于中间值的数移到左边,这里不用交换值,直接覆盖即可
while (left < rigth && arry[left] < temp)
left++; // 从前往后搜索大于中间值的数
if (left < rigth)
arry[rigth--] = arry[left]; // 将大于中间值的数移到右边,这里不用交换值,直接覆盖即可
}
// 循环体结束,说明左标与右标相遇
arry[left] = temp;// 将参考值赋给当前位置的数,此时左边的数都小于temp,右边的数都大于temp
quikSort(arry, low, left - 1);// 递归排序左部
quikSort(arry, rigth + 1, high);// 递归排序右部
}
public static void main(String[] args) {
int[] a = { 8, 7, 6, 3, 5, 4 };
System.out.println("排序前:" + Arrays.toString(a));
QuikSorter.quikSort(a, 0, a.length - 1);
System.out.println("排序后:" + Arrays.toString(a));
}
}