排序算法
名称 | 平均时间复杂度 | 最好情况 | 最坏情况 | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
冒泡排序 | O ( n 2 ) O(n^2) O(n2) | O ( n ) O(n) O(n) | O ( n 2 ) O(n^2) O(n2) | O ( 1 ) O(1) O(1) | Y Y Y |
选择排序 | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( n 2 ) O(n^2) O(n2) | O ( 1 ) O(1) O(1) | N N N |
堆排序 | O ( n l o g n ) O(nlogn) O(nlogn) | O ( n l o g n ) O(nlogn) O(nlogn) | O ( n l o g n ) O(nlogn) O(nlogn) | O ( 1 ) O(1) O(1) | N N N |
插入排序 | O ( n 2 ) O(n^2) O(n2) | O ( n ) O(n) O(n) | O ( n 2 ) O(n^2) O(n2) | O ( 1 ) O(1) O(1) | Y Y Y |
希尔排序 | O ( n l o g n ) O(nlogn) O(nlogn) | O ( n 2 ) O(n^2) O(n2) | O ( n l o g n ) O(nlogn) O(nlogn) | O ( 1 ) O(1) O(1) | N N N |
归并排序 | O ( n l o g n ) O(nlogn) O(nlogn) | O ( n l o g n ) O(nlogn) O(nlogn) | O ( n l o g n ) O(nlogn) O(nlogn) | O ( n ) O(n) O(n) | Y Y Y |
快速排序 | O ( n l o g n ) O(nlogn) O(nlogn) | O ( n l o g n ) O(nlogn) O(nlogn) | O ( n 2 ) O(n^2) O(n2) | O ( l o g n ) O(logn) O(logn) | N N N |
计数排数 | O ( n + k ) O(n+k) O(n+k) | O ( n + k ) O(n+k) O(n+k) | O ( n + k ) O(n+k) O(n+k) | O ( k ) O(k) O(k) | Y Y Y |
桶排序 | O ( n + k ) O(n+k) O(n+k) | O ( n + k ) O(n+k) O(n+k) | O ( n 2 ) O(n^2) O(n2) | O ( n + k ) O(n+k) O(n+k) | Y Y Y |
基数排序 | O ( n × k ) O(n×k) O(n×k) | O ( n × k ) O(n×k) O(n×k) | O ( n × k ) O(n×k) O(n×k) | O ( n + k ) O(n+k) O(n+k) | Y Y Y |
一、冒泡排序
递归版
非递归
public class BubbleSort{
public static void sort(int[] a) {
}
public void bubble(int[] a) {
int j = a.length - 1;
int x = 0;
while (true) {
for(int i = 0; i < j - 1; i++) {
if (a[i] > a[i + 1]) {
swap(a, i, i + 1);
x = i;
}
}
j = x;
if (j == 0) {
break;
}
}
}
private void swap(int[] a, int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
二、选择排序
public class SelectSort{
public static void sort(int[] a) {
for(int i = a.length - 1; i > 0; i--) {
int max = i;
for(int j = 0; j < i; j++) {
if (a[j] > a[max]) {
max = j;
}
}
if (max != i) {
swap(a, i, max);
}
}
}
private void swap(int[] a, int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
堆排序
public class HeapSort() {
public static void sort(int[] a) {
heapify(a, a.length);
for(int i = a.length - 1; i > 0; i--) {
swap(a, 0, i);
down(a, 0, i);
}
}
public static void heapify(int[] array, int size) {
for(int i = size / 2 - 1; i >= 0; i--) {
down(array, i, size);
}
}
public static void down(int[] array, int parent, int size) {
int left = 2 * parent + 1;
int right = left + 1;
int max = parent;
if (left < size && array[left] > array[max]) {
max = left;
}
if (right < size && array[right] > array[max]) {
max = right;
}
if (max != parent) {
swap(array, max, parent);
down(array, max, size);
}
}
public static void swap(int[] array, int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
插入排序
递归实现
public class InsertSort{
public static void sort(int[] a) {
insert(a, 1);
}
public static void insert(int[] a, int low) {
if (low == a.length) {
return ;
}
int t = a[low];
int i;
for(i = low - 1; i >= 0 && a[i] > t; i--) {
a[i + 1] = a[i];
}
if (i + 1 != low) {
a[i + 1] = t;
}
insert(a, low + 1);
}
}
public class InsertSort{
public static void sort(int[] a) {
insert(a, 1);
}
public static void insert(int[] a, int low) {
if (low == a.length) {
return;
}
int temp = a[low];
int i = low - 1;
while (i >= 0; a[i] > temp) {
a[i + 1] = a[i];
i--;
}
if (i + 1 != low) {
a[i + 1] = temp;
}
insert(a, low + 1);
}
}
非递归实现
public class InsertSort {
public static void sort(int[] a) {
for(int i = 1; i < a.length; i++) {
int temp = a[i];
for(int j = i - 1; j >= 0 && a[j] > a[i]; j--) {
a[j + 1] =a[j];
}
if(j != i - 1) {
a[j + 1] = temp;
}
}
}
}
public class InsertSort {
public static void sort(int[] a) {
for(int i = 1; i < a.length; i++) {
int temp = a[i];
int j = i - 1;
while (j >= 0 && a[j] > temp) {
a[j + 1] = a[j];
}
if(j != i - 1) {
a[j + 1] = temp;
}
}
}
}
希尔排序
public class ShellSort{
public static void sort(int[] a){
for(int gap = a.length >> 1; gap >= 1; gap = gap >> 1) {
for(int i = gap; i < a.length; i++) {
int temp = a[i];
int j = i - gap;
while (j >= 0 && a[j] > temp) {
a[j + gap] = a[j];
j -= gap;
}
if (j + gap != i) {
a[j + gap] = temp;
}
}
}
}
}
归并排序
递归方法
public class MergeSort{
public static void sort(int[] a) {
int[] a2 = new int[a.length];
merge(a, 0, a.length - 1, a2);
}
public static void split(int[] a, int left, int right, int[] a2) {
if (left == right) {
return;
}
int m = (left + right) >>> 1;
split(a, left, m, a2);
split(a, m + 1, right, a2);
// 合并操作
merge(a, left, m, m + 1, right, a2);
System.arraycopy(a2, left, a, left, right - left + 1);
}
public static void merge(int[] a1, int i, int iend, int j, int jend, int[] a2) {
int k = i;
while (i <= iend && j <= jend) {
if (a1[i] <= a1[j]) {
a2[k] = a1[i];
i++;
} else {
a2[k] = a1[j];
j++;
}
k++;
}
if (i > iend) {
System.arraycopy(a1, j, a2, k, jend - j + 1);
}
if (j > jend) {
System.arraycopy(a1, i, a2, k, iend - i + 1);
}
}
}
非递归方式
归并加插入
public class MergeInsertionSort{
public static void insertion(int[] a, int left, int right) {
for(int i = left + 1; i <= right; i++) {
int t = a[i];
int j = i - 1;
while (j >= left && a[j] > t) {
a[j + 1] = a[j];
j--;
}
if (i != j + 1) {
a[j + 1] = t;
}
}
}
public static void merge(int[] a, int i, int iend, int j, int jend, int[] a2) {
int k = 0;
while (i <= iend && j <= jend) {
if (a[i] <= a[j]) {
a[k] = a[i];
i++;
} else {
a[k] = a[j];
j++;
}
k++;
}
if (j > jend) {
System.arraycopy(a, i, a2, k, iend - i + 1);
}
if (i > iend) {
System.arraycopy(a, j, a2, k, jend - j + 1);
}
}
public static void split(int[] a, int i, int j, int[] a2) {
if (i == j) {
// 插入排序
insertion(a, i, j);
return;
}
int m = (i + j) >>> 1;
split(a, i, m);
split(a, m + 1, j);
// 合
merge(a, i, m, m + 1, j, a2);
System.arraycopy(a2, left, a, left, j - i + 1);
}
}
快排
单边循环
public class QuickSortLomuto{
public static void sort(int[] a) {
quick(a, 0, a.length - 1);
}
public static void quick(int[] a, int left, int right) {
if (left >= right) {
return;
}
int p = partition(a, left, right);
quick(a, left, p - 1);
quick(a, p + 1, right);
}
public static int partition(int[] a, int left, int right) {
int pv = a[right];
int i = left;
int j = right;
while (i < j) {
if (a[j] < pv) {
if (i != j) {
swap(a, i, j);
}
i++;
}
j++;
}
swap(a, i, right);
return i;
}
public static void swap(int[] array, int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
双边循环
注意事项
- 加内层循环的
i < j
条件 - 先处理j,后处理i
- 随机元素作为基准点
public class QuickSortLomuto{
public static void sort(int[] a) {
quick(a, 0, a.length - 1);
}
public static void quick(int[] a, int left, int right) {
if (left >= right) {
return;
}
int p = partition(a, left, right);
quick(a, left, p - 1);
quick(a, p + 1, right);
}
public static int partition(int[] a, int left, int right) {
int pv = a[left];
int i = left;
int j = right;
while (i < j) {
while (i < j && a[j] > pv) {
j--;
}
while (i < j && a[i] <= pv) {
i++;
}
swap(a, i, j);
}
swap(a, left, i);
return i;
}
public static void swap(int[] array, int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
改进
public class QuickSortLomuto{
public static void sort(int[] a) {
quick(a, 0, a.length - 1);
}
public static void quick(int[] a, int left, int right) {
if (left >= right) {
return;
}
int p = partition(a, left, right);
quick(a, left, p - 1);
quick(a, p + 1, right);
}
public static int partition(int[] a, int left, int right) {
int pv = a[left];
int i = left;
int j = right;
while (i <= j) {
while (i <= j && a[i] < pv) {
i++;
}
while (i <= j && a[j] > pv) {
j--;
}
if (i <= j) {
swap(a, i, j);
}
}
swap(a, left, j);
return j;
}
public static void swap(int[] array, int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
计数排序
public class CountSort{
public static void sort(int[] a) {
int max = a[0];
for(int num : a) {
if (num > max) {
max = num;
}
}
int[] counts = new int[max + 1];
for(int i = 0; i < a.length; i++) {
counts[a[i]]++;
}
int k = 0;
for(int i = 0; i < count.length; i++) {
while (count[i] > 0) {
a[k++] = i;
count[i]--;
}
}
}
}
代码改进
public class CountSort{
public static void sort(int[] a) {
int max = a[0];
int min = a[0];
for(int num : a) {
if (num > max) {
max = num;
}
if (num < min) {
min = num;
}
}
int[] counts = new int[max - min + 1];
//for(int i = 0; i < a.length; i++) {
// counts[a[i]]++;
//}
// 使用增强for循环
for(int num : a) {
counts[num - min]++;
}
int k = 0;
for(int i = 0; i < counts.length; i++) {
while (counts[i] > 0) {
a[k++] = i + min;
count[i]--;
}
}
}
}
桶排序
public clsss BucketSor{
public static void sort(int[] a) {
List buckets = new ArrayList[10];
for(int i = 0; i < a.length; i++) {
buckets[i] = new ArrayList();
}
for(int num : a) {
buckets[num % 10] = num;
}
int k = 0;
for(List bucket : buckets) {
int[] array = new int[bucket.size()];
if (bucket.size() > 0) {
for(int i = 0; i < bucket.size(); i++) {
array[i] = bucket.get(i);
}
}
InsertSort.sort(array);
for(int i : array) {
a[k++] = i;
}
}
}
}
基数排序
public class RadixSort{
public static void sort(String[] a, int length) {
ArrayList<String>[] buckets = new ArrayList<>[10];
for(int i = 0; i < 10; i++) {
buckets[i] = new ArrayList<>();
}
for(int i = length - 1; i >= 0; i--) {
for(String s : a) {
bucket[s.charAt(i) - '0'].add(s);
}
int k = 0;
for(ArrayList<String> bucket : buckets) {
for(String s : bucket) {
a[k++] = s;
}
bucket.clear();
}
}
}
}