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是基数(个十百)
ShellO(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;                
            }
        }
    }

}

 

  

 

转载于:https://www.cnblogs.com/ERFishing/p/11284299.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值