本文已参与「新人创作礼」活动,一起开启掘金创作之路。
排序算法是软件开发中非常重要的一环。本期就来讨论关于算法在面试中会遇到的一些问题,其中包含个人一些理解,由于本人学识有限,难免会有纰漏之处,还望读者能多多包涵。
上一期我们讲了归并排序和插入排序。本期继续讲解其他的排序算法。
快速排序
与上一期的归并排序一样,快速排序又是一种分而治之思想在排序算法上的典型应用。本质上来看,快速排序应该算是在冒泡排序基础上的递归分治法。快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。
快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下,排序 n 个项目要 次比较。在最坏状况下则需要 次比较,但这种状况并不常见。事实上,快速排序通常明显比其他 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。它是处理大数据最快的排序算法之一。
文字描述过程就是(从小到大排序):在数组中随机选一个数(默认数组首个元素),数组中小于等于此数的放在左边,大于此数的放在右边,再对数组两边递归调用快速排序,重复这个过程。动图如下:
Java实现如下:
public static void quickSort(int[] a, int left, int right) {
int i,j,t,temp;
if(left>right) //(递归过程先写结束条件)
return ;
temp=a[left]; //temp中存的就是基准数
i=left;
j=right;
while(i!=j)
{
//顺序很重要,要先从右边开始找(最后交换基准时换过去的数要保证比基准小,因为基准
//选取数组第一个数,在小数堆中)
while(a[j]>=temp && i<j)
j--;
//再找右边的
while(a[i]<=temp && i<j)
i++;
//交换两个数在数组中的位置
if(i<j)
{
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
//最终将基准数归位 (之前已经temp=a[left]过了,交换只需要再进行两步)
a[left]=a[i];
a[i]=temp;
quickSort(a,left,i-1);//继续处理左边的,这里是一个递归的过程
quickSort(a,i+1,right);//继续处理右边的 ,这里是一个递归的过程
}
public static void main(String[] args) throws IOException {
int[] array= {5,0,1,2,81,-4,21,9,11};
quickSort(array, 0, array.length-1);
//输出
for (int j = 0; j < array.length; j++) {
System.out.print(array[j]+" ");
}
}
总结一下就是先把一个大数组通过第一个元素将之分割成2个小的数组,并且以该轴点为界,小于它的在左边,大于它的在右边,然后递归对2个小数组执行步骤1、2操作,直到不能再分割。
希尔排序
希尔排序(Shell Sort)是插入排序的一种,它是针对直接插入排序算法的改进。希尔排序步长从大到小调整,第一次循环后面元素逐个和前面元素按间隔步长进行比较并交换,直至步长为1,步长选择是关键。
希尔排序时间复杂度是 ,空间复杂度为常数阶 。希尔排序没有时间复杂度为 的快速排序算法快 ,因此对中等大小规模表现良好,但对规模非常大的数据排序不是最优选择,总之比一般 复杂度的算法快得多。
文字描述其过程:为了加快速度,交换不相邻的元素对数组的局部进行排序,并最终用插入排序将局部有序的数组排序。在此我们选择增量 ,缩小增量以 的方式,用序列 来表示。
Java实现如下:
public static void ShellSort(int[] array) {
int n=array.length,i,j,temp;
int gap=n;
do{
gap=gap/2;
for( i=gap;i<n;i++ )
{
if(array[i]<array[i-gap])
{
temp=array[i];
for( j=i-gap; j>=0&&array[j]>temp; j-=gap)
{
array[j+gap]=array[j];
}
array[j+gap]=temp;
}
}
}while(gap>1);
//输出
for (int k = 0; k < array.length; k++) {
System.out.print(array[k]+" ");
}
}
public static void main(String[] args) throws IOException {
int[] array= {5,0,1,2,81,-4,21,9,11};
ShellSort(array);
}
以上就是希尔排序,它利用分组粗调的方式减少了直接插入排序的工作量,使得算法的平均时间复杂度低于。