快速排序算法-java

快速算法的思路就是对数组分区排序

一般的先取第一个数作为基准数,然后将整个数列按大小分成两个区,大于基准数的在右边,小于的在左边。然后分别对分区按照上面的方法在进行分区排序,直到整个数组排序好。

下面以一个数组为例:

6,7,1,8,3,9,2,5,10

一般的以第一个数作为基准数,那么怎么才能将大于6的移到右边,小于6的移到左边呢?

假如用6从头到尾比的话,6比7小不动,6比1大换位,这样无法排序(冒泡排序是相邻的两个数比较换位)。

假如再创建一个一样大的空数组,将比6小的放在左边,大的放在右边,剩下的一个位子就是基准数,并记录下它的位子,这样也很麻烦,递归下去需要的中间数会越来越多,而且没有头和尾。另外创建这么多数组也很耗费内存,最好是能够在原来的数组上面进行修改。

既然要分区,肯定有个中间位置,假定中间的指针叫middle,显然这个Middle可以通过比较得出,那么必须要两个指针来表示这个区的位置,假定这个区的开始是left,结尾是right。要递归的分区下去,需要这样三个参数,int[] array, int left,int right 。那么递归什么时候结束呢?当不能再分区的时候就结束了,吗么什么时候不能再分区呢?left=right的时候。

这里最重要的就是一个求分区中间值的函数,我们假定为getMiddle(int array ,int left ,int right)

排序的函数  sort(int [] array,int left ,int right)

按照上面的思路那么这个sort函数的函数体如下

    public void sort(int [] array ,int left ,int right)
    {
           if(left<right)
           {
               int middle=getMiddle(array,left,right);
               sort(array, left, middle-1);//对左边的进行分区
               sort(array, middle+1, right);//对右边的进行分区
           }
    }

现在要实现getMiddle函数,这个函数需要在分区中找到中间的位置,而且要在原数组上进行操作。

首先将该区的第一个即 left 和最后一个即right 进行比较

目的是在右边找到一个数比left指向的数小,并把它替换掉left指向的位置,那么这样替换下去会不会造成left指向的数消失呢?当然持续在右边找的话肯定会这样的,怎么样才能避免这样的问题?那就是右边找完了,替换掉left指向的那个数,即right指向的那个数现在有重复,现在left和right指向的那个数是一样的,就需要在right的左边找到一个数能够取代right的数,这样就从left开始比较,要找到一个比基准数大的去替换掉右边,只要left<right就不停止。当left和right相等的时候这个位置的左边都比基准数小,右边都比基准数大。这个位置就是Middle。

    public int getMiddle(int[] list, int left, int right) {
        int pvoit=list[left];
        while(left<right)
        {
            while(left<right && list[right]>pvoit)
            {
                right--;
            }
            list[left]=list[right];
            while(left<right && list[left]<pvoit)
            {
                left++;
            }
            list[right]=list[left];
        }
        list[left]=pvoit;
        return left;                   //返回中轴的位置
    }

最后测试

    public void quick(int[] str) {
        if (str.length > 0) {    //查看数组是否为空
            sort(str, 0, str.length - 1);
        }
    }

 

原文地址:https://www.cnblogs.com/maydow/p/4484959.html