排序算法简介及Java实现

常见的排序算法有冒泡排序,选择排序,插入排序,希尔排序,快速排序,归并排序,堆排序。

其中,各算法的时间复杂度和空间复杂度如下表所示

算法比较
算法 时间复杂度(平均情况) 空间复杂度 时间复杂度(最坏情况) 算法稳定性
冒泡排序 N*N 1 N*N 稳定
选择排序 N*N 1 N*N 不稳定?
插入排序 N*N 1 N*N 稳定?
希尔排序 N*logN ~ N*N
快速排序 N*logN
归并排序 N*logN
堆排序 N*logN
桶排序

一、冒泡排序

1.1、简介

冒泡排序的基本思想是比较相邻的两个元素,并将较大者交换到后面。由于排序的过程中,元素按照由大到小的顺序依次上浮到其各自的位置,犹如一个一个的泡泡往上冒,因此叫做冒泡排序。

每一轮比较,可以确定一个元素的位置。共有N个数的数组,一共需要N-1轮比较完成排序。第一轮比较需要比较N-1次,第二轮需要比较N-2次,......,第N-1轮比较只需要比较1轮比较。需要比较的总的次数大约为N(N-1)/2。交换的次数不一定。

所以,冒泡排序的时间复杂度为O(N*N),空间复杂度为O(1)。

1.2、Java实现

public static void bubbleSort(int[] a) {
    int n = a.length;
    for(int i=1;i<n;i++) {
	for(int j=0;j<n-i;j++) {
	    if(a[j] > a[j+1])
		exch(a, j, j+1);
	}
    }
}

private void exch(int[] a, int i, int j) {
    int temp = a[i];
    a[i] = a[j];
    a[j] = temp;
}

二、选择排序

2.1、简介

选择排序的基本思想是:首先,找到数组中最小的那个元素,然后将其与数组中的第一个元素交换位置;然后,在剩下的元素中找到最小的元素,将其与数组中的第二个元素交换位置;如此继续下去,直到将整个数组排序。

因此,共需要N轮外循环,每一轮外循环确定一个元素的位置。N轮外循环之后,所有的元素的位置都已确定,完成排序。

在每一轮外循环中,为了确定剩下未排序元素中的最小者,需要进行一次内循环对未排序的元素进行一次遍历。第一轮外循环时,内循环中需要遍历的数量为N-1;第二轮外循环时,内循环中需要遍历的数量为N-2;一直到第N轮外循环时,内循环中需要遍历的数量为0。

因此,选择排序需要大约0+1+2+3+......+(N-1) = N*N/2次比较及N次交换,其时间复杂度为平方级别,O(N*N),空间复杂度为O(1)。

另外,由于选择排序还有两个特点:

1、运行时间与输入无关。因为无论输入数据是何种顺序,选择排序每一轮都会进行一次遍历以未排序数据中的选出最大者。

2、数据移动是最少的。只需要N次交换,与数组大小成线性关系(其他算法都是线性对数或平方级别)。

2.2、Java实现

public void selectSort(int[] a) {
    int n = a.length;
    for(int i=0;i<n;i++) {
	int min = i;
	for(int j = i+1;j<n;j++) {
	    if(a[j] < a[min])
		min = j;
	}
	exch(a, i, min);
    }
}

三、插入排序

3.1、简介

插入排序的基本思想如下:像麻将一样,从左到右第二个开始,将其与前一个比较,如果小于前一个,就与前者交换位置,直到不再小于前者或者它自己已经处于第一个位置。

插入排序适合于已经部分有序的数组,事实上,当数组的绝大部分元素都已经有序,只是少数元素无序时,选择插入排序是最好的选择。

对于小规模的数组,也可以优先选用插入排序,而非选择后面提到的高级排序算法,因为可以避免递归栈过于太深。

最好情况下,插入排序能够在线性时间内完成排序;最坏情况下,仍然需要平方级别的时间。

所以,插入排序的时间复杂度为O(N*N)。

3.2、Java实现

public void insertSort(int[] a) {
    int n = a.length;
    for(int i=1;i<n;i++) {
        for(int j=i;j>0 && a[j] < a[j-1];j--) {
	    exch(a, j, j-1);
	}
    }
}

四、希尔排序

4.1、简介

当数组规模较大时,插入排序将元素移到合适位置的速度太慢。希尔排序就是针对这一问题的改进,其基本思想是将一个大规模的数组看成若干个长度为h的子数组相互交织而成。首先实现数组的h有序,当h较大时,可以较大范围内移动元素的位置;当h为1时,就相当于是完成了插入排序。

希尔排序的时间复杂度难以衡量,但可以确定的是介于平方级别与线性对数之间的。

4.2、Java实现

public static void shellSort(int[] a) {
    int n = a.length;
    int h = 1;
    while(h < n/3)
	h = h * 3 + 1;
    while(h > 0) {
	for(int i=h;i<n;i++) {
	    for(int j=i;j>=h && a[j] < a[j-h];j = j-h) {
		exch(a, j, j-h);
	    }
	}
	h = h / 3;
    }
}

五、快速排序

5.1、简介

5.2、Java实现

public static void quickSort(int[] a) {
    quickSort(a, 0, a.length-1);
}

private static void quickSort(int[] a, int lo, int hi) {
    if(hi <= lo)
	return;
    int j = partition(a, lo, hi);
    quickSort(a, lo, j-1);
    quickSort(a, j+1, hi);
}

private static int partition(int[] a, int lo, int hi) {
    int v = a[lo];
    int i = lo;
    int j = hi+1;
    while(true) {
	while(a[++i] < v) 
	    if(i == hi)
		break;
	while(a[--j] > v)
	    if(j == lo)
		break;
	if(i >= j)
	    break;
	exch(a, i, j);
    }
    exch(a, lo, j);
    return j;
}

六、归并排序

5.1、简介

5.2、Java实现

5.2.1、自上而下

/*
 * 归并排序,自上而下
 */
private static int[] aux;
public static void mergeSort1(int[] a) {
    aux = new int[a.length];
    mergeSort(a, 0, a.length-1);
}
	
private static void mergeSort(int[] a, int lo, int hi) {
    if(hi <= lo) 
        return;
    int mid = lo + (hi - lo)/2;
    mergeSort(a, lo, mid);
    mergeSort(a, mid+1, hi);
    merge(a, lo, mid, hi);
}
	
private static void merge(int[] a, int lo, int mid, int hi) {
    int i = lo;
    int j = mid + 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[i++];
	else
	    a[k] = aux[j++];
    }
}

5.2.2、自下而上

/*
 * 归并排序,自下而上
 */
public static void mergeSort2(int[] a) {
    int n = a.length;
    aux = new int[n];
    for(int sz = 1;sz < n; sz = sz + sz) {
	for(int lo = 0; lo < n-sz; lo = lo + sz + sz) {
	    merge(a, lo, lo + sz-1, Math.min(lo + sz + sz -1, n-1));
	}
    }
}

Supongo que te gusta

Origin blog.csdn.net/sun_lm/article/details/83019012
Recomendado
Clasificación