冒泡排序、选择排序、插入排序、归并排序算法

最近了解了一下在面试题中,会经常遇到的一些常见的简单的排序的算法

在这里做个简单的记录如有不对之处请多指教。

1、冒泡排序

算法思想:冒泡排序是对数组中相邻的两个元素进行比较,看是否满足大小关系,不满足的话就交换位置

     每次冒泡排序至少有一个元素到达指定位置,也至少会发生一次位置交换(如果没有位置交换就说明数组有序),

     有n个数据,需要重复n次

最好、最坏、平均时间复杂度:

  最好时间复杂度(是一个有序数组时)为O(n)            

  最坏时间复杂度(刚好倒序时)为O(n2)

  平均时间复杂度:O(n2)

 代码示例:

 1 public static void bubbleSort(int[] arr) {
 2         for (int i = 0; i < arr.length - 1; i++) {            
 3             for (int j = 0; j < arr.length - 1 - i; j++) {        
 4                 if(arr[j] > arr[j+1]) {
 5                     int temp = arr[j];
 6                     arr[j] = arr[j + 1];        //数据交换
 7                     arr[j+1] = temp;
 8                 }
 9             }
10         }
11     }

冒泡排序的一些小的优化:当某次冒泡,没有再进行数据的交换时,说明数组已经有序,就可以不用进行后面的冒泡操作了

代码示例:

 1 public static void bubbleSort(int[] arr) {
 2 
 3         if(arr.length <= 1) return;
 4 
 5         for(int i = 0;i < arr.length - 1;i++) {
 6             boolean flag = false;                   //提前退出循环的标志
 7             for(int j = 0;j < arr.length - i -1;j++) {
 8                 if(arr[j] > arr[j + 1]) {
 9                     int temp = arr[j];
10                     arr[j] = arr[j + 1];            //数据交换
11                     arr[j + 1] = temp;
12                     flag = true;                    //表示有数据交换
13                 }
14             }
15             if (!flag) break;                       //如果没有数据交换的话退出循环
16         }
17     }

运行结果:

2、选择排序

算法思想:在未排序区间寻找最小的数据,将其放到已排好序区间的元素的尾部

最好、最坏、平均时间复杂度:

  最好时间复杂度:O(n2)

  最坏时间复杂度:O(n2)

  平均时间复杂度:O(n2)

 

代码示例:

 1 public static void selectionSort(int[] arr) {
 2         for(int i = 0;i < arr.length - 1;i++) {
 3             int minIndex = i;
 4             //选出未排序区间的最小元素
 5             for (int j = i + 1; j < arr.length; j++) {
 6                 if(arr[j] < arr[minIndex]) {
 7                     minIndex = j;
 8                 }
 9             }
10             if(minIndex == i)
11                 continue;
12             //交换位置
13             int temp = arr[i];
14             arr[i] = arr[minIndex];
15             arr[minIndex] = temp;
16         }
17 
18     }

运行结果:

3、插入排序

算法思想:我们将元素分为两个区间,未排序区间和已排序区间。

     在未排序区间取出元素与已排序区间元素进行比较插入到适当位置,

     以此类推,直到未排序区间为空为止

  最好时间复杂度:(数组有序)O(n)

  最坏时间复杂度:(刚好倒序)O(n2)

  平均时间复杂度:O(n2)

4、归并排序

算法思想:利用归并的思想方法实现的一种有效的排序方法,采用经典的分治策略。

  最好时间复杂度:O(nlogn)

  最坏时间复杂度:O(nlogn)

  平均时间复杂度:O(nlogn)

代码示例:

 1 public class MergeSort {
 2     public static void main (String[] args) {
 3         int[] arr = {56,12,97,58,64,25};
 4         sort(arr);
 5         print(arr);
 6     }
 7 
 8     public static void print(int[] arr) {
 9         for(int i = 0;i < arr.length;i++){
10             System.out.print(arr[i] + " ");
11         }
12     }
13 
14     public static void sort(int[] arr) {
15         int[] temp = new int[arr.length];               //定义一个临时数组,避免递归时频繁开辟空间
16         sort(arr,0,arr.length - 1,temp);
17     }
18 
19 
20     public static void sort(int[] arr,int left,int right,int[] temp) {
21         if(left < right){
22             int mid = (left + right) / 2;
23             sort(arr,left,mid,temp);                    //左归并操作
24             sort(arr,mid + 1,right,temp);           //右归并操作
25             mergeSort(arr,left,mid,right,temp);
26 
27         }
28 
29     }
30 
31     //合并子序列的操作
32     private static void mergeSort(int[] arr,int left,int mid,int right,int[] temp) {
33         int i = left;
34         int j = mid + 1;
35         int k = 0;
36 
37         while(left <= mid && j <= right) {          //将子序列元素有序写入临时数组
38             if(arr[i] >= arr[j]) {
39                 temp[k++] = arr[j++];
40             } else {
41                 temp[k++] = arr[i++];
42             }
43 
44         }
45 
46         while(i <= mid) {                   //将左子序列元素全部写入临时数组中
47             temp[k++] = arr[i++];
48         }
49 
50         while(j <= right) {                 //将右子序列元素全部写入临时数组中
51             temp[k++] = arr[j];
52 
53         }
54 
55         for (int t = 0;left <= right;t++) {
56             arr[left++] = temp[t];
57         }
58     }
59 
60 }

 合并子序列的操作图解。可以用Debug调试,进入程序查看具体的运算,这里只做个简单的图解。

运行的结果:

猜你喜欢

转载自www.cnblogs.com/98dkk/p/10222971.html