排序是程序设计中经常遇到的问题,因此是算法中的重要内容。
常见的排序算法包括:冒泡排序,简单选择排序,直接插入排序,希尔排序,堆排序,归并排序,快速排序等。
排序算法各有各的优缺点,下表总结了各种排序的性质,主要包括时间复杂度、空间复杂度和稳定性。
具体的Java实现代码如下:
1. 冒泡排序
package com.wl.test;
/**
* 冒泡排序提供了三种方式
* 第一种不能算是真正的冒泡排序,因为他并不是连续的两个值进行比较
* 第三种对第二种进行了优化,考虑到当序列本来就基本有序时,就不需要那么多次的循环了
* @author WangLiang
* @version v1.0
*/
public class BubbleSort {
public static void sort(int[] array, int type) {
if(type == 1) {
for(int i=0; i<array.length; i++) {
for(int j=i; j<array.length; j++) {
if(array[i] > array[j]) {
swap(array, i, j);
}
}
}
} else if(type == 2) {
for(int i=0; i<array.length; i++) {
for(int j=array.length-1; j>i; j--) {
if(array[j] < array[j-1])
swap(array, j, j-1);
}
}
} else if(type == 3) {
boolean flag = true;
for(int i=0; flag && i<array.length; i++) {
flag = false;
for(int j=array.length-1; j>i; j--) {
if(array[j] < array[j-1])
swap(array, j, j-1);
flag = true;
}
}
}
}
private static void swap(int[]array, int i, int j) {
int x = array[i];
array[i] = array[j];
array[j] = x;
}
}
2. 简单选择排序
package com.wl.test;
/**
* 选择排序实现过程如下:
* 首先遍历第i(i从第一个值循环到最后一个值)个节点后的所有值,找出最小(大)的值,与第i个值交换位置,
* 循环完成后,排序就已经完成了
* @author Administrator
* @version v1.0
*/
public class SelectSort {
public static void sort(int[] array) {
int min;
for(int i=0; i<array.length-1; i++) {
min = i;
for(int j=i+1; j<array.length; j++) {
if(array[j] < array[min]) {
min = j;
}
}
if(min != i) {
swap(array, i, min);
}
}
}
private static void swap(int[]array, int i, int j) {
int x = array[i];
array[i] = array[j];
array[j] = x;
}
}
3. 直接插入排序
package com.wl.test;
/**
* 插入排序实现过程如下:
* 从第i(i从第2个值到最后一个值)个节点值开始,每个值都在前面已经排好序的队列中找到自己的位置并插入
* 整个过程就像我们玩扑克牌时接牌(起和插)一样
* @author Administrator
* @version v1.0
*/
public class InsertSort {
public static void sort(int[] array) {
int i, j, sentry;
for(i=1; i<array.length; i++) {
if(array[i] < array[i-1]) {
sentry = array[i];
for(j=i-1; j>=0&&sentry < array[j]; j--) {
array[j+1] = array[j];
}
array[j+1] = sentry;
}
}
}
}
4. 希尔排序
package com.wl.test;
/**
* 希尔排序实现过程如下:
* 将整个待排序序列分组,分别进行插入排序
* @author Administrator
* @version v1.0
*/
public class ShellSort {
public static void sort(int[] array) {
int i, j, sentry;
int increment = array.length;
do {
increment = increment/2;
for(i=increment; i<array.length; i++) {
if(array[i] < array[i-increment]) {
sentry = array[i];
for(j=i-increment; j>=0&&sentry<array[j]; j-=increment) {
array[j+increment] = array[j];
}
array[j+increment] = sentry;
}
}
} while (increment > 1);
}
public static void shellSort(int[] arr) {
int j;
int len = arr.length;
for(int val=len>>1; val>0; val>>=1) {
for(int i=val; i<len; i++) {
int temp = arr[i];
for(j=i; j>=val&&temp<arr[j-val]; j-=val) {
arr[j] = arr[j-val];
}
arr[j] = temp;
}
}
}
}
5. 堆排序
package com.wl.test;
/**
* 程序利用大根堆的性质,每次都可以找到最大的那个值
* 程序运行过程中需要维护堆的性质
* @author Administrator
* @version v1.0
*/
public class HeapSort {
public static void sort(int[] array) {
for(int i=array.length/2-1; i>=0; i--) {
heapAdjust(array, i, array.length-1);
}
for(int i=array.length-1; i>0; i--) {
swap(array, 0, i);
heapAdjust(array, 0, i-1);
}
}
private static void heapAdjust(int[] array, int s, int m) {
int temp = array[s];
for(int j=2*s+1; j<=m; j=2*j+1) {
if(j<m && array[j] < array[j+1]) { // array[j]为左孩子,array[j+1]为右孩子
j++;
}
if(temp > array[j]) { // 如果array[s]比左右孩子都大,则退出
break;
}
array[s] = array[j]; // 否则,将最大的那个孩子提升为父节点,循环继续
s = j;
}
array[s] = temp;
}
private static void swap(int[]array, int i, int j) {
int x = array[i];
array[i] = array[j];
array[j] = x;
}
}
6. 归并排序
package com.wl.test;
/**
* 排序使用归并的思想,将排序数组分成若干个只包含1个值的n个部分,然后对他们进行归并排序
* 排序发生在归并的过程中
* @author Administrator
* @version v1.0
*/
public class MergeSort {
public static void sort(int[] array) {
mSort(array, 0, array.length-1);
}
private static void mSort(int[] array, int s, int t) {
int m;
if(s != t) {
m = (s + t) / 2;
mSort(array, s, m);
mSort(array, m+1, t);
merge(array, s, m, t);
}
}
private static void merge(int[] array, int s, int m, int t) {
int i, j, k;
int[] temp = new int[t-s+1];
for(i = s, j = m+1, k=0; i<=m&&j<=t; k++) {
if(array[i] < array[j]) {
temp[k] = array[i++];
} else {
temp[k] = array[j++];
}
}
if(i<=m) {
for(; i<=m; i++, k++) {
temp[k] = array[i];
}
}
if(j<=t) {
for(; j<=t; j++, k++) {
temp[k] = array[j];
}
}
for(k=s; k<=t; k++) {
array[k] = temp[k-s];
}
}
}
7. 快速排序
package com.wl.test;
public class QuickSort {
public static void sort(int[] array) {
qSort(array, 0, array.length-1);
}
private static void qSort(int[] array, int low, int high) {
if(low<high) {
int pivot = partition(array, low, high);
qSort(array, low, pivot-1);
qSort(array, pivot+1, high);
}
}
private static int partition(int[] array, int low, int high) {
int pivotkey = array[low];
while(low < high) {
while(low<high && array[high] >= pivotkey)
high--;
swap(array, low, high);
while(low<high && array[low] <= pivotkey)
low++;
swap(array, low, high);
}
return low;
}
private static void swap(int[]array, int i, int j) {
int x = array[i];
array[i] = array[j];
array[j] = x;
}
}