数据结构和算法-011 数组排序 快速排序

快速排序(Quicksort)是对冒泡排序的一种改进。

快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。


1算法介绍

快排图快排图

设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。

一趟快速排序的算法是:

1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;

2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];

3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]互换;

4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;

5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。


Note:参考百度百科 http://baike.baidu.com/view/19016.htm


快速排序,理论上最快的排序算法之一。简单的说就是先找一个值(pivot,中文可能解释“枢”),然后将数组分成两个部分(Partition),大于这个值的,和小于这个值的,再重复上面的步骤,直到完成排序。那我们就先看看分组(Partition)是怎么做的。

public class Partitioning {

    public static int[] theArray;
    public static int arraySize;

    public Partitioning(int arraySize) {
        System.out.println("Create a randan array");
        this.arraySize = arraySize;
        theArray = new int[arraySize];
        generateRandomArray();

    }

    public void partitionArray(int pivot) {

        int leftPoint = -1;
        int rightPoint = arraySize;
        while (true) {

            while (leftPoint < arraySize && theArray[++leftPoint] < pivot)
                ;

            while (rightPoint > 0 && theArray[--rightPoint] > pivot)
                ;

            if (leftPoint >= rightPoint)
                break;
            else
                swapValues(leftPoint, rightPoint);
        }
    }

    public static void main(String[] args) {
        Partitioning p = new Partitioning(10);

        p.printArray();
        System.out.println();
        
        System.out.println("Partition array by pivot 30");
        p.partitionArray(30);
        p.printArray();

    }

    public void printArray() {
        StringBuffer sb = new StringBuffer("-");
        for (int i = 0; i<arraySize; i++){
            sb.append("-----");
        }
        
        String septalLine= sb.toString();
        
        System.out.println(septalLine);
        for (int i = 0; i<arraySize; i++){
            if (i/10 == 0)
                System.out.print("|  " + i + " ");
            else 
                System.out.print("| " + i + " ");
        }
        System.out.println("|");
        System.out.println(septalLine);
        for (int i = 0; i<arraySize; i++){
            System.out.print("| " + theArray[i] + " ");
        }
        System.out.println("|");
        System.out.println(septalLine);
    }

    public void swapValues(int indexOne, int indexTwo) {
        int temp = theArray[indexOne];
        theArray[indexOne] = theArray[indexTwo];
        theArray[indexTwo] = temp;
        ;
    }

    public void generateRandomArray() {
        for (int i = 0; i < arraySize; i++) {
            theArray[i] = (int) (Math.random() * 40 + 10);
        }
    }

}


最关键的代码

    public void partitionArray(int pivot) {
        //设两个指针,分别指向数组的最左面和最有面
        int leftPoint = -1;
        int rightPoint = arraySize;
        while (true) {

            //左指针,从左往右扫描,找到大于pivot的值
            while (leftPoint < arraySize && theArray[++leftPoint] < pivot)
                ;
            
            //右指针,从右往左扫描,找到小于pivot的值
            while (rightPoint > 0 && theArray[--rightPoint] > pivot)
                ;
            
            // 退出条件 
            if (leftPoint >= rightPoint)
                break;
            else
                // 交换左右指针的值
                swapValues(leftPoint, rightPoint);
        }
    }


看看结果数组被分成两个部分,数组被分成了两个部分,小于30的 0~4, 和大于30的5~9


输出结果

Create a randan array
---------------------------------------------------
|  0 |  1 |  2 |  3 |  4 |  5 |  6 |  7 |  8 |  9 |
---------------------------------------------------
| 48 | 20 | 36 | 23 | 27 | 10 | 43 | 49 | 26 | 39 |
---------------------------------------------------

Partition array by pivot 30
---------------------------------------------------
|  0 |  1 |  2 |  3 |  4 |  5 |  6 |  7 |  8 |  9 |
---------------------------------------------------
| 26 | 20 | 10 | 23 | 27 | 36 | 43 | 49 | 48 | 39 |
---------------------------------------------------


如果,你看懂的分组(Partition)的代码,那么快速排序就简单了。就是用低轨(Recursion)将分好的数组反复的做分组,直到完成排序。


看代码:


public class QuickSort {
    
    private int [] anArray;
    private int arraySize;
    
    public QuickSort(int arraySize){
        this.arraySize = arraySize;
        anArray = new int[arraySize];
        generateRandomArray();
    }
    
    public void generateRandomArray(){
        for (int i=0; i<arraySize; i++){
            anArray[i] = (int)(Math.random()*50 + 10);
        }
    }
    
    public void printArray() {
        StringBuffer sb = new StringBuffer("-");
        for (int i = 0; i<arraySize; i++){
            sb.append("-----");
        }
        
        String septalLine= sb.toString();
        
        System.out.println(septalLine);
        for (int i = 0; i<arraySize; i++){
            if (i/10 == 0)
                System.out.print("|  " + i + " ");
            else 
                System.out.print("| " + i + " ");
        }
        System.out.println("|");
        System.out.println(septalLine);
        for (int i = 0; i<arraySize; i++){
            System.out.print("| " + anArray[i] + " ");
        }
        System.out.println("|");
        System.out.println(septalLine);
    }

    public void quickSort(int left, int right){
        if(right - left <=0) return ;
        
        else {
            int pivot = anArray[right];
            int partitionLocation = partitionArray(left, right, pivot);
            
            quickSort(left, partitionLocation -1);
            quickSort(partitionLocation+1, right);
        }
        
    }
    
    public int partitionArray(int left, int right, int pivot){
        int leftPoint = left -1;
        int rightPoint = right;
        while (true) {

            while ( anArray[++leftPoint] < pivot)
                ;

            while (rightPoint > 0 && anArray[--rightPoint] > pivot)
                ;

            if (leftPoint >= rightPoint)
                break;
            else
                swapValues(leftPoint, rightPoint);
        }
        swapValues (leftPoint, right);
        return leftPoint;
    }
    
    public void swapValues(int indexOne, int indexTwo) {
        int temp = anArray[indexOne];
        anArray[indexOne] = anArray[indexTwo];
        anArray[indexTwo] = temp;
        ;
    }
    
    
    public static void main(String[] args) {
        System.out.println("Create a Randan Array:");
        QuickSort qs = new QuickSort(20);
        qs.printArray();
        System.out.println();
        System.out.println("Sort the array by Quick Sort algorithem");
        qs.quickSort(0, qs.arraySize-1);
        qs.printArray();
    }

}


输出结果

Create a Randan Array:
-----------------------------------------------------------------------------------------------------
|  0 |  1 |  2 |  3 |  4 |  5 |  6 |  7 |  8 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
-----------------------------------------------------------------------------------------------------
| 40 | 18 | 51 | 59 | 39 | 25 | 42 | 43 | 35 | 54 | 59 | 16 | 31 | 26 | 10 | 24 | 18 | 53 | 24 | 35 |
-----------------------------------------------------------------------------------------------------

Sort the array by Quick Sort algorithem
-----------------------------------------------------------------------------------------------------
|  0 |  1 |  2 |  3 |  4 |  5 |  6 |  7 |  8 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
-----------------------------------------------------------------------------------------------------
| 10 | 16 | 18 | 18 | 24 | 24 | 25 | 26 | 31 | 35 | 35 | 39 | 40 | 42 | 43 | 51 | 53 | 54 | 59 | 59 |
-----------------------------------------------------------------------------------------------------


你可能感兴趣的:(java,排序,数组)