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

    运行的结果:

  • 相关阅读:
    SpringBoot集成JWT
    MongoDB学习入门
    Docker入门笔记
    商品分类(递归子目录)接口开发笔记
    深入理解java虚拟机
    -XX:+HeapDumpOnOutOfMemoryError
    使用kettle报Invalid byte 1 of 1-byte UTF-8 sequence异常
    kettle学习笔记(四)——kettle输入步骤
    eclipse maven项目,如何导出使用的依赖jar包
    kettle学习笔记(二)——kettle基本使用
  • 原文地址:https://www.cnblogs.com/98dkk/p/10222971.html
Copyright © 2011-2022 走看看