当前位置 博文首页 > 邱天的henry的博客:第七章 数据结构与算法(八大排序算法--堆排

    邱天的henry的博客:第七章 数据结构与算法(八大排序算法--堆排

    作者:[db:作者] 时间:2021-07-05 22:06

    7.1冒泡算法
    7.1.1基本介绍
    (1)冒泡排序(Bubble Sorting)的基本思想是:通过对待排序序列从前向后(从下标较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就像水底下的气泡一样逐渐向上冒。
    (2)优化:因为排序的过程中,各元素不断接近自己的位置,如果一趟比较下来没有进行过交换,就说明序列有序,因此要在排序过程中设置一个标志flag判断元素是否进行交换。从而减少不必要的比较。(这里说的优化,可以在冒泡排序写好后,在进行)
    7.1.2演示冒泡过程的例子(图解)
    在这里插入图片描述
    小结以上图解:
    (1)一共进行(数组的大小-1)次 大的循环
    (2)每一趟排序的次数在逐渐的减少
    (3)如果我们发现在某趟排序中,没有发生一次交换,可以提前结束冒泡排序。这个就是优化。

    7.1.3冒泡排序应用实例
    @将五个无序的数:3,9,-1,10,-2使用冒泡排序法将其排成一个从小到大的有序数列。

    public class Demo1 {
        public static void main(String[] args) {
            //为了便于理解,冒泡排序的演变过程如下
            /*int[] arr={3,9,-1,10,-2};
    
            //起始的数组为
            System.out.println("初始的数组为:");
            System.out.println(Arrays.toString(arr));*/
    
            //测试冒泡排序的时间O(n^2)
            //定义一个随机数组
            int[] arr=new int[80000];
            for (int i=0;i<80000;i++){
                arr[i]=(int)(Math.random()*800000); //math.random的范围是[0,1)
            }
    
            //输出起始时间
            long time = System.currentTimeMillis();
            System.out.println(time);
            //调用封装好的冒泡方法
            bubbleSort(arr);
            //排序后时间
            long time2 = System.currentTimeMillis();
            System.out.println(time2);
    
            //排序后的数组为
            /*System.out.println("排序后的数组为:");
            System.out.println(Arrays.toString(arr));*/
    
            /*//第二趟排序
            for (int j=0;j<arr.length-1-1;j++){
                if (arr[j]>arr[j+1]){
                    temp=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=temp;
                }
            }
    
            //第三趟排序
            for (int j=0;j<arr.length-1-2;j++){
                if (arr[j]>arr[j+1]){
                    temp=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=temp;
                }
            }
    
            //第四趟排序
            for (int j=0;j<arr.length-1-3;j++){
                if (arr[j]>arr[j+1]){
                    temp=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=temp;
                }
            }*/
        }
    
        //将冒泡排序封装为方法
        public static void bubbleSort(int[] arr){
            int temp=0; //临时变量
            boolean flag=false;  //定义标识符,判断每一趟是否交换过
            //冒泡排序时间复杂度为O(n^2)
            for (int i=0;i<arr.length-1;i++){
                for (int j=0;j<arr.length-1-i;j++){
                    if (arr[j]>arr[j+1]){
                        flag=true;   //如果交换就将flag置位true
                        temp=arr[j];
                        arr[j]=arr[j+1];
                        arr[j+1]=temp;
                    }
                }
                //System.out.println("第"+(i+1)+"趟排序后的数组为:");
                //System.out.println(Arrays.toString(arr));
                if (!flag){
                    break;   //结束循环(因为此趟没有交换数组位置,说明数组已经有序)
                }else {
                    flag=false;  //如果此趟交换过位置,需要将flag重置,以便于下一轮的循环
                }
            }
        }
    }
    

    7.2选择排序

    7.2.1基本介绍
    选择排序也属于内部排序法,是从欲排序的数据中,按指定的规则选出来某一元素,再一次规定交换位置后达到排序的目的。

    7.2.2选择排序思想
    选择排序(select sorting)也是一种简单的排序方法。它的基本思想是:第一次从arr[0]-arr[n-1]中选取最小值,与arr[0]交换,第二次从arr[1]-arr[n-1]中选取最小值,与arr[1]交换,第三次从arr[2]-arr[n-1]中选取最小值,与arr[2]交换,…, 第i次从arr[i-1]-arr[n-1]中选取最小值,与arr[i-1]交换,…, 第n-1次从arr[n-2]-arr[n-1]中选取最小值,与arr[n-2]交换,总共通过n-1次,得到一个按排序码从小到大排列的有序序列。

    7.2.3选择排序的思路图
    在这里插入图片描述

    7.2.4选择排序实例
    @将数组101,34,119,1进行排序

    public class SelectSort {
        public static void main(String[] args) {
            //int[] arr={101,34,119,1};
            //System.out.println("起始数组");
            //System.out.println(Arrays.toString(arr));
            //定义一个随机数组(测试时间:时间比冒泡排序快)
            int[] arr=new int[80000];
            for (int i=0;i<80000;i++){
                arr[i]=(int)(Math.random()*800000); //math.random的范围是[0,1)
            }
            //起始时间
            System.out.println(System.currentTimeMillis());
            selectSort(arr);
            //排序后时间
            System.out.println(System.currentTimeMillis());
            //System.out.println("排序后数组");
            //System.out.println(Arrays.toString(arr));
        }
    
        //选择排序算法
        public static void selectSort(int[] arr){
            //算法  先简单--》做复杂,就是可以把一个复杂的算法,拆分成简单的问题-》逐步解决
    
            //冒泡时间复杂度为O(n^2)
            //第一轮
            for (int i=0;i<arr.length-1;i++){
                int minIndex=i;  //假设起始数小标为最小下标
                int min=arr[minIndex];  //假设起始数为最小值
                for (int j=i+1;j<arr.length;j++){
                    if (arr[j]<min){  //判断循环的数是否比假设的起始值小,如果小则交换
                        minIndex=j;   //交换最小值下标
                        min=arr[j];   //交换最小值
                    }
                }
                if (minIndex !=i){  //如果最小值不为当前假设值才可进入if语句
                    arr[minIndex]=arr[i];
                    arr[i]=min;
                }
            }
    
    
            /*//第二轮
             minIndex=1;  //假设起始数小标为最小下标
             min=arr[1];  //假设起始数为最小值
            for (int j=1+1;j<arr.length;j++){
                if (arr[j]<min){  //判断循环的数是否比假设的起始值小,如果小则交换
                    minIndex=j;   //交换最小值下标
                    min=arr[j];   //交换最小值
                }
            }
            if (minIndex !=1){  //如果最小值不为当前假设值才可进入if语句
                arr[minIndex]=arr[1];
                arr[1]=min;
            }
    
            //第三轮
            minIndex=2;  //假设起始数小标为最小下标
            min=arr[2];  //假设起始数为最小值
            for (int j=2+1;j<arr.length;j++){
                if (arr[j]<min){  //判断循环的数是否比假设的起始值小,如果小则交换
                    minIndex=j;   //交换最小值下标
                    min=arr[j];   //交换最小值
                }
            }
            if (minIndex !=2){  //如果最小值不为当前假设值才可进入if语句
                arr[minIndex]=arr[2];
                arr[2]=min;
            }*/
        }
    }
    

    7.3插入排序
    7.3.1插入排序法介绍
    插入式排序属于内部排序法,是对于欲排序的元素以插入的方式寻找该元素的适当位置,以达到排序的母的。
    7.3.2插入排序法思想
    插入排序(Insertion Sorting)的基本思想是:把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表。
    7.3.3插入排序思路图
    在这里插入图片描述
    7.3.4插入排序法应用实例:
    @有一群小牛,考试成绩为101,34,119,1;请从小到大排序

    public class InsertSort {
        public static void main(String[] args) {
            //int[] arr={101,34,119,1};
            int[] arr=new int[80000];
            for (int i=0;i<80000;i++){
                arr[i]=(int)(Math.random()*800000); //math.random的范围是[0,1)
            }
            //起始时间
            System.out.println(System.currentTimeMillis());
            insertSort(arr);
            //排序后时间
            System.out.println(System.currentTimeMillis());
        }
        //插入排序
        public static void insertSort(int[] arr){
            int indexVal=0;  //待排序的数
            int beforeIndex=0;
           //分步演示,便于理解
            for (int i=1;i<arr.length;i++){
                //第一轮(101,34,119,1) ==》(34,101,119,1)
                indexVal=arr[i];  //待排序的数
                beforeIndex=i-1;  //待排序前面一个数的索引(从次数开始进行往前遍历)
                //1.首先保证beforeIndex不越界
                //2.保证待插入的值小于与之比较的值后方可进入循环
                //3.满足条件就将待排序前一个数往后移,并将before--继续与前面的数比较
                while (beforeIndex>=0 && indexVal<arr[beforeIndex]){
                    arr[beforeIndex+1]=arr[beforeIndex];
                    beforeIndex--;
                }
                //循环结束后,将待排序数插入(在循环的最后将beforeIndex--作为循环判断条件,所以要把待排序数放在后一位)
                arr[beforeIndex+1]=indexVal;
               // System.out.println("第"+i+"次排序后");
                //System.out.println(Arrays.toString(arr));
            }
    
            /*//第二轮
            indexVal=arr[2];  //待排序的数
            beforeIndex=2-1;  //待排序前面一个数的索引(从次数开始进行往前遍历)
            while (beforeIndex>=0 && indexVal<arr[beforeIndex]){
                arr[beforeIndex+1]=arr[beforeIndex];
                beforeIndex--;
            }
            //循环结束后,将待排序数插入(在循环的最后将beforeIndex--作为循环判断条件,所以要把待排序数放在后一位)
            arr[beforeIndex+1]=indexVal;
            System.out.println("第二次排序后");
            System.out.println(Arrays.toString(arr));
    
            //第三轮
            indexVal=arr[3];  //待排序的数
            beforeIndex=3-1;  //待排序前面一个数的索引(从次数开始进行往前遍历)
            while (beforeIndex>=0 && indexVal<arr[beforeIndex]){
                arr[beforeIndex+1]=arr[beforeIndex];
                beforeIndex--;
            }
            //循环结束后,将待排序数插入(在循环的最后将beforeIndex--作为循环判断条件,所以要把待排序数放在后一位)
            arr[beforeIndex+1]=indexVal;
            System.out.println("第三次排序后");
            System.out.println(Arrays.toString(arr));*/