排序算法

几种排序算法的比较

 

直接插入排序

算法

插入排序由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];
        }
    }
}

 

posted @ 2017-03-28 10:19  且听风吟-wuchao  阅读(175)  评论(0编辑  收藏  举报