zoukankan      html  css  js  c++  java
  • 常见的排序算法整理

    在这里整理一下目前一些常见的排序算法和一些个人理解,可能会存在一定的错误,后续发现后会立即更正。

    所涉及到的算法包括:冒泡排序、选择排序、插入排序、希尔排序、快速排序(递归和非递归版本)、堆排序、归并排序、桶排序、基数排序、计数排序。

    一些理解:

    快速排序和归并排序都是基于分治的思想,区别在于快速排序是先整体再局部:先把数据整体划分成两部分,一部分大于某个值,另一部分小于某个值,然后再分别对两部分作递归处理,即先保证整体基本有序,再保证局部有序;而归并排序是先把数据划分成最小的排序单元,先局部有序,然后对排序单元进行合并,从而保证整体有序。

    计数排序不适合大范围的数据排序的情况,因为会根据最大值来申请空间。

    冒泡排序的改进:

    ①第一遍从前往后遍历,找到最大值,然后从后往前遍历,找到最小值,后面重复这两步操作,这种改进称为鸡尾酒排序。改进点在于增加了遍历的方向,在某些情况下有比冒泡更好的性能,但是两者在最差情况下的表现差不多。

      1 package sortalg;
      2 
      3 import java.util.ArrayList;
      4 import java.util.Collections;
      5 import java.util.List;
      6 import java.util.Stack;
      7 
      8 public class SortAlgorithms {
      9   public static void main(String[] args){
     10     SortAlgorithms test = new SortAlgorithms();
     11     int[] arr = new int[]{1,3,4,2,5,4,7,9,21,10,11,8};
     12     test.radixsort(arr);
     13 //    test.mergesort(arr, 0, arr.length-1);
     14     for(int i : arr){
     15       System.out.print(i + " ");
     16     }
     17   }
     18 
     19   //冒泡排序
     20   public void bubble(int[] nums){
     21     for(int i=0; i<nums.length-1; i++){
     22       for(int j=0; j<nums.length-1-i; j++){
     23         if(nums[j] > nums[j+1]){
     24           nums[j] = nums[j] + nums[j+1];
     25           nums[j+1] = nums[j] - nums[j+1];
     26           nums[j] = nums[j] - nums[j+1];
     27         }
     28       }
     29     }
     30   }
     31 
     32   //选择排序
     33   public void selectsort(int[] nums){
     34     for(int i=0; i<nums.length-1; i++){
     35       int minIndex = i;
     36       for(int j=i; j<nums.length; j++){
     37         if(nums[j] < nums[minIndex]){
     38           minIndex = j;
     39         }
     40       }
     41       swap(nums, i, minIndex);
     42     }
     43   }
     44 
     45   //插入排序
     46   public void insertsort(int[] nums){
     47     for(int i=1; i<nums.length; i++){
     48       for(int j=i; j>0; j--){
     49         if(nums[j]<nums[j-1]){
     50           nums[j] = nums[j] + nums[j-1];
     51           nums[j-1] = nums[j] - nums[j-1];
     52           nums[j] = nums[j] - nums[j-1];
     53         }
     54       }
     55     }
     56   }
     57 
     58   //希尔排序--插入排序的改进版
     59   public void shellsort(int[] nums){
     60     int step = 0;
     61     while(step < nums.length) step = 3*step +1;
     62     while(step >0){
     63       step /= 3;
     64       for(int i=0; i<step; i++){
     65         for(int j=i+step; j<nums.length; j += step){
     66           int tmp = nums[j];
     68           while(j>=step && nums[j-step] > tmp){
     69             nums[j] = nums[j-step]; 70             j -= step 71           }
     72           nums[j] = tmp;
     73         }
     74       }
     75     }
     76   }
     77 
     78   //堆排序:建堆,交换首尾元素,调整堆
     79   public void heapsort(int[] nums){
     80     int len = nums.length;
     81     while(len>1){
     82       for(int i = (len-2)/2; i>=0; i--){
     83         adjustheap(nums, i, len);
     84       }
     85       swap(nums, 0, len-1);
     86       len--;
     87     }
     88   }
     89 
     90   // 递归调整堆
     91   public void adjustheap(int[] nums, int i, int len){
     92     int k = i;
     93     int left = 2*i+1, right = 2*i+2;
     94     if( left < len && nums[left] > nums[k]){
     95       k = left;
     96     }
     97     if(right < len && nums[right] > nums[k]){
     98       k = right;
     99     }
    100     if(k != i){
    101       swap(nums, i, k);
    102       adjustheap(nums, k, len);
    103     }
    104   }
    105 
    106   // =========================快速排序=============================
    107   // 递归版本
    108   public void quicksortRecursion(int[] nums, int low, int high){
    109     if(low >= high) return;
    110     int left = low, right = high;
    111     int tmp = nums[left];
    112     while(left < right){
    113       while(right > left && nums[right] >= tmp) right--;
    114       nums[left] = nums[right];
    115       while(left < right && nums[left] <= tmp) left++;
    116       nums[right] = nums[left];
    117     }
    118     nums[left] = tmp;
    119     quicksortRecursion(nums, low, left-1);
    120     quicksortRecursion(nums, left+1, high);
    121   }
    122 
    123   // 快速排序-非递归版本
    124   public void quicksortNonRecursion(int[] nums){
    125     Stack<Integer> stack = new Stack<>();
    126     stack.push(0);
    127     stack.push(nums.length-1);
    128     while(!stack.empty()){
    129       int high = stack.pop();
    130       int low = stack.pop();
    131 
    132       int pivorite = partition(nums, low, high);
    133       if(pivorite > low){
    134         stack.push(low);
    135         stack.push(pivorite-1);
    136       }
    137       if(pivorite < high){
    138         stack.push(pivorite+1);
    139         stack.push(high);
    140       }
    141     }
    142   }
    143 
    144   public int partition(int[] nums, int low, int high){
    145     if(low >= high) return low;
    146     int left = low, right = high;
    147     int tmp = nums[left];
    148     while(left < right){
    149       while(right > left && nums[right] >= tmp) right--;
    150       nums[left] = nums[right];
    151       while(left < right && nums[left] <= tmp) left++;
    152       nums[right] = nums[left];
    153     }
    154     nums[left] = tmp;
    155     return left;
    156   }
    157   // =========================快速排序 end=============================
    158 
    159   // 归并排序
    160   public void mergesort(int[] nums, int left, int right){
    161     int mid = left + (right-left)/2;
    162     if(right > left){
    163       mergesort(nums, left, mid);
    164       mergesort(nums, mid+1, right);
    165       mergePartion(nums, left, mid, right);
    166     }
    167   }
    168 
    169   // 合并每个partion
    170   public void mergePartion(int[] nums, int left, int mid, int right){
    171     int[] tmp = new int[right-left +1];
    172     int low = left, high = mid+1;
    173     int i=0;
    174     while(low <= mid && high <= right){
    175       if(nums[low] <= nums[high]){
    176         tmp[i++] = nums[low++];
    177       }else{
    178         tmp[i++] = nums[high++];
    179       }
    180     }
    181     while(low<=mid) tmp[i++] = nums[low++];
    182     while(high<=right) tmp[i++] = nums[high++];
    183     for(i=left; i<=right; i++){
    184       nums[i] = tmp[i-left];
    185     }
    186   }
    187 
    188   // =========================桶排序 start=============================
    189   // 先把元素放到桶里,再对每一个桶分别排序,最后汇总输出
    190   public void bucketsort(int[] nums){
    191     int len = nums.length;
    192     int max = Integer.MIN_VALUE, min = Integer.MAX_VALUE;
    193     //找到最小值和最大值
    194     for(int i=0; i<len; i++){
    195       if(nums[i] < min) min = nums[i];
    196       if(nums[i] > max) max = nums[i];
    197     }
    198     int bucketnum = max/len - min/len + 1;
    199     List list = new ArrayList<ArrayList<Integer>>();
    200     for(int i=0; i<bucketnum; i++){
    201       list.add(new ArrayList<>());
    202     }
    203 
    204     // 把数据放到不同的桶里
    205     for(int i=0; i<len; i++){
    206       int index = (nums[i] - min)/len;
    207       ((ArrayList<Integer>)list.get(index)).add(nums[i]);
    208     }
    209 
    210     // 对每个桶分别排序
    211     for(int i=0; i<bucketnum; i++){
    212       Collections.sort((ArrayList)list.get(i));
    213     }
    214 
    215     // 汇总数据
    216     int k=0;
    217     for(int i=0; i<bucketnum; i++){
    218       List<Integer> list1 = (ArrayList<Integer>)list.get(i);
    219       if(list1.size()>0){
    220         for(int j : list1){
    221           nums[k++] = j;
    222         }
    223       }
    224     }
    225   }
    226   // =========================桶排序 end=============================
    227 
    228   // =========================计数排序 start=============================
    229   public void countsort(int[] nums){
    230     int max = Integer.MIN_VALUE;
    231     for(int num : nums){
    232       if(num > max) max = num;
    233     }
    234     int busketnum = max + 1;
    235     int[] arr = new int[busketnum];
    236     for(int num : nums){
    237       arr[num]++;
    238     }
    239     int index = 0;
    240     for(int i=0; i< busketnum; i++){
    241       while(arr[i]>0){
    242         nums[index++] = i;
    243         arr[i]--;
    244       }
    245     }
    246   }
    247   // =========================计数排序 end=============================
    248 
    249   // =========================基数排序 end=============================
    250   public void radixsort(int[] nums){
    251     //获取最大的数字
    252     int max = Integer.MIN_VALUE;
    253     for(int num : nums){
    254       if(num > max) max = num;
    255     }
    256     for(int exp = 1; max/exp > 0; exp*=10){
    257       radixsort(nums, exp);
    258     }
    259   }
    260 
    261   public void radixsort(int[] nums, int exp){
    262     int[] busket = new int[10];
    263     int[] output = new int[nums.length];
    264     for(int i=0; i<nums.length; i++){
    265       busket[(nums[i]/exp)%10]++;
    266     }
    267 
    268     // 修改后,每个数组元素就代表小于等于当前位的数字有多少
    269     // 例如当前是个位排序,busket: 0 1 1 2 3 4 7 7 8 9的4表示个位小于等于5的数字有4个
    270     for(int i=1; i<busket.length; i++){
    271       busket[i] += busket[i-1];
    272     }
    273 
    274     // 更改buckets[i]。目的是让更改后的buckets[i]的值,是该数据在output[]中的位置。 注意这里要从后向前遍历
    275     for(int i=nums.length-1; i>=0; i--){
    276       int busketIndex = (nums[i]/exp)%10;
    277       output[--busket[busketIndex]-1] = nums[i];279     }
    280 
    281     for(int i=0; i<nums.length; i++){
    282       nums[i] = output[i];
    283     }
    284   }
    285   // =========================基数排序 end=============================
    286 
    287   public void swap(int [] nums, int  i, int j){
    288     int tmp = nums[i];
    289     nums[i] = nums[j];
    290     nums[j] = tmp;
    291   }
    292 }

     补充鸡尾酒排序:

     1     //鸡尾酒排序:冒泡排序的改进,稳定
     2     //先从低到高,再从高到低
     3     public void cocktail(int[] arr){
     4         if(arr==null||arr.length==0) return;
     5         for(int left=0,right=arr.length-1;left<right;){
     6             //从低到高,将较大元素后移
     7             for(int i=left;i<right;i++){
     8                 if(arr[i]>arr[i+1]){
     9                     exchange(arr,i,i+1);
    10                 }                
    11             }
    12             right--;
    13             //从高到低,将较小元素前移
    14             for(int j=right;j>0;j--){
    15                 if(arr[j]<arr[j-1]){
    16                     exchange(arr,j,j-1);
    17                 }
    18             }
    19             left++;
    20         }
    21     }
  • 相关阅读:
    java基础-代理模式
    java基础-反射(细节)
    java基础-反射
    设计模式之单例
    23种设计模式汇总整理
    dialog--not attached to window manager
    java之设计模式
    android-sdk和api版本
    studio之mac快捷键
    控件之ReleLayout属性
  • 原文地址:https://www.cnblogs.com/NaLanZiYi-LinEr/p/10803909.html
Copyright © 2011-2022 走看看