算法-排序算法-1

1. 选择排序 o n平方/o1

  在剩余的数组中选取最小值与数组第一位替换

  缺点是:无论是基本有序的数组还是乱序的数组,使用的时间是一致的

  

 1  public void selectSort(int[] a){
 2         for (int i = 0; i < a.length; i++) {
 3             int min = i;
 4             for (int j = i+1; j < a.length; j++) {
 5                 if (a[min]>a[j]){
 6                     swap(a,min,j);
 7                     min = j;
 8                 }
 9             }
10         }
11     }
1  public void swap(int[] a,int i,int j){
2         int temp = a[i];
3         a[i] = a[j];
4         a[j] = temp;
 
}
1 void swap(int[] arr,int i,int j){
2     int[i] = int[i] ^ int[j];
3     int[j] = int[i] ^ int[j];
4     int[i] = int[i]  ^ int[j];  
5 }

2. 插入排序(稳定性排序) o n平方/o1

每次都跟前面排好序的数组进行比较 后面小于前面就互换

比较适合基本有序的数组 大概比选择排序快1.7倍

1 public void insertion(int[] a){
2     for(int i = 1;i<a.length;i++){
3         for(int j = i;j>0&&a[j]<a[j-1];j--){
4            swap(a,j,j-1);
5         }
6     }
7 }

3.希尔排序

希尔排序是插入排序的进化版,有点像最优子问题一样,先达到大概有序 最后进行一次插入排序

 1 public void shell(int[] a){
 2   
 3   // 先确定一个步长h
 4   int h = a.length/2;
 5 
 6   // 等于1时就是进行一次插入排序 
 7   while(h>=1){
 8     for(int i = h;i<a.lenght;i++){
 9        for(int j = i;j >= h && a[j]<a[j-h];j-=h){
10             swap(a,j,j-h);
11         }
12    }
13     h/=2;
14   }  
15     
16 }        

 4.冒泡排序(稳定排序) o n平方/o1

  每一轮都得出一个最大的数放最右边

 public void bubbol(int[] arr) {
        for (int i = arr.length - 1; i > 0; i--) {
            for (int j = 0; j < i; j++) {
                if (arr[j] > arr[j + 1]) {
                    arr[j + 1] = arr[j] ^ arr[j + 1];
                    arr[j] = arr[j] ^ arr[j + 1];
                    arr[j + 1] = arr[j] ^ arr[j + 1];
                }
            }
        }
    }

 5. 归并排序(稳定排序) o n*logn/o n

  遍历分成两个数组,两个数组双指针合并

 1 public void process(int[] arr, int l, int r) {
 2         if (l == r) {
 3             return;
 4         }
 5         int mid = l + ((r - l) >> 1);
 6          process(arr,l,mid);
 7          process(arr,mid+1, r);
 8          merge(arr,l,mid,r);
 9     }
10 
11     public int merge(int[] arr, int l, int mid, int r) {
12         int p1 = l;
13         int p2 = mid + 1;
14         int ret = 0;
15         int i = 0;
16         int[] help = new int[r - l + 1];
17         while (p1 <= mid && p2 <= r) {
18             // 这一步是计算经过几次调换
19             ret += arr[p1] < arr[p2] ? (r - p2 + 1) * arr[p1] : 0;
20             // 小值移动到数组的左边
21             help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
22         }
23         // 移动剩余值
24         while (p1 <= mid) {
25             help[i++] = arr[p1++];
26         }
27         while (p2 <= r) {
28             help[i++] = arr[p2++];
29         }
30         // 用辅助内存替换原数组的值
31         for (i = 0; i < help.length; i++) {
32             arr[l + i] = help[i];
33         }
34         return ret;
35     }

 6. 快速排序 o n*logn/o logn

  选取一个数,大于这个数的放右边 小于这个数的放左边 等于这个数的放中间 没进行一次确定一批相同值的位置

 1 public void sort(int[] arr, int l, int r) {
 2         if (l < r) {
 3             // 选出随机值
 4             AlUtils.swap(arr, (int) (l + Math.random() * (r - l + 1)), r);
 5             // 荷兰国旗一次
 6             int[] partition = partition(arr, l, r);
 7             // 左区间
 8             sort(arr, l, partition[0] - 1);
 9             // 右区间
10             sort(arr, partition[1] + 1, r);
11         }
12     }
13 
14     public int[] partition(int[] arr, int l, int r) {
15         int less = l - 1;
16         int more = r;
17         while (l < more) {
18             if (arr[l] < arr[r]) {
19                 // 目标值是r位置的值
20                 // l位置的值小于目标值, l位置与less下一个值交换 l跳下一个
21                 AlUtils.swap(arr, l++, ++less);
22             } else if (arr[l] > arr[r]) {
23                 // l位置的值大于目标值 l位置与more上一个值交换 l不变
24                 AlUtils.swap(arr, l, --more);
25             } else {
26                 // l位置的值 与目标值一致不变 l跳下一个
27                 l++;
28             }
29         }
30         // 目标值r位置换到中间位置 r位置的值确定了位置
31         AlUtils.swap(arr, more, r);
32         int[] result = {less + 1, more};
33         return result;
34     }

 7. 堆排序 o n*logn/o1

  父 (i-1)/2

  左 2*i+1

  右 2*i +2

  

 1  public void heapInsert(int[] arr, int index) {
 2         while (arr[index] > arr[(index - 1) / 2]) {
 3             AlUtils.swap(arr, index, (index - 1) / 2);
 4             index = (index - 1) / 2;
 5         }
 6     }
 7 
 8     public void heapify(int[] arr, int index, int heapSize) {
 9         int left = index * 2 + 1;
10         while (left < heapSize) {
11             int largest = left + 1 < heapSize && arr[left] < arr[left + 1] ? left + 1 : left;
12             largest = arr[index] < arr[largest] ? largest : index;
13             if (largest == index) {
14                 break;
15             }
16             AlUtils.swap(arr, largest, index);
17             index = largest;
18             left = index * 2 + 1;
19         }
20     }
21 
22     public void sort(int[] arr) {
23         // 先建立大顶堆
24         for (int i = 0; i < arr.length; i++) {
25             heapInsert(arr, i);
26         }
27         // 第一个值与最后一个值替换 然后heapify
28         int heapSize = arr.length;
29         AlUtils.swap(arr, 0, --heapSize);
30         // 再替换 知道heapsize小于0
31         while (heapSize > 0) {
32             heapify(arr, 0, heapSize);
33             AlUtils.swap(arr, 0, --heapSize);
34         }
35     }
36 
37     public void disLessK(int[] arr,int k){
38         PriorityQueue<Integer> heap = new PriorityQueue<>();
39         int index = 0;
40         for (;index<=Math.min(arr.length,k);index++){
41             heap.add(arr[index]);
42         }
43         int i = 0;
44         for (;index<arr.length;i++,index++){
45             heap.add(arr[index]);
46             arr[i] = heap.poll();
47         }
48         while (!heap.isEmpty()){
49             arr[i++] = heap.poll();
50         }
51     }

 8. 桶排序(不基于比较的排序)

统计排序: 创建相同长度的数组,每个数在对应的index+1 最后遍历有值的数组 放入数组

基数排序: 以10进制为例,创建10个桶(队列),个位数放入对应的队列取出,按十位放入对应队列取出,按百位放入对应的队列取出 取出放入数组 有序

原文地址:https://www.cnblogs.com/isnotnull/p/14845784.html