排序汇总(Java实现)

来源:互联网 发布:vantagepoint软件下载 编辑:程序博客网 时间:2024/06/05 19:59


选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,
冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。


那什么是稳定的排序算法呢?


就是在排序的过程中,相等的两个数并不会在排列后中为位置发生次序发生颠倒(一般而言,交换相隔很远的元素的算法是不稳定的)


时间效率分析汇总



排序法

平均时间

最差情形

稳定度

额外空间

备注

冒泡

O(n2)

    O(n2)

稳定

O(1)

n小时较好

选择

O(n2)

O(n2)

不稳定

O(1)

n小时较好

插入

O(n2)

O(n2)

稳定

O(1)

大部分已排序时较好

基数

O(dn)

O(dn)

稳定

O(n)

d为整数最高为的位数

希尔

O(nlogn)

O(ns) 1<s<2

不稳定

O(1)

s是所选分组

快速

O(nlogn)

O(n2)

不稳定

O(log2n)

n大时较好

归并

O(nlogn)

O(nlogn)

稳定

O(n)

n大时较好

O(nlogn)

O(nlogn)

不稳定

O(1)

n大时较好


关于快速排序,归并排序的空间复杂度,这里解释一下
归并排序每次递归都要用到一个辅助表,长度与待排序的表长度相同,虽然递归次数是O(log2n),但每次递归都会释放掉所占的辅助空间,所以下次递归的栈空间和辅助空间与这部分释放的空间就不相关了,因而空间复杂度还是O(n)。
快速排序空间复杂度只是在通常情况下才为O(log2n),如果是最坏情况的话,很显然就要O(n)的空间了。当然,可以通过随机化选择pivot来将空间复杂度降低到O(log2n)。但下面的快速排序实现就是一种O(n)的实现了



适用场景


冒泡排序:    在实际运用中它是效率最低的算法;但在待排序的元素序列基本有序的前提下,效率最高

插入排序:    一般不适合数据量比较大的场合或数据重复比较多的场合;但在每个元素距其最终位置不远时效率高
选择排序:    在实际应用中和冒泡排序基本差不多
希尔排序: 希尔排序比冒泡排序快5倍,比插入排序大致快2倍。Shell排序比起快速排序,归并排序,堆排序慢很多。
归并排序:    合并排序比堆排序稍微快一点,由于它需要一个额外的数组,在数据量大是比较适用
快速排序:  快速排序比大部分排序算法都要快。尽管在某些特殊的情况(有序,逆序)下有比快速排序快的算法,但通一般情况下,没有比它更快的。
堆排序:   适合数据量大的处理,对随机数的处理比快速排序慢,但和归并排序还是有比较有竞争的


代码实现


一、冒泡排序

/** * 冒泡排序 <br/> * 时间复杂度O(n2) 空间复杂度O(1) *  * @author Joeson *  */public class BubbleSort{public static void main(String[] args){int[] data = new int[] { 12, 3, 34, 13, 42, 56, 62, 35, 8 };bubbleSort(data);System.out.print("排序结果: " + Arrays.toString(data));}/** * 排序核心部分 *  * @param a * @return */private static void bubbleSort(int[] a){int temp;for (int i = 0; i < a.length; i++)for (int j = 0; j < a.length - i - 1; j++){if (a[j] > a[j + 1]){temp = a[j];a[j] = a[j + 1];a[j + 1] = temp;}}}}


二、选择排序


/** * 选择排序<br/> * 时间复杂度O(n2) 空间复杂度O(1) *  * @author Joeson *  */public class SelectionSort{public static void main(String[] args){int[] data = new int[] { 12, 3, 34, 13, 42, 56, 62, 35, 8 };selectionSort(data);System.out.print("排序结果: " + Arrays.toString(data));}/** * 选择排序核心 *  * @param data * @return */private static void selectionSort(int[] data){int min;int temp;for (int i = 0; i < data.length; i++){min = i;for (int j = i + 1; j < data.length; j++){if (data[j] < data[min]){min = j;}}temp = data[i];data[i] = data[min];data[min] = temp;}}}


三、插入排序

/** * 插入排序<br/> * 时间复杂度O(n2) 空间复杂度O(1) *  * @author Joeson *  */public class InsertSort{public static void main(String[] args){int[] data = new int[] { 12, 3, 34, 13, 42, 56, 62, 35, 8 };insertSort(data);System.out.print("排列顺序: " + Arrays.toString(data));}/** * 插入排序 *  * @param data */private static void insertSort(int[] data){int temp;for (int i = 1; i < data.length; i++){temp = data[i];int j = i - 1;for (; j >= 0 && data[j] > temp; j--){data[j + 1] = data[j];}data[j + 1] = temp;}}}




四、基数排序


