zoukankan      html  css  js  c++  java
  • 算法相关——Java排序算法之快速排序(三)

    0. 前言

    本系列文章将介绍一些常用的排序算法。排序是一个非常常见的应用场景,也是开发岗位面试必问的一道面试题,有人说,如果一个企业招聘开发人员的题目中没有排序算法题,那说明这个企业不是一个正规的企业,哈哈,虽然有点戏谑,但是也从侧面证明了排序算法的重要性。

    本文将介绍的是常见排序算法中的快速排序


    3.       快速排序

    3.1  基本思想

    快速排序是一种比较快的排序算法,其基本思想为设置两个指针ij分别指向第一个和最后一个待排元素i向后移动,j向前移动,一般选第一个数为标准数,从后面开始,j向前移动时找到第一个比标准小的数,互换位置,然后再从前面,找到第一个比标准大的数,互换位置,第一趟的结果就是标准左边的所有数都小于标准数,右边的所有数都大于标准数,分成两拨后,再对左右两拨继续递归的使用上述方法,最终使整个序列有序。


    3.2  代码实现

    /*
    *@author Calvin
    *@blog http://blog.csdn.net/seu_calvin/article/details/55193059
    *@date 2017/01/31
    */
    
    public class Order {
    	private int[] array; 
    	public Order(int[] array){
    		this.array = array;
    	}
    	
        public void sort() {
           if(array!=null){
               quickSort(array,0,array.length-1);
           }
        } 
        
        public void quickSort(int[] array, int begin, int end){
        	if(begin < end){
        		int key = array[begin];
        		int i = begin;
        		int j = end;
        		
        		while(i < j){
        			while(i < j && array[j]>key){
        				j--;
        			}
            		if(i < j){
            			array[i] = array[j];
            			i++;
            		}
        			while(i < j && array[i]<key){
        				i++;
        			}
            		if(i < j){
            			array[j] = array[i];
            			j--;
            		}
        		}
        		//循环完了把最后一个空位i赋值给key
        		array[i] = key;
        		//递归完成两个自序列排序
        		quickSort(array,begin,i-1);
        		quickSort(array,i+1,end);
        		
        	}
        }
        
        public void print() {  
            for(int i = 0; i < array.length; i++)
         	        System.out.println(array[i]);
        }  
          
        public static void main(String[] args) {  
            int[] array = new int[]{3,1,5,9,6,5,0}; 
            Order order = new Order(array); 
            order.sort();
            order.print();
        }  
      
    }
    
    输出结果略。


    3.3  性能特点

    快速排序是冒泡排序的一种改进,后者是相邻元素的比较交换,前者是跳跃式交换,因此总得比较次数和交换次数少了很多,因此效率较高。快速排序的时间复杂度为O(nlogn),空间复杂度为O(logn)。快排真正消耗空间是在递归调用上,因为每次递归都要保持一些数据。而且快速排序算法是不稳定的,因为相同值的元素在排序后的相对应的位置会改变。


    3.4  可以优化的点

    快速排序法在性能上有着很大优势,当然快排也会有一些优化方法,但是快排本身简单易用,因此大多数情况下使用快排就足够了。下面介绍几个快排的优化方法

    1)标准数的选择一直是第一个可能会导致算法性能很差,可以考虑选头尾中间三个数取中间大小的数为标准数,这样就能对一些情况进行优化。

    2快排在数据量较小时性能并不比其他算法好,因此可以考虑在待排序列为10左右时,选择其他排序算法继续进行排序。

    3利用计算机的多线程并行处理来提高快排的执行效率。这不是对算法本身的优化,而是对算法使用上的优化。


    3.5  和堆排序的比较

    堆排序(后面会总结到)和快排哪个效率更好呢?两者时间复杂度相同,但是空间复杂度堆排序貌似更胜一筹,答案是快速排序比堆排序的效率高很多,并且随着数据规模的扩大,二者的差距不断扩大,快速排序的优势越来越明显。因此堆排比较少被使用。原因总结如下:

    1)首先要明确第一点,数学上的时间复杂度不代表实际运行时的情况。

    2堆排比较的几乎都不是相邻元素,对cache极不友好,堆排中比较父节点和字节点的值大小的时候,虽然计算下标会很快完成,在大规模的数据中对数组指针寻址也需要一定的时间。而快速排序只需要将数组指针移动到相邻的区域即可。

    3)堆排序中删除堆顶后的将最后的元素放到堆顶,再让其自我调整。这样有很多比较将是被浪费的,因为被拿到堆顶的那个元素几乎肯定是很小/大的,而靠近堆顶的元素又几乎肯定是很小/大的,最后一个元素能留在堆顶的可能性微乎其微,而且很有可能最终再被移动到底部。


  • 相关阅读:
    Everything
    图片在下载过程中由模糊逐渐变清晰的技巧
    Windows下Critical Section、Event、Mutex、Semaphores区别
    二维Cookie操作(JS和ASP)
    ASP.net利用urlMappings重写URL路径(URL映射)
    GHOST (以硬盘为单位和以分区分区为单位还原)>个人观点:)
    简单计算器
    ASP操作COOKIE
    擦亮自己的眼睛去看SQLServer之谈谈锁机制
    SQL SERVER2008跟踪标志
  • 原文地址:https://www.cnblogs.com/qitian1/p/6461436.html
Copyright © 2011-2022 走看看