zoukankan      html  css  js  c++  java
  • 冒泡排序、选择排序、插入排序、归并排序算法

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

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

    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调试,进入程序查看具体的运算,这里只做个简单的图解。

    运行的结果:

  • 相关阅读:
    消息中间件(一)MQ详解及四大MQ比较
    SIP协议
    PAT (Basic Level) Practice 1008 数组元素循环右移问题
    LeetCode-Algorithms 1. 两数之和
    PAT (Basic Level) Practice 1040 有几个PAT
    PAT (Basic Level) Practice 1023 组个最小数
    PAT (Basic Level) Practice 1021 个位数统计
    PAT (Basic Level) Practice 1007 素数对猜想
    PAT (Basic Level) Practice 1006 换个格式输出整数
    PAT (Basic Level) Practice 1004 成绩排名
  • 原文地址:https://www.cnblogs.com/98dkk/p/10222971.html
Copyright © 2011-2022 走看看