常用排序算法一

248 阅读8分钟

一、冒泡排序

  1、基本介绍

  冒泡排序(Bubble Sorting)的基本思想是:通过对待排序序列从前向后(从下标较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就象水底下的气泡一样逐渐向上冒。

因为排序的过程中,各元素不断接近自己的位置,如果一趟比较下来没有进行过交换,就说明序列有序,因此要在排序过程中设置
一个标志flag判断元素是否进行过交换。从而减少不必要的比较。(这里说的优化,可以在冒泡排序写好后,在进行)
  例如:

  
  
  

  2、代码实现

  

 1     //基础版
 2     public static void bubbleSort_v1(int[] arr) {
 3         int tmp=0;
 4         for (int i = 0; i < arr.length - 1; i++) {
 5             for (int j = 0; j < arr.length - 1 - i; j++) {
 6                 if (arr[j] > arr[j + 1]) {
 7                     tmp = arr[j];
 8                     arr[j] = arr[j + 1];
 9                     arr[j + 1] = tmp;
10                 }
11             }
12         }
13     }

 

 1  //加强版
 2     public static void bubbleSort_v2(int[] arr) {
 3         boolean flag = false;
 4         int tmp=0;
 5         for (int i = 0; i < arr.length - 1; i++) {
 6             for (int j = 0; j < arr.length - 1 - i; j++) {
 7                 if (arr[j] > arr[j + 1]) {
 8                     flag=true;
 9                     tmp = arr[j];
10                     arr[j] = arr[j + 1];
11                     arr[j + 1] = tmp;
12                 }
13             }
14             //如果没进入比较,则表示已经是有序数组,中断排序即可
15             if(!flag){
16                 break;
17             }else {
18                 flag=false;
19             }
20         }
21     }

 

 

二、快速排序

  

  1、基本介绍 

  快速排序(Quicksort)是对冒泡排序的一种改进。基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

  

 

  

  

  2、代码实现

  

 1 public class QuickSort1 {
 2     // 我们的算法类不允许产生任何实例
 3     private  QuickSort1(){}
 4     // 对arr[low...high]部分进行partition操作
 5     // 返回p, 使得arr[low...p-1] < arr[p] ; arr[p+1...high] > arr[p]
 6     private static int partition(int[] arr, int low, int high){
 7         // 随机在arr[l...r]的范围中, 选择一个数值作为标定点pivot
 8         Common.swap(arr,low,(int)(Math.random() * (high - low + 1)) + 1);
 9 
10         int v = arr[low];
11         int j = low;// arr[l+1...j] < v ; arr[j+1...i) > v
12         for (int i =low+1; i <=high ; i++) {
13             if(arr[i]<v){
14                 j++;
15                 Common.swap(arr,i,j);
16             }
17         }
18         Common.swap(arr,low,j);
19         return j;
20     }
21     // 递归使用快速排序,对arr[l...r]的范围进行排序
22     private static void sort(int[] arr, int low, int high){
23         if( low >= high )
24             return;
25         int p=partition(arr,low,high);
26         sort(arr,low,p-1);
27         sort(arr,p+1,high);
28     }
29     public static  void sort(int[] arr){
30         int n = arr.length;
31         sort(arr,0,n-1);
32     }
33 }

 

   

 1 package com.atguigu.Sort.QuickSort;
 2 
 3 import com.atguigu.Sort.Common;
 4 
 5 /**
 6  * @author z
 7  * @createdate 2019-08-06 9:02
 8  */
 9 public class QuickSort2 {
10     // 我们的算法类不允许产生任何实例
11     private QuickSort2() {
12     }
13 
14     // 对arr[l...r]部分进行partition操作
15     // 返回p, 使得arr[l...p-1] < arr[p] ; arr[p+1...r] > arr[p]
16     private static int partition(int[] arr, int l, int r) {
17         // 随机在arr[l...r]的范围中, 选择一个数值作为标定点pivot
18         Common.swap(arr, l, (int) (Math.random() * (r - l + 1)) + 1);
19 
20         int v = arr[l];
21         int i = l + 1, j = r; // arr[l+1...i) <= v; arr(j...r] >= v
22         while (true) {
23             // 注意这里的边界, arr[i].compareTo(v) < 0, 不能是arr[i].compareTo(v) <= 0
24             // 思考一下为什么?
25             while (i <= r && arr[i] < v) i++;
26             // 注意这里的边界, arr[j].compareTo(v) > 0, 不能是arr[j].compareTo(v) >= 0
27             // 思考一下为什么?
28             while (j >= l + 1 && arr[j] > v) j--;
29             // 对于上面的两个边界的设定, 有的同学在课程的问答区有很好的回答:)
30             // 大家可以参考: http://coding.imooc.com/learn/questiondetail/4920.html
31             if (i > j) break;
32             Common.swap(arr, i, j);
33             i++;
34             j--;
35         }
36         Common.swap(arr, l, j);
37         return j;
38     }
39 
40     // 递归使用快速排序,对arr[l...r]的范围进行排序
41     private static void sort(int[] arr, int l, int r) {
42         if (l >= r)
43             return;
44         int p = partition(arr, l, r);
45         sort(arr, l, p - 1);
46         sort(arr, p + 1, r);
47     }
48 
49     public static void sort(int[] arr) {
50         int n = arr.length;
51         sort(arr, 0, n - 1);
52     }
53 }

 

三、直接插入排序

   

  1、基本介绍 

  插入排序(Insertion Sorting)的基本思想是:把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表

  

  

  2、代码实现

   

 1  public  static void insertSort_v1(int[] arr){
 2         //从第二个元素开始,因为如果从第一个元素向前插入,第一个元素之前是没有数据的
 3         for (int i = 1; i < arr.length; i++) {
 4             //从第i个元素开始向前查找正确的插入位置
 5             //下标j>0并且当前元素值arr[j]小于arr[j-1]时,进入循环,即从小到大
 6             for (int j = i; j > 0 && arr[j] < arr[j - 1]; j--) {
 7                 if (arr[j] < arr[j - 1]) {
 8                     int tmp = arr[j];
 9                     arr[j] = arr[j - 1];
10                     arr[j - 1] = tmp;
11                 }
12             }
13 
14         }
15     }

 

  

 1  public  static void insertSort_v2(int[] arr){
 2         for (int i = 1; i < arr.length; i++) {
 3             // 寻找元素arr[i]合适的插入位置
 4             int e = arr[i];
 5             int j = 0;
 6             // j保存元素e应该插入的位置,一次赋值,交换一次需要三次赋值
 7             for (j = i; j > 0 && arr[j - 1] > e; j--) {
 8                 //此时arr[j],arr[j-1]是同一个数
 9                 arr[j] = arr[j - 1];
10             }
11             //j是arr[i]应该插入的位置
12             arr[j] = e;
13         }
14     }

 

3.1、折半插入排序

  

  1、基本介绍 

  2、代码实现

 

四、希尔排序

  

  1、基本介绍 

 

  

  

  

  2、演化

  

 1  //演化
 2     private void evolution(){
 3         int[] arr = { 8, 9, 1, 7, 2, 3, 5, 4, 6, 0 };
 4         int temp = 0;
 5         // 希尔排序的第1轮排序
 6         // 因为第1轮排序,是将10个数据分成了 5组
 7         for (int i = 5; i < arr.length; i++) {
 8             // 遍历各组中所有的元素(共5组,每组有2个元素), 步长5
 9             for (int j = i - 5; j >= 0; j -= 5) {
10                 // 如果当前元素大于加上步长后的那个元素,说明交换
11                 if (arr[j] > arr[j + 5]) {
12                     temp = arr[j];
13                     arr[j] = arr[j + 5];
14                     arr[j + 5] = temp;
15                 }
16             }
17         }
18 
19         System.out.println("希尔排序1轮后=" + Arrays.toString(arr));//
20 
21 
22         // 希尔排序的第2轮排序
23         // 因为第2轮排序,是将10个数据分成了 5/2 = 2组
24         for (int i = 2; i < arr.length; i++) {
25             // 遍历各组中所有的元素(共5组,每组有2个元素), 步长5
26             for (int j = i - 2; j >= 0; j -= 2) {
27                 // 如果当前元素大于加上步长后的那个元素,说明交换
28                 if (arr[j] > arr[j + 2]) {
29                     temp = arr[j];
30                     arr[j] = arr[j + 2];
31                     arr[j + 2] = temp;
32                 }
33             }
34         }
35 
36         System.out.println("希尔排序2轮后=" + Arrays.toString(arr));//
37 
38         // 希尔排序的第3轮排序
39         // 因为第3轮排序,是将10个数据分成了 2/2 = 1组
40         for (int i = 1; i < arr.length; i++) {
41             // 遍历各组中所有的元素(共5组,每组有2个元素), 步长5
42             for (int j = i - 1; j >= 0; j -= 1) {
43                 // 如果当前元素大于加上步长后的那个元素,说明交换
44                 if (arr[j] > arr[j + 1]) {
45                     temp = arr[j];
46                     arr[j] = arr[j + 1];
47                     arr[j + 1] = temp;
48                 }
49             }
50         }
51 
52         System.out.println("希尔排序3轮后=" + Arrays.toString(arr));//
53     }

 

  3、代码实现

  

 1  // 希尔排序时, 对有序序列在插入时采用->交换法
 2     public static void sellSort_v1(int [] arr){
 3         int tmp = 0;
 4         for (int gap =arr.length/2 ; gap >0 ; gap/=2) {
 5             for (int i = gap; i <arr.length ; i++) {
 6                 // 遍历各组中所有的元素(共gap组,每组有个元素), 步长gap
 7                 for (int j = i-gap; j >=0; j-=gap) {
 8                     // 如果当前元素大于加上步长后的那个元素,说明交换
 9                     if(arr[j]<arr[j+gap]){
10                         tmp= arr[j];
11                         arr[j]=arr[j+gap];
12                         arr[j+gap]=tmp;
13                     }
14                 }
15             }
16         }
17     }

 

   

 1  //对交换式的希尔排序进行优化->移位法
 2     public static void sellSort_v2(int [] arr){
 3         for (int gap =arr.length/2 ; gap >0 ; gap/=2) {
 4             // 从第gap个元素,逐个对其所在的组进行直接插入排序
 5             for (int i = gap; i < arr.length; i++) {
 6                 int j = i;
 7                 int tmp = arr[j];
 8                 if(arr[j]<arr[j-gap]){
 9                     while (j - gap >= 0 && tmp < arr[j - gap]) {
10                         //移动
11                         arr[j] = arr[j-gap];
12                         j -= gap;
13                     }
14                     //当退出for后,就给temp找到插入的位置
15                     arr[j]=tmp;
16                 }
17             }
18         }
19     }