/** * 基数排序(桶排序) <br/> * 平均时间复杂度:O(dn)(d即表示整形的最高位数) <br/> * 空间复杂度:O(10n) (10表示0~9,用于存储临时的序列)<br/> * 稳定性:稳定 *  * @author Joeson *  */public class RadixSort{/** * 最大数的位数 */static int max_Pos = 2;public static void main(String[] args){int[] data = new int[] { 23, 54, 63, 61, 46, 27 };radixSort(data, 10, 2);System.out.print("排列结果: " + Arrays.toString(data));}/** *  * @param data * @param radix *            多少进制数,就代表多少个桶 * @param d *            将关键字拆分为多少个子关键字 * @return */public static void radixSort(int[] data, int radix, int d){// 需要一个临时数组int[] tmp = new int[data.length];// 桶int[] buckets = new int[radix];for (int i = 0, rate = 1; i < d; i++){Arrays.fill(buckets, 0);// 拷贝数组到tmp中System.arraycopy(data, 0, tmp, 0, data.length);// 计算数组关键位置的子关键字,将其位置记录在bucktes中for (int j = 0; j < data.length; j++){int subKey = (tmp[j] / rate) % radix;buckets[subKey]++;}for (int j = 1; j < radix; j++){buckets[j] = buckets[j] + buckets[j - 1];}for (int m = data.length - 1; m >= 0; m--){int subKey = (tmp[m] / rate) % radix;data[--buckets[subKey]] = tmp[m];}System.out.println("对" + rate + "位上子关键字排序:" + Arrays.toString(data));rate *= radix;}}}



五、希尔排序


/** * 希尔排序 *  * <br/> * 时间复杂度O(n1.25) *  * @author Joeson *  */public class ShellSort{public static void main(String[] args){int[] a = new int[] { 12, 3, 34, 13, 42, 56, 62, 35, 8 };shellSort(a);System.out.print("排列顺序 : ");System.out.println(Arrays.toString(a));}/** * 希尔排序核心1 *  * @param args * @return */private static void shellSort(int[] data){for (int step = data.length / 2; step > 0; step /= 2){shellInsert(data, step);}}/** * 增序排列 *  * @param data * @param step * @return */private static void shellInsert(int[] data, int step){int j;int min;for (int i = step; i < data.length; i++){if (data[i - step] > data[i]){min = data[i];for (j = i - step; j >= 0 && data[j] > data[j + step]; j -= step){data[j + step] = data[j];}data[j + step] = min;}}}}



六、快速排序

/** * 快速排序 时间复杂度 O(nlogn) * 空间复杂度O(n) *  * @author Joeson *  */public class QuickSort{public static void main(String[] args){int[] data = new int[] { 12, 45, 12, 42, 42, 46, 63, 28 };quickSort(data, 0, data.length - 1);System.out.print("排序顺序: ");System.out.println(Arrays.toString(data));}/** * 增序排序 *  * @param a * @param from * @param to *            最大下标 */public static void quickSort(int[] data, int begin, int end){if (end <= begin)return;int mid = partition(data, begin, end);quickSort(data, begin, mid - 1);quickSort(data, mid + 1, end);}/** * 快速排序核心部分 *  * @param a * @param low * @param high * @return */public static int partition(int[] data, int begin, int end){int low = begin + 1;int high = end;do{while (low < end && data[low] <= data[begin])low++;while (high > begin && data[high] >= data[begin])high--;swap(data, low, high);} while (low < high);// 返回最后一次交换swap(data, low, high);swap(data, begin, high);return high;}public static void swap(int[] a, int i, int j){int temp = a[i];a[i] = a[j];a[j] = temp;}}



七、合并排序


/** * 合并排序 * @author Joeson * */public class MergeSort{public static void main(String[] args){int[] list = new int[12];for (int i = 0; i < args.length; i++){list[i] = Integer.valueOf(args[i]);}list = new MergeSort().mergeSort(list, 0, list.length-1);System.out.print("排列顺序:  ");for (int i = 0; i < list.length; i++){System.out.print(list[i] + " ");}}public int[] mergeSort(int[] list, int from, int to) {if (from != to){int mid = (from + to) >> 2;mergeSort(list, from, mid);mergeSort(list, mid + 1, to);return merge(list, from, to);}return list;}public int[] merge(int[] list, int from, int to){int i = from;int mid = (from + to) >>> 2;int j = mid + 1;int[] a = new int[to - from + 1];int count = 0;while (i <= mid && j <= to){if (list[i] < list[j]){a[count++] = list[i++];}else{a[count++] = list[j++];}}// 把剩余部分都加进去while (i <= mid){a[count++] = list[i++];}while (j <= to){a[count++] = list[j++];}for(int k=from; k<= to; k++){list[k] = a[k-from];}return list;}}


八、堆排序


/** * 建堆 O(n) 删除O(logn) <br/> * 堆排序包括两个步骤<br/> * (1)初始堆(堆的定义:1)堆是一个完全二叉树 2)根结点的值或者大于左右子树的值或者小于左右子树的值 3)左右子树也是一个堆) <br/> * (2)调整堆(当初始小顶堆之后,堆顶元素是最小的元素,取出最小的元素与最后一个元素相交换,再把剩下n-1个元素调整成堆,依次调整直到1为止) * 非终端节点调整 初始堆时从n/2向上调整成堆 把第一个元素与最后一个元素交换之后从第1个元素开始调整成新堆 *  *  * 时间复杂度为O(nlogn) 辅助空间为O(1) *  * @author Joeson *  */public class HeapSort{public static void main(String[] args){int[] data = new int[] { 2, 23, 24, 43, 52, 24, 51, 26 };heapSort(data);System.out.print("排列顺序: ");System.out.println(Arrays.toString(data));}/** * 堆排序核心部分 *  * @param num */private static void heapSort(int[] a){if (a.length <= 0)return;// 调整整个堆堆过程for (int i = a.length / 2 - 1; i >= 0; i--){adjust(a, i, a.length);}int tmp;for (int i = a.length - 1; i > 0; i--){tmp = a[i];a[i] = a[0];a[0] = tmp;// 从a[0]到num[i-1]调整成新堆adjust(a, 0, i);}}/** * 调整堆 *  * @param num * @param s *            调整开始父节点 * @param t *            调整结尾的界限,不包括 */private static void adjust(int[] a, int begin, int end){int tmp = a[begin];// 从最下父节点 与子节点比较,一直向上进行调整for (int i = 2 * begin + 1; i < end; i = 2 * i + 1){// 找出较大者把较大者给num[i]if (i < end - 1 && a[i] < a[i + 1]){i++;}if (a[i] > tmp){a[begin] = a[i];begin = i;}elsebreak;}a[begin] = tmp;}}


0 0
原创粉丝点击