注:以下皆为个人理解,如有错误请联系我进行纠正

选择排序

从0-(n-1)找出一个最小值放在0位置 1-(n-1)找出一个最小值放在1位置,以此类推

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void SelectionSort(int[] arr){
if(arr == null || arr.length < 2){
return;
}
for(int minIndex, i = 0;i < arr.length - 1 ;i++){
//
minIndex = i;
for(int j = i+1;j < arr.length;j++){
if(arr[i]>arr[j]){
minIndex = j;
swap(arr,i,minIndex);
}

}
}
}

冒泡排序

两两比较,大的向后移,直至在数组末尾,每比较一轮下一轮比较次数减一

1
2
3
4
5
6
7
8
9
10
11
12
public static void BubbleSort(int[] arr){
if(arr == null || arr.length < 2){
return;
}
for(int end= arr.length - 1;end >0 ;end--){
for(int i=0;i<end;i++){
if(arr[i]>arr[i+1]){
swap(arr,i,i+1);
}
}
}
}

插入排序

认为第一个值为一个有序序列,从剩下的未排序序列中取出第一个元素,从有序序列末尾开始,依次与此元素比较,小则交换

1
2
3
4
5
6
7
8
9
10
public static void InsertionSort(int[] arr){
if(arr == null || arr.length < 2){
return;
}
for(int i = 1;i <arr.length;i++){
for(int j = i -1;j >=0 &&arr[j]>arr[j+1];j--){
swap(arr,j,j+1);
}
}
}

归并排序

算法步骤

  1. 将一个大数组持续对半拆分,直至剩下一个元素,此时天然有序
  2. 将左右两部分数组进行排序并放入一个辅助数组中
  3. 将辅助数组的元素拷贝回原数组
  4. 重复执行2和3
    代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static void mergeSort(int l ,int r) {
if (l == r) {
return;
}
int mid = l + (r - l)/2;//找出中间位置
mergeSort(l, mid);
mergeSort(mid + 1, r);
merge(l, mid, r);
}
public static void merge(int l,int mid,int r){
int a = l,b = mid+1 ,i = l;
while(a <= mid && b <= r){
help[i++] = arr[a] <= arr[b] ? arr[a++] : arr[b++];
}
while (a <= mid){
help[i++] = arr[a++];
}
while (b <= r){
help[i++] = arr[b++];
}
for(int k = l;k <= r;k++){
arr[k] = help[k];
}
}

随机快速排序

算法步骤

  1. 随机出一个数组中的值,假定它为中间值,对其左右两侧进行分区,<x的放左边 ,=x的放中间,>x的放右边
  2. 左右两侧的做法与步骤一相同
    代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public static void quickSort(int l ,int r){
if( l >= r){
return;
}
int mid = arr[l + (int)(Math.random() * (r - l + 1))];
partition(l,r,mid);
int left =first;
int right=last;//使用临时变量存储,防止底层递归覆盖全局变量
quickSort(l,left - 1);
quickSort(right + 1,r);
}
public static int first ,last;
public static void partition(int l ,int r ,int mid){
first = l;//小于区域的越界位置
last = r;//大于区域的越界位置
int i = l;
while(i <= last){
if(arr[i] < mid){
swap(first++,i++);
}else if(arr[i] > mid){
swap(last--,i);//i不变是因为换过来的这个元素还没有判断
}else {
i++;
}
}
}
public static void swap(int i,int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}

堆排序

  1. 首先建立一个大根堆(最大值在最顶部)
  2. 将最大值与数组最后一个元素交换,再将剩下的元素再构成一个大根堆
  3. 重复步骤2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//i位置的数向上调整
public static void heapInsert(int i){

while (arr[i] > arr[(i - 1) / 2]) {
swap(i, (i - 1) / 2);
i = (i - 1) / 2;
}

}
//i位置的数向下调整
public static void heapify(int i ,int size){
int l = 2*i+1;
while(l < size) {
int best = l + 1 < size && arr[l + 1] > arr[l] ? l + 1 : l;
best = arr[best] > arr[i] ? best : i;
if (best == i) {
break; int best = (l+1) < size && arr[l] > arr[l + 1] ? l : (l + 1);
best = arr[i] > arr[best] ? i : best;
}
swap(i, best);
i = best;
l = 2 * i + 1;
}
}
//从顶到底建立大根堆
public static void heapSort1(){
for(int i = 0;i < n;i++){//本人感觉从后往前遍历也可以
heapInsert(i);
}
int size = n;
while(size > 1){
swap(0,--size);
heapify(0,size);
}
}
//从底到顶建立大根堆(时间复杂度更好)只能从后往前遍历
public static void heapSort2(){
for(int i = (n - 1)/2;i >= 0;i--){
heapify(i,n);
}
int size = n;
while(size > 1){
swap(0,--size);
heapify(0,size);
}
}
public static void swap(int i,int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}

让我不能理解的地方是以下两行代码

1
2
int best = l + 1 < size && arr[l + 1] > arr[l] ? l + 1 : l;
best = arr[best] > arr[i] ? best : i;

替换成接下来的代码无法通过测试

1
2
break; int best = (l+1) < size && arr[l] > arr[l + 1] ? l : (l + 1);
best = arr[i] > arr[best] ? i : best;

基数排序

不基于比较的排序

  1. 找出数组中的最大值,得出其位数
  2. 从最低位开始,计算每一位数字小于等于其值的个数
  3. 按照当前位的数字大小进行排序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//有负数也可使用
public static void sort(){
int min = arr[0];
for(int i = 0;i < n;i++){
min = Math.min(min,arr[i]);
}
int max = 0;
for(int i = 0;i < n;i++){
arr[i] -= min;//减去数组中的最小值
max = Math.max(max,arr[i]);
}
radisSort(bit(max));
for(int i = 0;i < n;i++){
arr[i] += min;
}
}
//此方法只能在数组元素全为正整数的情况下适用
public static void radisSort(int bits){
for(int offset = 1 ;bits > 0 ;offset *= BASE ,bits--){
Arrays.fill(cnt, 0);
for(int i = 0;i < n ;i++){
cnt[(arr[i]/offset)%BASE]++;
}
for(int i = 1;i < BASE ;i++){
cnt[i] = cnt[i] + cnt[i-1];
}
for(int i = n -1 ;i >= 0;i--){
help[--cnt[(arr[i]/offset)%BASE]] = arr[i];
}
for(int i = 0;i < n ;i++){
arr[i] = help[i];
}
}
}
//返回数字在BASE进制下有几位
public static int bit (int number){
int ans = 0;
while(number > 0){
ans++;
number /= BASE;
}
return ans;
}