• 算法篇1:排序算法(上篇)


    一:常见算法的复杂度及稳定性

      

    二:冒泡排序

    基本方法:

    比较两个相邻的元素,将值大的元素交换至右端

    举例说明:

    初始需排序数组 int[] arr = {6,3,8,2,9,1};

    第一趟排序:

        第一次排序:6和3比较,6大于3,交换位置:  3  6  8  2  9  1

        第二次排序:6和8比较,6小于8,不交换位置:3  6  8  2  9  1

        第三次排序:8和2比较,8大于2,交换位置:  3  6  2  8  9  1

        第四次排序:8和9比较,8小于9,不交换位置:3  6  2  8  9  1

        第五次排序:9和1比较:9大于1,交换位置:  3  6  2  8  1  9

        第一趟总共进行了5次比较, 排序结果:      3  6  2  8  1  9

    第一趟比较完成后,最后一个数一定是数组中最大的一个数,所以第二趟比较的时候最后一个数不参与比较;

    ————————————————————————————————————

    第二趟排序:

        第一次排序:3和6比较,3小于6,不交换位置:3  6  2  8  1  9

        第二次排序:6和2比较,6大于2,交换位置:  3  2  6  8  1  9

        第三次排序:6和8比较,6大于8,不交换位置:3  2  6  8  1  9

        第四次排序:8和1比较,8大于1,交换位置:  3  2  6  1  8  9

        第二趟总共进行了4次比较, 排序结果:      3  2  6  1  8  9

    第二趟比较完成后,倒数第二个数也一定是数组中第二大的数,所以第三趟比较的时候最后两个数不参与比较;

    ———————————————————————————————————————

    第三趟排序:

        第一次排序:3和2比较,3大于2,交换位置:  2  3  6  1  8  9

        第二次排序:3和6比较,3小于6,不交换位置:2  3  6  1  8  9

        第三次排序:6和1比较,6大于1,交换位置:  2  3  1  6  8  9

        第二趟总共进行了3次比较, 排序结果:         2  3  1  6  8  9

    第三趟完成后,倒数第三个也是数组中第三大的数,·······以后也是一样

    ——————————————————————————————————————

    第四趟排序:

        第一次排序:2和3比较,2小于3,不交换位置:2  3  1  6  8  9

        第二次排序:3和1比较,3大于1,交换位置:  2  1  3  6  8  9

        第二趟总共进行了2次比较, 排序结果:        2  1  3  6  8  9

    ——————————————————————————————————————

    第五趟排序:

        第一次排序:2和1比较,2大于1,交换位置:  1  2  3  6  8  9

        第二趟总共进行了1次比较, 排序结果:  1  2  3  6  8  9

    ——————————————————————————————————————

    代码实现:  

     1 package com.xqc.sort;
     2 
     3 public class BubleSort {
     4     public static void main(String[] args) {
     5         //步骤1:初始化数组
     6         int[] arr={6,3,8,2,9,1};
     7         System.out.println("排序前数组为:");
     8         for(int num:arr){
     9             System.out.println(num+"");
    10         }
    11         //步骤二:冒泡排序
    12         for(int i=0;i<arr.length-1;i++){//外层循环控制排序趟数
    13             for(int j=0;j<arr.length-1-i;j++){//内层循环控制每一趟排序多少次
    14                 if(arr[j]>arr[j+1]){
    15                     int temp=arr[j];
    16                     arr[j]=arr[j+1];
    17                     arr[j+1]=temp;
    18                 }
    19             }
    20             
    21         }
    22         //步骤三:显示排序后数组
    23         System.out.println();
    24         System.out.println("排序后的数组为:");
    25         for(int num:arr){
    26             System.out.println(num+" ");
    27         }
    28     }
    29 }

    三:选择排序

    基本方法:

    每一次从待排序的数据元素中选出最小的一个元素,存放在待排序序列的起始位置,直到全部排完

    举例说明:

    初始需排序数组:int[] arr = {6,3,8,2,9,1}

    第一趟排序:待排序数组为 { 6,3,8,2,9,1 } 中最小的数据是【1】,则将【1】和第一个数据 【6】做交换

        结果为{1,3,8,2,9,6}

    ————————————————————————————————————

    第二趟排序:此时未排序数组为{3,8,2,9,6}中最小的数据是【2】,则将【2】与第一个数据【3】做交换

      结果为{1,2,8,3,9,6}

    ————————————————————————————————————

    第三趟排序:此时未排序数组为{8,3,9,6}中最小的数据是【3】,则将【3】与第一个数据【8】进行交换

      结果为{ 1,2,3,8,9,6}

    ————————————————————————————————————

    第四趟排序:此时未排序数组为{8,9,6}中最小数据是【6】,则将【6】与第一个数据【8】进行交换

      结果为{1,2,3,6,9,8}

    ————————————————————————————————————

    第五趟排序:此时未排序数组为{9,8}中最小数据是【8】,则将【8】与第一个数据【9】进行交换

      结果为{1,2,3,6,8,9}

    代码实现:

     1 package com.xqc.sort;
     2 
     3 public class SeclectionSort {
     4     public static void main(String[] args) {
     5         //步骤1:初始化数组
     6         int[] arr={6,3,8,2,9,1};
     7         System.out.println("排序前数组为:");
     8         for(int num:arr){
     9             System.out.println(num+"");
    10         }
    11         //步骤二:选择排序
    12         for(int i = 0; i < arr.length - 1; i++) {// 做第i趟排序
    13             int k = i;
    14             for(int j = k + 1; j < arr.length; j++){// 选最小的记录
    15                 if(arr[j] < arr[k]){ 
    16                     k = j; //记下目前找到的最小值所在的位置
    17                 }
    18             }
    19             //在内层循环结束,也就是找到本轮循环的最小的数以后,再进行交换
    20             if(i != k){  //交换a[i]和a[k]
    21                 int temp = arr[i];
    22                 arr[i] = arr[k];
    23                 arr[k] = temp;
    24             }    
    25         }        
    26 
    27         //步骤三:显示排序后数组
    28         System.out.println();
    29         System.out.println("排序后的数组为:");
    30         for(int num:arr){
    31             System.out.println(num+" ");
    32         }
    33     }
    34 }

    四:直接插入排序:

    基本方法:

    每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。

    举例说明:

    初始需排序数组:int[] arr = {6,3,8,2,9,1}

    (第一趟:从上述初始数组中取出第一个数【6】,把他插入到有序表中

      结果为:有序表{ 6 },无序表:{ 3,8,2,9,1} )

    有的会在代码中显示该步骤,有的直接跳过这步会

    ————————————————————————————————————

    第二趟:从上述无序表中取出第一个数【3】,,把他插入到有序表的合适位置

      结果为:有序表{ 3,6},无序表{8,2,9,1}

    ————————————————————————————————————

    第三趟:从上述无序表中取出第一个数【8】,,把他插入到有序表的合适位置

      结果为:有序表{ 3,6,8},无序表{2,9,1}

    ————————————————————————————————————

    第四趟:从上述无序表中取出第一个数【2】,,把他插入到有序表的合适位置

      结果为:有序表{ 2,3,6,8},无序表{9,1}

    ————————————————————————————————————

    第五趟:从上述无序表中取出第一个数【9】,,把他插入到有序表的合适位置

      结果为:有序表{ 2,3,6,8,9},无序表{1}

    ————————————————————————————————————

    第六趟:从上述无序表中取出第一个数【1】,,把他插入到有序表的合适位置

      结果为:有序表{ 1,2,3,6,8,9},无序表{}

    ————————————————————————————————————

    代码实现:

     1 package com.xqc.sort;
     2 
     3 public class InsertSort {
     4     public static void main(String[] args) {
     5         //步骤1:初始化数组
     6         int[] arr={6,3,8,2,9,1};
     7         System.out.println("排序前数组为:");
     8         for(int num:arr){
     9             System.out.println(num+"");
    10         }
    11         //步骤二:插入排序
    12         //从未排序的序列中取出第一个
    13         for(int i=1;i<arr.length;i++){
    14             int tempdata = arr[i];
    15             int j;
    16             //寻找合适的插入位置,从后往前走,如果大与这个数则将这个数往后移动一
    17             for(j=i-1;j>=0;j--){
    18                 if(arr[j]>tempdata){
    19                     arr[j+1] = arr[j];
    20                 }else{
    21                     break;
    22                 }
    23             }
    24             //寻找到合适位置,将取出的数放在该位置
    25             arr[j+1] = tempdata;
    26         }
    27 
    28         //步骤三:显示排序后数组
    29         System.out.println();
    30         System.out.println("排序后的数组为:");
    31         for(int num:arr){
    32             System.out.println(num+" ");
    33         }
    34     }
    35 }

    五:快速排序:

    基本思路:

    快速排序是找出一个元素(理论上可以随便找一个)作为基准(pivot),然后对数组进行分区操作,使基准左边元素的值都不大于基准值,基准右边的元素值 都不小于基准值,如此作为基准的元素调整到排序后的正确位置。递归快速排序,将其他n-1个元素也调整到排序后的正确位置。最后每个元素都是在排序后的正 确位置,排序完成。

    举例说明:

    初始需排序数组:int[] = {3,7,2,9,1,4,6,8,10,5}(这次换个数组,并不是什么原因,我只是想在一次排序中让他体现出所有的情况)

    第一趟:选取基准值【5】

    第一次:从左边开始,将每个数与基准值比较,直到找到比基准值大的【7】,调换【5】和【7】的位置,因为【7】必须要在基准【5】的右边,则结果:

    比基准【5】小的有  {3} ,没有排序的有{5,2,9,1,4,6,8,10},比基准5大的有{7}

    第二次:从右边开始,将每个数与基准值比较,直到找到比基准值小的【4】,然后交换【4】和【5】的位置,则结果为

    比基准【5】小的有{3,4},没有排序的有{ 2,9,1,5},比基准大的有{ 6,8,10,7}

    第三次:从左边开始,将每个数与基准值比较,直到找到比基准值大的【9】,调换【5】和【9】的位置,则结果为

    比基准【5】小的有{3,4,2} 未排序的有{5,1},比基准大的有{ 9,6,8,10,7 }

    第四次:从右边开始,将每个数与基准值比较,直到找到比基准值小的【1】,然后交换【1】和【5】的位置,则结果为

    比基准【5】小的有{3,4,2,1}   基准值  { 5 }比基准大的有{ 9,6,8,10,7 }

    第二趟:重复上述步骤,分别对{3,4,2,1} 和 {9,6,8,10,7}进行递归式快排

        ······

    代码实现:

     1 package com.xqc.sort;
     2 
     3 public class QuickSort {
     4 
     5     public static void main(String[] args) {
     6         //步骤1:初始化数组
     7         int[] arr={3,7,2,9,1,4,6,8,10,5};
     8         System.out.println("排序前数组为:");
     9         for(int num:arr){
    10             System.out.println(num+"");
    11         }
    12         //步骤二:快速排序,因为要进行递归,所以我就将改方法提取出来
    13         sort(arr, 0, arr.length-1);
    14         
    15 
    16         //步骤三:显示排序后数组
    17         System.out.println();
    18         System.out.println("排序后的数组为:");
    19         for(int num:arr){
    20             System.out.println(num+" ");
    21         }
    22     }
    23     
    24     /**
    25      * 将数组的某一段元素进行划分,小的在左边,大的在右边
    26      * @param a
    27      * @param start
    28      * @param end
    29      * @return
    30      */
    31     public static int divide(int[] a, int start, int end){
    32         //每次都以最右边的元素作为基准值
    33         int base = a[end];
    34         //start一旦等于end,就说明左右两个指针合并到了同一位置,可以结束此轮循环。
    35         while(start < end){
    36             while(start < end && a[start] <= base)
    37                 //从左边开始遍历,如果比基准值小,就继续向右走
    38                 start++;
    39             //上面的while循环结束时,就说明当前的a[start]的值比基准值大,应与基准值进行交换
    40             if(start < end){
    41                 //交换
    42                 int temp = a[start];
    43                 a[start] = a[end];
    44                 a[end] = temp;
    45                 //交换后,此时的那个被调换的值也同时调到了正确的位置(基准值右边),因此右边也要同时向前移动一位
    46                 end--;
    47             }    
    48             while(start < end && a[end] >= base)
    49                 //从右边开始遍历,如果比基准值大,就继续向左走
    50                 end--;
    51             //上面的while循环结束时,就说明当前的a[end]的值比基准值小,应与基准值进行交换
    52             if(start < end){
    53                 //交换
    54                 int temp = a[start];
    55                 a[start] = a[end];
    56                 a[end] = temp;
    57                 //交换后,此时的那个被调换的值也同时调到了正确的位置(基准值左边),因此左边也要同时向后移动一位
    58                 start++;
    59             }    
    60             
    61         }
    62         //这里返回start或者end皆可,此时的start和end都为基准值所在的位置
    63         return end;
    64     }
    65  
    66     /**
    67      * 排序
    68      * @param a
    69      * @param start
    70      * @param end
    71      */
    72     public static void sort(int[] a, int start, int end){
    73         if(start > end){
    74             //如果只有一个元素,就不用再排下去了
    75             return;
    76         } 
    77         else{
    78             //如果不止一个元素,继续划分两边递归排序下去
    79             int partition = divide(a, start, end);
    80             sort(a, start, partition-1);
    81             sort(a, partition+1, end);
    82         }
    83             
    84     }
    85     
    86 }

     

     

     

     

    文章可随意参考借鉴,欢迎大家指正错误,如果感觉有用,点个赞就好
  • 相关阅读:
    【转】DOS命令大全(远程命令)
    system CPU占用率过高与91助手的关系
    要像管理咨询一样去做软件需求调研
    近两个月工作日志
    ECSHOP:首页实现显示子分类商品,并实现点击Tab页切换分类商品
    奋战5个小时解决诡异的PHP“图像XX因其本身有错无法显示”的问题
    SVN强制添加日志出现E205000错误解决方法
    pdf文件之itextpdf操作实例
    验证码实例
    Struts2拦截器记录系统操作日志
  • 原文地址:https://www.cnblogs.com/nullering/p/9537321.html
Copyright © 2020-2023  润新知