归并排序
归并排序是将两个较小的有序数组归并为一个较大的有序数组。将一个数组排序,可以先将该数组分成两半,将这两半分别排序,最后将两个有序的子序列归并。根据这种思想,人们发明了一种简单的递归排序算法,归并排序。
归并排序的步骤可以用下图的一个例子进行说明:
首先利用分割的方法将带排序的序列分割成一个个的子序列,直到每个子序列只剩一个元素(有序),再对每个子序列进行合并。具体的实现代码如下:
/*
* 归并排序
*/
public static void mergeSort(int[] A){
sort(A,0,A.length - 1);
}
/*
* 排序
*/
private static void sort(int[] A,int lo,int hi){
if(hi <= lo)
return;
int mid = lo + (hi - lo) / 2; //防止溢出
sort(A, lo, mid); //将左半边排序
sort(A, mid + 1, hi); //将右半边排序
merge(A,lo,mid,hi); //归并结果
}
/*
* 原地归并
*/
private static void merge(int[] a, int lo, int mid, int hi) {
//将两个数组归并
int i = lo,j = mid + 1;
int[] aux = new int[hi + 1];
for (int k = lo; k <= hi; k++) {//将原来的数组复制到辅助数组中
aux[k] = a[k];
}
for(int k = lo;k <= hi;k++){//归并
if(i > mid) //左边元素用尽
a[k] = aux[j++];
else if(j > hi) //右边元素用尽
a[k] = aux[i++];
else if(aux[i] > aux[j]) //右半边元素小于左半边元素,取右半边
a[k] = aux[j++];
else //左半边元素小于右半边元素,取左半边
a[k] = aux[i++];
}
}
归并排序的特点如下:
1、归并排序是一种渐进最优的基于比较排序的算法,其时间复杂度为n*lgn;
2、归并排序算法的空间复杂度与元素个数成正比;
3、归并排序算法是稳定的;
4、归并排序算法对输入的初始次序不敏感。
快速排序
快速排序是应用最广泛的的排序算法,采用递归调用对元素进行排序,是基于比较排序算法的一个著名算法。主要思想如下:
算法由以下步骤组成:
1、如果数组中只有一个元素或者没有元素则返回;
2、选择数组中的一个元素作为枢轴点;
3.将数组分为两部分,一部分大于枢轴点,一部分小于枢轴点;
4、对两部分数组递归调用该方法。
算法实现代码如下:
public class Quicksort {
public static void quickSort(int[] A){
sort(A,0,A.length - 1);
}
private static void sort(int[] A,int lo,int hi){
if(hi <= lo) //只有一个元素或者数组为空,则直接返回
return;
int pivot = partition(A,lo,hi);//切分数组
sort(A,lo,pivot - 1);//对左半部分排序
sort(A,pivot+1,hi);//对右半部分排序
}
/*
* 对数组进行切分
*/
private static int partition(int[] a, int lo, int hi) {
int left = lo,right = hi+1;
int pivot = a[lo];//选择第一个元素为基准进行切分
while(left < right){
while(a[++left] <= pivot){
if(left == hi)
break;
}
while(a[--right] >= pivot)
if(right == lo)
break;
if(left < right)
swap(a,left,right);
}
swap(a,lo,right);
return right;
}
/*
* 交换
*/
private static void swap(int[] A,int i, int j) {
int temp = A[i];
A[i] = A[j];
A[j] = temp;
}
测试代码如下:
public static void main(String[] args) {
int[] A = {4,8,5,3,6,3,7,29,10,11};
for (int i = 0; i < A.length; i++) {
System.out.print(A[i] + " ");
}
System.out.println();
System.out.println("=========================================");
quickSort(A);
for (int i = 0; i < A.length; i++) {
System.out.print(A[i] + " ");
}
}
快速排序的特点:
1、快速排序在平均情况或者最好情况下,时间复杂度均为O(N*lgN),最坏情况下的时间复杂度为O(n*n)。
2、快速排序实现简单,适用于各种不同的输入数据,在一般应用中比其他算法快得多;
3、快速排序算法非常脆弱,在实现是要非常小心才能避免低劣的性能。