排序算法 | 描述 | 时间复杂度 | 空间复杂度 | 稳定性 | 说明 |
冒泡排序 | 正反循环 | O(N*N) | O(1) | 是 |
|
插入排序 | 慢慢有序 | O(N*N) | O(1) | 是 |
|
归并排序 | 分治 | O(N*logmN) | O(N) | 是 |
|
基数排序 | 求余 | O(N*logmN) | O(11N) | 是 | LSD MSD |
选择排序 | 选择min or max | O(N*N) | O(1) | 否 |
|
快速排序 | 分治(直接两边大小区分) | O(N*log2N) | O(1) | 否 |
|
希尔排序 | 三重循环 | O(N*log2N) | O(1) | 否 | 有序的序列效率很高 |
堆排序 | 构造堆顶,交换 | O(N*log2N) | O(1) | 否 | 均性能较接近于最坏性能 |
public class Sort {
/**
* Utils for swap and print
*/
public static void swap(int[] data, int indexOne, int indexTwo) {
int temp = data[indexOne];
data[indexOne] = data[indexTwo];
data[indexTwo] = temp;
}
public static void print(int[] data) {
System.out.println("--------------------------------");
for (int i = 0; i < data.length; i++) {
System.out.print(data[i]+", ");
}
System.out.println();
}
/**
* 冒泡排序
* (稳定)
* 每次通过交换,将最大或者最小的移动到前面
*/
public static void bubbleSort(int[] data) {
for (int i = 0; i < data.length; i++) {
for (int j = data.length - 1; j > i; j--) {
if (data[j] < data[j - 1]) {
swap(data, j, j - 1);
}
}
}
}
/**
* 插入排序
* (稳定)
* 处理顺序是:1个元素有序,2个元素有序,3个元素有序。。。。
*/
public static void insertSort(int[] data) {
for (int i = 1; i < data.length; i++) {
for (int j = 0; j < i; j++) {
if (data[j] > data[i]) {
swap(data, j, i);
}
}
}
}
/**
* 归并排序 (2路归并)
* (稳定)
* 要点:
* 1. int mid = (last+first)/2;
* 2. i < last+1
*/
public static void mergeSort(int[] data, int first, int last){
if (first >= last) {
return;
}
int mid = (last+first)/2;
mergeSort(data, first, mid);
mergeSort(data, mid + 1, last);
merge(data, first, mid, last);
}
public static void merge(int[] data, int first, int mid, int last){
int[] temp = new int[last - first + 1];
int begin1 = first;
int end1 = mid;
int begin2 = mid +1 ;
int end2 = last;
int k = 0;
while (begin1 <= end1 && begin2 <= end2 ) {
if (data[begin1] < data[begin2]) {
temp[k] = data[begin1];
begin1 ++ ;
}else {
temp[k] = data[begin2];
begin2 ++ ;
}
k++;
}
while (begin1 <= end1) {
temp[k++] = data[begin1++];
}
while (begin2 <= end2) {
temp[k++] = data[begin2++];
}
for (int i = first; i < last+1; i++) {
data[i] = temp[i-first];
}
}
/**
* 基数排序
* (稳定)
* 要点:
* 1. temp空间的开辟
* 2. 计数空间的开辟
* 3. 如何通过radix求取remainder
*/
public static void radixSort(int[] data,int depth){
int radix = 1 ;
while ( radix <=depth ) {
int[][] temp = new int[10][data.length];
int[] count = new int[10];
for (int i = 0; i < count.length; i++) {
count[i] = -1;
}
for (int i = 0; i < data.length; i++) {
int remainder = (data[i]/radix)%10;
if (count[remainder] == -1) {
count[remainder] = 0;
}
temp[remainder][count[remainder]] = data[i];
count[remainder]++;
}
int k = 0;
for (int i = 0; i < temp.length; i++) {
for (int j = 0; j < count[i]; j++) {
data[k] = temp[i][j];
k++;
}
}
radix = radix*10;
}
}
/**
* 选择排序
* (不稳定)
* 每次找到最大(或者最小的),放到前面
*/
public static void selectSort(int[] data) {
for (int i = 0; i < data.length; i++) {
int min = i;
for (int j = i + 1; j < data.length; j++) {
if (data[j] < data[min]) {
min = j;
}
}
swap(data, min, i);
}
}
/**
* 快速排序(改进的冒泡排序)
* (不稳定)
* 循环递归
* 要点:
* 1. 嵌套的while循环条件 i<right , j>left
* 2. 将key元素交换到正确的位置(和j所在元素交换)
*/
public static void quickSort(int[] data, int left, int right) {
if (left >= right) {
return;
}
int key = data[left];
int i = left + 1;
int j = right;
while(true){
while (data[j] > key && j > left) j-- ;
if (i < j) {
swap(data, i, j);
}
while (data[i] < key && i < right) i++ ;
if (i < j) {
swap(data, i, j);
}
if (i >= j) {
break;
}
}
swap(data, left, j);
quickSort(data,left,j-1);
quickSort(data,j+1,right);
}
/**
* 希尔排序(改进的插入排序)
* (不稳定)
* 三重循环
*/
public static void shellSort(int[] data) {
int dataLength = data.length/2;
while (dataLength != 0) {
for (int i = 0; i < dataLength; i++) {
//所有的数字为i ,i+dataLength,i+2*dataLength......
for (int j = 1; j < data.length; j = j+dataLength) {
for (int k = 0; k < j; k = k+dataLength) {
if (data[k] > data[j]) {
swap(data, j, k);
}
}
}
}
dataLength = dataLength/2;
}
}
/**
* 堆排序
* (不稳定)
* 从小到大,就构造大顶堆。
* 要点:
* 1. 半次循环,将最大的数字弄到堆顶。
* 2. 构造堆的长度不断减小。
*/
public static void heapAdjust(int[] data, int i, int length){
int parent = i;
int child = 2*i + 1;
while (child < length) {
if (child+1 < length && data[child] < data[child+1]) {
child ++ ;
}
if (data[parent] < data[child]) {
swap(data, parent, child);
parent = child;
child = 2*parent + 1;
}else {
break;
}
}
}
public static void heapSort(int[] data, int length){
for (int i = length/2 -1 ; i >= 0; i--) {
heapAdjust(data, i , length);
}
for (int i = length - 1; i >= 1 ; i--) {
swap(data, 0, i);
heapAdjust(data,0,i);
}
}
public static void main(String[] args) {
int[][] datas = {
{ 1, 2, 3, 4, 5 },
{ 5, 4, 3, 2, 1 },
{ 5, 1, 3, 4, 2 },
{ 10, 233, 3222, 411, 532 },
{ 1 }
};
for (int i = 0; i < datas.length; i++) {
int[] data = datas[i];
radixSort(data,1000);
print(data);
}
}
}