D5-排序算法(一)[Java数据结构和算法]

1.排序也称排序算法(sort Algorithm),排序是将一组数据,依指定的顺序进行排序的过程

  1.1 排序的分类

  (1)内部排序:指将需要处理的所有数据都加在到内部存储器中进行排序。

  (2)外部排序:数据量过大,无法全部加载到内存中,需要借助外部存储进行排序

  1.2 常见的排序

  (1)内部排序:插入排序(直接插入排序,希尔排序),选择排序(简单选择排序,堆排序),交换排序(冒泡排序,快速排序),归并排序,基数排序

  (2)外部排序

  1.3 算法的时间复杂度-衡量一个算法执行时间的两种方法

  (1)事后统计的方法-先运行再看运行时间

    -要想对设计的算法的运行性能进行评测,需要实际运行该程序

    -所得时间的统计量依赖于计算机的硬件软件等环境因素

  (2)事前估算的方法

    -通过分析某个算法的时间复杂度来判断哪个算法更优

  (3)时间频度

    -一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多。一个算法中的语句执行次数称为语句频度或时间频度,记为T(n)。

  (4)时间复杂度

    -一般情况下, 算法中的基本操作语句的重复执行次数是问题规模n的某个函数,用f(n)表示,若有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f(n)的极限值为不等于0的常数,则成f(n)是T(n)的同数量级函数。记作T(n)=O(f(n),为算法的渐进时间复杂度,简称时间复杂度)

    -T(n)不同,但时间复杂度可能相同。

    -计算时间复杂度的方法:

      --用常数1代替运行时间中的所有加法常数

      --修改后的运行次数函数中,只保留最高阶项

      --去除最高阶项的系数

     -常见的时间复杂度

      --常数阶O(1),对数阶O(log2n),线性阶O(n),线性对数阶O(nlog2n),平方阶O(n^2),立方阶O(n^3),k次方阶O(n^k),指数阶O(2^n)

      --常见的算法时间复杂度由小到大次序如上,时间复杂度不断增大,算法的执行效率越低

    -平均时间复杂度:指的是所有可能的输入实例以等概率出现的情况下,该算法的运行时间

    -最坏时间复杂度:一般讨论的时间复杂度均是最坏情况下的时间复杂度,最坏情况吓得时间复杂度是算法在任何输入实例上运行时间的界限

    -平均时间复杂度和最坏时间复杂度是否一样与算法有关

排序法 平均时间 最差情形 稳定度 额外空间 备注
冒泡 O(n2) O(n2) 稳定 O(1)

n小时较好

交换 O(n2) O(n2) 不稳定 O(1) n小时较好
选择 O(n2) O(n2) 不稳定 O(1) n小时较好
插入 O(n2) O(n2) 稳定 O(1) 大部分已排序时较好
基数 O(logRB) O(logRB) 稳定 O(n) B是真数(0-9),R是基数(个十百)
Shell O(nlogn) O(ns)1<s<2 不稳定 O(1) s是所选分组
快速 O(nlogn) O(n2) 不稳定 O(nlogn) n大时较好
归并 O(nlogn) O(nlogn) 稳定 O(1) n大时较好
O(nlogn) O(nlogn) 不稳定 O(1) n大时较好

  (5)算法的空间复杂度

    -算法的空间复杂度(Space Complexity)定义为算法所耗费的存储空间,是对一个算法在运行过程中临时占用存储空间大小的度量。有的算法需要占用的临时工作单元数与解决问题的规模n有关,它随着n的增大而增大,当n较大时,将占用较多的存储单元。

    -算法分析主要讨论的是时间复杂度,用户体验上更加侧重程序执行的速度。一些缓存产品(Redis,memcache)和算法(基数排序)本质就是用空间换时间。

2.冒泡排序(Bubble Sorting)

  2.1 思想:通过对待排序序列从前向后,依次比较相邻元素的值,若发现逆序则交换,使值较大的元素主键从前移向后部。因为排序的过程中,各元素不断接近自己的位置,若一趟比较下来没有进行过交换,说明序列有序,因此在排序过程中设置一个标志flag判断元素是否进行过交换,从而减少不必要的比较(优化可以在冒泡写完后写)。

  2.2 规则

  (1)一共进行数组的大小-1次的大循环

  (2)每一趟排序的次数在逐渐减少

  (3)如果发现在某趟排序中,没有发生一次交换,可以提前结束冒泡排序(优化)

  2.3 源代码

public static void bubbleSort(int[] arr) {
        // TODO Auto-generated method stub
        //冒泡排序演变过程,时间复杂度为O(n^2)
        boolean flag=false;//定义标识变量,表示是否进行过交换,没有交换为false,交换为true
        int temp=0;//临时变量
        for(int i=0;i<arr.length-1;i++) {
            //每一趟开始前都假设为没有交换
            flag=false;
            for(int j=0;j<arr.length-1-i;j++) {
                //如果前面的数比后面的数大,则交换
                if(arr[j]>arr[j+1]) {
                    flag=true;//进行了交换
                    temp=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=temp;
                }
            }
            System.out.printf("第%d趟排序:",i+1);
            System.out.println(Arrays.toString(arr));
            //一趟结束后判断是否进行交换,若一趟都没有交换,则结束冒泡排序
            if(!flag) {
                break;
            }
        }
    }

3.选择排序(select sorting)

   3.1 属于内部排序,是从需要排序的数据中,按照指定的规则选出某一元素,再按照规定交换位置后达到排序的目的。

   3.2 思想:第一次从arr[0]-arr[n-1]中选取最小值,与arr[0]交换,第二次从arr[1]-arr[n-1]中选取最小值,与arr[1]交换....第n-1次从arr[n-2]-arr[n-1]中选取最小值,与arr[n-2]交换,总共通过n-1次,得到一个按排序码从小到大排列的有序序列。

  3.3 说明

  (1)选择排序一共有数组大小-1轮排序

  (2)每1轮排序,又是一个循环,先假定当前这个数是最小数,然后和后面的每个数进行比较,如果发现有比当前数更小的数,就重新确定最小数,并得到下标

  (3)当遍历到数组的最后时,得到本轮最小数和下标

  (4)交换

  3.4 源代码

package cn.atguigu.sort;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

public class SelectSort {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //int[] arr= {101,34,119,1};
        int[] arr=new int[80000];
        for(int i=0;i<80000;i++) {
            arr[i]=(int)Math.random()*8000000;
        }
        
        Date date1=new Date();
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date1Str=simpleDateFormat.format(date1);
        System.out.println("排序前时间"+date1Str);
        
        
        selectSort(arr);
        Date date2=new Date();
        String date2Str=simpleDateFormat.format(date2);
        System.out.println("排序后时间"+date2Str);
    }
    
    public static void selectSort(int[] arr) {
        
        int min=0;
        int minIndex=0;//最小值的下标
        boolean flag=false;
        for(int i=0;i<arr.length;i++) {
            min=arr[i];//假设本身为最小值
            flag=false;
            for(int j=i+1;j<arr.length;j++) {
                if(min>arr[j]) {
                    min=arr[j];//找出a[i+1]-a[n-1]之间的最小值,记住其最小值的下标
                    minIndex=j;
                    flag=true;
                }
            }
            if(flag) {
                //进行交换
                arr[minIndex]=arr[i];
                arr[i]=min;                
            }
        }
    }

}

  

猜你喜欢

转载自www.cnblogs.com/ERFishing/p/11284299.html