排序算法 - 图1

快速排序

基本思想

1.选择一个基准元素,通常选择第一个元素或者最后一个元素。
2.通过一趟排序讲待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素值小。另一部分记录的 元素值比基准值大。
3.此时基准元素在其排好序后的正确位置。
4.然后分别对这两部分记录用同样的方法继续进行排序,直到整个序列有序。

  1. class Solution {
  2. private void quickSort(int[] nums, int start, int end) {
  3. if (start >= end) {
  4. return;
  5. }
  6. int partition = partition(nums, start, end);
  7. quickSort(nums, start, partition - 1); //到p-1停止
  8. quickSort(nums, partition + 1, end); //从p+1开始
  9. }
  10. //找基准
  11. private static int partition(int[] arr, int startIndex, int endIndex) {
  12. int pivot = arr[startIndex];
  13. int left = startIndex;
  14. int right = endIndex;
  15. while (left != right) {
  16. while (left < right && arr[right] > pivot) {
  17. right--;
  18. }
  19. while (left < right && arr[left] <= pivot) {
  20. left++;
  21. }
  22. //找到left比基准大,right比基准小,进行交换
  23. if (left < right) {
  24. swap(arr, left, right);
  25. }
  26. }
  27. //第一轮完成,让left和right重合的位置和基准交换,返回基准的位置
  28. swap(arr, startIndex, left);
  29. return left;
  30. }
  31. private void swap(int[] nums, int i, int j) {
  32. int t = nums[i];
  33. nums[i] = nums[j];
  34. nums[j] = t;
  35. }
  36. }


冒泡排序

基本思想:

它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

步骤

1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3.针对所有的元素重复以上的步骤,除了最后一个。
4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

void bubbleSort(int a[], int n){  
    for(int i =0 ; i< n-1; ++i) {  
        for(int j = 0; j < n-i-1; ++j) {  
            if(a[j] > a[j+1])  
            {  
                int tmp = a[j] ; a[j] = a[j+1] ;  a[j+1] = tmp;  
            }  
        }  
    }  
}

算法改进

对冒泡排序常见的改进方法是加入一标志性变量exchange,用于标志某一趟排序过程中是否有数据交换,如果进行某一趟排序时并没有进行数据交换,则说明数据已经按要求排列好,可立即结束排序,避免不必要的比较过程。本文再提供以下两种改进算法:

选择排序

基本思想

首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

public static void selection(int[] arrays)
{
    int min;
    for (int i = 0; i < arrays.length; i++) {
        min=i;
        for (int j = i; j < arrays.length; j++) {
            if (arrays[j]<arrays[min]) {
                min=j;
            }
            if (min!=i) {
                int temp;
                temp=arrays[min];
                arrays[min]=arrays[i];
                arrays[i]=temp;

            }
        }
    }
}

直接插入排序

基本思想

将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。
要点:设立哨兵,作为临时存储和判断数组边界之用。
(感觉和冒泡类似)

public static void insertsort(int[] array) {
    for (int i = 1; i < array.length; i++) {
        int get=array[i];
        int j=i-1;
        while(j>=0 && array[j] > get){
            array[j+1]=array[j];
            j--;
        }
        array[j+1]=get;

    }

}

希尔排序

基本思想

先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。

操作方法

1.选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;
2.按增量序列个数k,对序列进行k 趟排序;
3.每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。