排序算法
几种排序算法的比较

直接插入排序
算法
插入排序由N-1趟排序组成。对于p=1到N-1趟,插入排序保证从位置0到位置p上的元素为已排序状态。
时间复杂度
最差的情况下,第p次排序,需要的比较次数是p次,则总的比较次数为1+2+3+……+N-1=O(N^2)。
平均情况,O(N^2)
最好情况,O(N)
空间复杂度
每次比较都是两个元素的交换,所以空间复杂度为O(1)
代码示例
package sort;
import java.util.Random;
/**
* Created by wuchao on 17-3-28.
*/
public class Insert {
public static void main(String[] args){
int[] array = getData(100);
printArray(insertSort(array));
}
//插入排序
public static int[] insertSort(int[] array){
int N = array.length;
int j;
for(int i=1 ; i<N ; i++){
//array[0,(i-1)]是已经排序的,现在判断array[i]插在哪
int tmp = array[i];
for(j=i;j>0&&array[j-1]<tmp;j--){
array[j]=array[j-1];
}
array[j]=tmp;
}
return array;
}
//返回一个长度为N的随机数组,元素大小[0,N]
public static int[] getData(int N){
int[] array = new int[N];
if(N<=0) return array;
Random random = new Random();
for(int i=0;i<N;i++){
array[i]= random.nextInt(N);
}
return array;
}
//打印数组
public static void printArray(int[] array){
System.out.print("[");
for(int i=0;i<array.length;i++){
System.out.print(array[i]+",");
}
System.out.print("]");
System.out.println();
}
}
Shell排序
算法
基于插入排序,但它通过比较相邻一定间隔的元素来工作。各趟比较所用的距离随着算法进行而减少,直到只比较相邻元素(间隔为1)的最后一趟为止。
时间复杂度
最差情况,O(N^2)
平均情况,O(N^1.3)
最好情况,O(N)
空间复杂度
每次比较都是两个元素的交换,所以空间复杂度为O(1)
代码示例
package sort;
import java.util.Random;
/**
* Created by wuchao on 17-3-28.
*/
public class Shell {
public static void main(String[] args){
int[] array = getData(100);
printArray(array);
printArray(shellSort(array));
}
//shell排序
public static int[] shellSort(int[] array){
int N = array.length;
int j;
//比较间隔gap由N/2逐步递减为1
for(int gap = N/2;gap>0;gap/=2){
for(int i=gap;i<N;i++){
int tmp = array[i];
for(j=i;j>=gap&&array[j-gap]>tmp;j -=gap){
array[j]=array[j-gap];
}
array[j]=tmp;
}
}
return array;
}
//返回一个长度为N的随机数组,元素大小[0,N]
public static int[] getData(int N){
int[] array = new int[N];
if(N<=0) return array;
Random random = new Random();
for(int i=0;i<N;i++){
array[i]= random.nextInt(N);
}
return array;
}
//打印数组
public static void printArray(int[] array){
System.out.print("[");
for(int i=0;i<array.length;i++){
System.out.print(array[i]+",");
}
System.out.print("]");
System.out.println();
}
}
快速排序
算法
在数组中选取一个元素,比如选第一个元素,经过一定的方法,使得数组重排,结果为比该元素小的元素都在该元素的左侧,比该元素大的元素都在该元素的右侧。
重排方法如下:
数组为array=[5 2 7 3 9 4 0 1]
(1)选取第一个元素为基x=5,相当于在array[i=0]处挖了一个坑,元素被取走了。
(2)建立索引i=0,j=6(i指向数组头部,j指向数组尾部),此时i=0指向数组的那个坑
(3)从尾部开始查找第一个小于x的值(查找范围为(i,j] ),然后令j指向该元素,并将该元素赋值数组的那个坑并i++(i指向的那个坑),此时j指向数组的新的坑
(4)从头部开始查找第一个大于x的值(查找范围[i,j) ),然后令i指向该元素,并将该元素复制给数组的那个坑并j--(j指向的坑),此时i指向数组新的坑
(5)直到i<j不成立时有i=j,这时坑的位置是i或j,用基x填这个坑,array[i]=x;
数组[5 2 7 3 9 4 0 1]排序细节如下
[ _ 2 7 3 9 4 0 1 ] x=5 i=0,j=7
[ 1 2 7 3 9 4 0 _ ] x=5 i=0,j=7
[ 1 2 _ 3 9 4 0 7 ] x=5 i=2,j=7
[ 1 2 0 3 9 4 _ 7 ] x=5 i=2,j=6
[ 1 2 0 3 _ 4 9 7 ] x=5 i=4,j=6
[ 1 2 0 3 4 _ 9 7 ] x=5 i=4,j=5
[ 1 2 0 3 4 5 9 7 ] x=5 i=5,j=5
时间复杂度
最差情况:O(n^2)
平均情况:O(nlogn)
空间复杂度
O(nlogn)
代码
代码如下
/**
* Created by wuchao on 17-3-29.
*/
import java.util.*;
public class test {
public static int array[] = {5,2,7,1,2,9,3};
public static void main(String[] args) {
quickSort(array,0,6);
System.out.println(Arrays.toString(array));
}
public static void quickSort(int[] array,int l,int r){
if(l<r){
int i=l,j=r;
int value = array[l];
while(i<j){
while(i<j && array[j]>value){
j--;
}
if(i<j){
array[i]=array[j];
i++;
}
while(i<j&&array[i]<value){
i++;
}
if(i<j){
array[j]=array[i];
j--;
}
}
array[i]=value;
quickSort(array,l,i-1);
quickSort(array,i+1,r);
}
}
}
归并排序
算法
这个算法的基本操作是合并两个已排序的表。在这里合并函数的几个参数a,tmpArray,leftPos,rightPos,rightEnd分别表示待排序数组、临时数组、左边起点、右边起点、右边终点。
时间复杂度
最差和最好情况下都是O(nlogn)
空间复杂度
O(1)
代码
import java.util.Arrays;
/**
* 归并排序
*/
public class Merge {
public static void main(String[] args){
int[] array={2,7,3,77,3,56,3,74,2,5,12,74,34,75};
mergeSort(array);
System.out.println(Arrays.toString(array));
}
//排序算法入口
public static void mergeSort(int[] a){
int[] tmpArray = new int[a.length];
mergeSort(a,tmpArray,0,a.length-1);
}
//分治并合并
private static void mergeSort(int[] a,int[] tmpArray,int left,int right){
if(left<right){
int middle = (left+right)/2;
mergeSort(a,tmpArray,left,middle);
mergeSort(a,tmpArray,middle+1,right);
merge(a,tmpArray,left,middle+1,right);
}
}
//合并
//此时数组a的[leftPos]-[rightPos-1]和[rightPos]-[rightEnd]已经是两个排序的子数组
//下面函数负责将这两个部分合并,并放入放到tmpArray数组的[leftPos]-[rightEnd]位置
//最后将tmpArray对应部分拷贝回原来数组
private static void merge(int[] a,int[] tmpArray,int leftPos,int rightPos,int rightEnd){
int leftEnd = rightPos-1;
int tmpPos = leftPos;
int numElements = rightEnd-leftPos+1;
while(leftPos<=leftEnd && rightPos<=rightEnd){
if(a[leftPos]<=a[rightPos]){
tmpArray[tmpPos++]=a[leftPos++];
}else{
tmpArray[tmpPos++]=a[rightPos++];
}
}
while(leftPos<=leftEnd){
tmpArray[tmpPos++]=a[leftPos++];
}
while(rightPos<=rightEnd){
tmpArray[tmpPos++]=a[rightPos++];
}
for(int i=0;i<numElements;i++,rightEnd--){
a[rightEnd]=tmpArray[rightEnd];
}
}
}

浙公网安备 33010602011771号