• 排序算法总结(java实现)


    排序算法

    介绍:排序分为内部排序和外部排序,内部排序指在内存中进行的排序过程;外部排序指在外存中进行排序的过程,但是此过程建立在多次访问内存的基础上(分成一段段利用内部排序进行排序)。

    以下排序均属于内部排序:

    一、插入排序                       

    1、直接插入排序

      思想:每一步将一个待排序元素,插入到前面已经排好序的序列中去进行比较排序,直到所有元素插完

      图解

      

      代码实现

      

     1 /**
     2      * 插入排序
     3      *
     4      * @param arr
     5      */
     6     public static void insertionSort(int[] arr) {
     7         for (int i = 1; i < arr.length; i++) {
     8             int j = i;
     9             //当前元素开始与前面排好序元素进行比较
    10             while (j > 0 && arr[j] < arr[j - 1]) {
    11                 swap(arr,j,j-1);
    12                 j--;
    13             }
    14         }
    15     }

    2、希尔排序

      思想:把排序序列按照设定的增量进行分组,然后对每一组使用直接插入排序

      说明:

    1. 增量的设定:这个值通常自定义,但是比较常用的增量是gap=length/2(并不是最优)
    2. 增量的修改:每次经过一次排序后,增量通常需要gap=gap/2,直到增量为1时,停止修改
    3. 增量的使用:若增量为n,则当前序列需要分为n组,即一组有length/n个元素
    4. 分组:距离保持一致

      图解:

      

      代码实现:

      

     1     private static int[] sort(int nums[]){
     2         int length = nums.length;
     3         int gap = length/2;//初始化增量
     4         while(gap>=1){
     5             for (int i=0;i<gap;i++){
     6                 //得到了本组所有元素,以下对本组元素进行直接插入排序
     7                 for (int j=i+gap;j<nums.length;j=j+gap){//默认第一个元素在已排序序列中,故从第二个元素开始插入比较
     8                        while(j>i && nums[j-gap]>nums[j]){
     9                            int temp = nums[j-gap];
    10                            nums[j-gap] = nums[j];
    11                            nums[j] = temp;
    12                            j=j-gap;
    13                        }
    14                 }
    15             }
    16             gap = gap/2;
    17         }
    18         return nums;
    19     }

    二、选择排序                       

    1、直接选择排序

      思想:每次遍历比较出最小值,再拿最小值与当前未排序列的第一个位置元素互换位置。n表示元素个数,则第m次比较(n-m)次

      图解

      

      代码实现

      

     1 private static int[] selectSort(int arr[]){
     2         int flag = 0;//记录待比较序列中最小值位置
     3         for(int i=0;i<arr.length-1;i++){
     4             //第i+1轮比较排序
     5             flag = i;
     6             for(int j=i+1;j<arr.length;j++){
     7                 if(arr[flag]>arr[j]){
     8                     flag=j;  //保存最小值位置
     9                 }
    10             }
    11             if(flag!=i) {
    12                 //判断最小值是否在目标位置,不是则需要进行交换
    13                 int temp = arr[flag];
    14                 arr[flag] = arr[i];
    15                 arr[i] = temp;
    16             }
    17         }
    18         return arr;
    19     }

    2、堆排序

      思想

      图解

      代码实现

    三、交换排序                       

    1、冒泡排序

      思想:进行n-1轮排序(n为元素个数)每轮排序中按照“小在前,大在后”的比较规则进行位置调整,每一轮都会冒出一个最大值在尾部(当前比较序列尾部)

      图解

             依次进行n-1轮排序

      代码实现

      

     1 private int[] 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     return arr; 
    12 }

    2、快速排序

      思想:在冒泡排序的基础上进行了优化,通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两

      部分数据分别进行快速排序,整个排序过程可  以 递归进行,以此达到整个数据变成有序序列

      过程说明

      ①选取适当的基准数,通常我们选取第一个数为基准数,每一趟依次选取一个基准数,直到结束。

      ②与基准数比较中,小的换到前面,大的换到后面

      ③每趟都是先从右边开始比较,发生一次比较赋值(比较位置元素不变,游标不动;把它的值再复制到目标位置,目标位置移动一个单位)后则从另一方向开始

      ④快速排序停止条件:

      图解

      图片来源于 https://www.cnblogs.com/skywang12345/p/3596746.html

      

      代码实现

      

     1     /**
     2      * 一次快速排序
     3      * @param array 数组
     4      * @param lo 数组的前下标
     5      * @param hi 数组的后下标
     6      * @return key的下标index,也就是分片的间隔点
     7      */
     8     public static int partition(int []array,int lo,int hi){
     9         /** 固定的切分方式 */
    10         int key=array[lo];//选取了基准点
    11         while(lo<hi){
    12             //从后半部分向前扫描
    13             while(array[hi]>=key&&hi>lo){
    14                 hi--;
    15             }
    16             array[lo]=array[hi];
    17             //从前半部分向后扫描
    18             while(array[lo]<=key&&hi>lo){
    19                 lo++;
    20             }
    21             array[hi]=array[lo];
    22         }
    23         array[hi]=key;//最后把基准存入
    24         return hi;
    25     }
    26 
    27     /**
    28      * 快速排序
    29      * @param array
    30      * @param lo
    31      * @param hi
    32      */
    33     public static void quickSort(int[] array,int lo ,int hi){
    34         if(lo>=hi){
    35             return ;
    36         }
    37         //进行第一轮排序获取分割点
    38         int index=partition(array,lo,hi);
    39         //排序前半部分
    40         quickSort(array, lo, index - 1);
    41         //排序后半部分
    42         quickSort(array,index+1,hi);
    43     }

    四、归并排序                       

      思想:归并排序采用“分治法”思想,将待排序列拆分位子序列,将个子序列内部排序,再合并各子序列,在子序列之间进行排序。

      图解

      

      在治(合并阶段)图解如下:

      拿上图中最后一步来举例说明吧

      

      代码实现

    五、基数排序                       

      思想

      图解

      代码实现

    性能比较

  • 相关阅读:
    linux删除大小为0,linux下批量删除空文件(大小等于0的文件) 和 乱码文件
    在 VMware 上启用 SCSI_ID
    vmware中的RHEL scsi_id不显示虚拟磁盘的wwid的问题
    spring cloud 集成和使用
    spring cloud alibaba 常见用法
    rabbitmq 和 erlang window 安装
    系统架构 垂直拓展 水平拓展的区别
    SPI 服务提供者接口
    摩斯密码
    vue3 pinia 和 vuex的对比
  • 原文地址:https://www.cnblogs.com/jim0816/p/9781823.html
Copyright © 2020-2023  润新知