• 冒泡排序,选择排序,插入排序,快速排序的比较及优化


    第一次写博客,不对的地方欢迎指正大笑

    以下的测试时间只是在本人的电脑上直接运行的,只是简单的对比,并不是标准的时间,可能涉及到后台程序的影响

    冒泡排序:时间复杂度O(n*n),可以从前向后,也可以从后向前进行排序,从后向前(自我感觉还是从后向前好,冒泡不就是向上冒),把最后一个和倒数第二个进行性比较,如果比第一个小就进行交换,这样小的数就换到了倒数第二个,倒数第二个再和倒数第三个进行比较,小再进行交换,直至最小的数被放到了第一个,之后再从后向前进行比较,直至换到第二个位置,以此类推,剩下一个数结束比较。(这个名字起的很形象)
    以下是自己用10000个随机数进行测试,时间只记录排序时间!
    package demo_sort;
    /**
     * 普通的冒泡排序:就像一个个泡向上漂,小的数字与前面的数字挨个进行比较,如果小于前面的就换位置
     */
    
    import java.util.Random;
    
    public class MaoPao {
    	public static void main(String[] args) {
    		Random r=new Random();
    		int array[]=new int[10000];
    		for(int i=0;i<10000;i++){
    			array[i]=r.nextInt(10000);
    		}
    		int lenth=array.length;
    		long begin=System.currentTimeMillis();
    		for(int i=0;i<lenth;i++){
    			for(int j=lenth-1;j>i;j--){
    				if(array[j-1]>array[j]){
    					int temp;
    					temp=array[j-1];
    					array[j-1]=array[j];
    					array[j]=temp;
    				}
    			}
    		}
    		long end=System.currentTimeMillis();
    		System.out.println(end-begin+"ms");
    //		for(int as:array){
    //			System.out.println(as+" ");
    //		}
    	}
    }
    
    

    通过多次运行得到的时间基本上维持在630ms左右

    优化冒泡排序:设置一个标记,如果执行到某个位置标记重新赋值,下次执行判断标记是否符合条件符合执行循环交换(对于已经有排好的可以优化很多时间)
    同样是10000个随机数
    package demo_sort;
    /**
     * 优化的冒泡排序:如果给定的数组中已经有按照顺序排列的数字,不必要进行多次循环比较
     * 不加优化:110多ms
     * 加优化:1ms
     */
    import java.util.Random;
    
    public class MaoPaoTest {
    	public static void main(String[] args) {
    		Random r=new Random();
    		int array[]=new int[10000];
    		for(int i=0;i<10000;i++){
    			array[i]=i;
    		}
    		int lenth=array.length;
    		int flag=1;
    		long begin=System.currentTimeMillis();
    		for(int i=0;i<lenth&&flag==1;i++){
    			flag=0;
    			for(int j=lenth-1;j>i;j--){
    				if(array[j-1]>array[j]){
    					int temp=array[j-1];
    					array[j-1]=array[j];
    					array[j]=temp;
    					flag=1;
    				}
    			}
    		}
    		long end=System.currentTimeMillis();
    		System.out.println(end-begin);
    	}
    
    }
    

    对于以上排好序的数组不加优化110ms,加了优化时间大幅价绍1ms
    选择排序:选择排序顾名思义,选择出来进行排序,最开始先遍历一遍数组,选择出来最小的值放在数组第一个位置,之后再对第二个元素之后的元素进行遍历,选择出来最小的值放在这个子无序序列的第一位,也就是数组的第二个元素,这样前两个数就排完了,以此类推,复杂度O(n*n)
    package demo_sort;
    /**
     * 选择排序算法
     */
    
    import java.util.Random;
    
    public class SelectSort {
    	public static void main(String[] args) {
    //		int array[]=new int[]{9,6,3,2,8,7};
    		Random r=new Random();
    		int array[]=new int[10000];
    		for(int i=0;i<10000;i++){
    			array[i]=r.nextInt(10000);
    		}
    		int lenth=array.length;
    		long begin=System.currentTimeMillis();
    		for(int i=0;i<lenth;i++){
    			for(int j=i+1;j<lenth;j++){
    				if(array[i]>array[j]){
    					int temp=array[i];
    					array[i]=array[j];
    					array[j]=temp;
    				}
    			}
    		}
    		long end=System.currentTimeMillis();
    		System.out.println(end-begin+"ms");
    //		for(int a:array){
    //			System.out.println(a);
    //		}
    	}
    
    }
    

    时间维持在700ms左右
    插入排序:插入排序复杂度也是O(n*n),涉及到了元素的移动。先把数组中的第一个元素看成有序数列,查找与这个有序数列相邻元素,与有序数列中的每个元素进行比较,插入到合适的位置,直至有序数列中的元素和原数组元素相等排序完成。
    package demo_sort;
    
    import java.util.Random;
    
    public class InsertSort2 {
        public static void main(String[] args) {
    //        int array[]=new int[]{9,1,4,3,6};
            int array[]=new int[10000];
            Random r=new Random();
            for(int i=0;i<10000;i++){
                array[i]=r.nextInt(10000);
            }
            long begin=System.currentTimeMillis();
            for(int i=1;i<array.length;i++){
                for(int j=i;j>0;j--){
                    if(array[j-1]>array[j]){
                        int temp=array[j];
                        array[j]=array[j-1];
                        array[j-1]=temp;
                    }
                }
            }
            long end=System.currentTimeMillis();
            System.out.println(end-begin+"ms");
    //        for(int a:array){
    //            System.out.println(a);
    //        }
        }
    
    }
    
    

    几次测试都会维持在200ms左右,相比以上的排序已经好不少,它是稳定排序,不改变相同元素原来的顺序。
    优化的插入排序:
    package demo_sort;
    
    import java.util.Random;
    
    public class InsertSort1 {
    	public static void main(String[] args) {
    //		int array[]=new int[]{9,5,8,1,4};
    		int array[]=new int[10000];
    		Random r=new Random();
    		for(int i=0;i<10000;i++){
    			array[i]=r.nextInt(10000);
    		}
    		long begin=System.currentTimeMillis();
    		for(int i=1;i<array.length;i++){
    			int temp=array[i];
    			int j=i-1;
    			while(j>=0&&array[j]>temp){
    				array[j+1]=array[j];
    				j--;
    			}
    			if(j!=i-1){
    				array[j+1]=temp;
    			}
    		}
    		long end=System.currentTimeMillis();
    		System.out.println(end-begin+"ms");
    //		for(int a:array){
    //			System.out.println(a);
    //		}
    	}
    
    }
    
    优化后10000个元素,排序用时80ms左右,和基本的插入排序相差一半,主要相差在循环上,减少不必要的循环
    快速排序:,快速排序要求选择的枢轴值两边子序列长度最好一致,快速排序的时间消耗上主要在对元素的划分上,元素数量为k的数组,共需要比较k-1次。快速排序主要在于选择基准,如果选择的基准刚好是最小的或者最大的元素,那么这时候时间复杂度最大为O(n*n),如果刚好选择的基准就是这个无序序列的中值,时间复杂度最小为O(nlgn),总的关键字比较次数:O(nlgn)
    快速排序对于数组元素重复率高的不适用。
    快速排序为社么快,这里要提到一个分治思想,分而治之,虽然用到的是递归,虽然也有最坏情况下和冒泡,选择排序相等的时间复杂度,但是,分治思想是关键,把一个大问题分成两个小问题,分别同时处理,这两个小问题再向下分,最后问题也就水落石出了,分治思想避免了做无用功,选择一个基准,大于他的数在他的右面,小于他的数在他的左面,在进行比较的时候,左面的数只在左面进行比较就可以,没有必要再去右面比较,这样节省了时间
    package demo_sort;
    
    import java.util.Random;
    
    public class QuickSort {
    	public static void main(String[] args) {
    		Random r=new Random();
    		int a[]=new int[10000];
    		for(int i=0;i<10000;i++){
    			a[i]=r.nextInt(10000);
    		}
    		long begin=System.currentTimeMillis();
    		sort(a,0,a.length-1);
    		long end=System.currentTimeMillis();
    		System.out.println(end-begin);
    //		for (int i = 0; i < a.length; i++) {
    //			System.out.println(a[i]);
    //		}
    	}
    
    	public static void sort(int[] a, int low, int hight) {
    		int i, j, index;
    		if (low > hight) {
    			return;
    		}
    		i = low;
    		j = hight;
    		index = a[i];
    		while (i < j) {
    			while (i < j && a[j] >= index) {
    				j--;
    			}
    			if (i < j) {
    				a[i++] = a[j];
    			}
    
    			while (i < j && a[i] < index) {
    				i++;
    			}
    			if (i < j) {
    				a[j--] = a[i];
    			}
    
    		}
    		a[i] = index;
    		sort(a, low, i - 1);
    		sort(a, i + 1, hight);
    	}
    
    }
    
    几次运行的结果都会在80ms左右,这是在随机的条件下,其中有一次20ms,可见快速排序非常对得起他这个名字



  • 相关阅读:
    2018.11.21 struts2获得servletAPI方式及如何获得参数
    2018.11.20 Struts2中对结果处理方式分析&struts2内置的方式底层源码剖析
    2018.11.19 Struts2中Action类的书写方式
    2018.11.18 Sturts2配置详解&常量配置进阶
    2018.11.17 Struts2框架入门
    需求分析
    可行性研究
    防火墙
    homework1
    静态网页开发技术
  • 原文地址:https://www.cnblogs.com/duzhentong/p/7816604.html
Copyright © 2020-2023  润新知