快速排序

快速排序

与归并排序相同,快速排序也使用了分治思想。算法设计思路:

分解:假设待排序数组A[p,r],将其划分为两个(可能为空)子数组A[p…q-1]和A[q+1…r],使得A[p…q-1]中的每一个元素都小于等于A[q]而A[q]则小于A[q+1…r]中的每一个元素。计算下标q也是划分过程的一部分

解决:通过递归调用快速排序对子数组进行排序。

合并:因为子数组都是原址排序的,所以不需合并操作。

下面代码为快速排序

Quicksort(A,p,r)
  if p < r
     q = Partition(A,p,r)  //划分方法将数组A[p..r]划分为两部分并返回划分界限的下标。q将不参与子数组的排序
     Quicksort(A,p,q-1)       //递归快速排序处理划分好的子数组
     Quicksort(A,q+1,r)

对于排序数组A的全部数据初始调用为Quicksort(A,1,A.length)

对于快速排序其核心在于对数组的划分即函数Partition

下面代码将实现数组的划分:

Partition(A,p,r)
 x = A[r]             //选择主元,选择一个元素将其作为划分的依据,这里选择待划分数组的最后一个元素最为方便
 i = p-1              //将i指针置在数组的前一位
 for j = p to r-1     //遍历数组A[p..r-1]
     if A[j]<=x       //当一次遍历中遍历元素的值小于等于主元值时
         i=i+1        //指针i向前进一
         exchange A[i] with A[j]  //将A[j]中的元素与A[i]交换
 exchange A[i+1] with A[r] //遍历结束后将A[i+1]的值与主元交换,此时一i+1为界限完成了对数组A[p,r]的划分
 return i+1                //向排序算法返回划分的界限i+1

对于Partition(A,p,r)算法将数组最后一个元素A[r]的值作为划分依据,遍历数组A[p…r-1],在划分过程中实际上把数组用i,r划分为A[p…i],A[i+1…r-1],A[r]三各部分期中每当遍历检索到一个小于等于A[r]的元素则i自增1A[p…i]长度增加一位并将检索到的元素的值与新增加的元素的值进行交换,在完成整个遍历之后A[p…i]中的元素都小于等于A[r]而A[i+1…r-1]中的元素都大于A[r]。最终将A[r]的值与A[i+1]交换将整个数组变成了一个以A[i+1]为界限划分了的数组,并向上层排序算法返回分界点。

以简单无序数列模拟快速排序,每一次排序的分界值将加粗

5 2 3 4 8 5 9 6 1 7

5 2 3 4 5 6 1 7 8 9

1 2 3 4 5 6 5 7 8 9

1 2 3 4 5 5 6 7 8 9

1 2 3 4 5 5 6 7 8 9

1 2 3 4 5 5 6 7 8 9

1 2 3 4 5 5 6 7 8 9

package QuickSort;

public class QuickSort {
    private int[]  A;

    public int[] getA() {
        return A;
    }

    public void setA(int[] a){
        this.A = quickSort(a,0,a.length-1);
    }
    //快速排序传入参数分别为排序数组,排序区间起始,排序区间末尾。
    public int[] quickSort(int[] a,int aStart,int aEnd){
        if(quickCheak(a,aStart,aEnd)) {
            if (aStart < aEnd) {
                int p = partition(a,aStart,aEnd);
                quickSort(a,aStart,p-1);
                quickSort(a,p+1,aEnd);
            }
        }
        return a;
    }
    //检测待排序区间是否已有序。
    public boolean quickCheak(int[] a,int aStart,int aEnd){
        int temp = 0;
        for (int i = aStart;i <= aEnd-1;i++){

            if(a[i] > a[i+1]){
                temp++;
            }
        }
        if(temp != 0){
            return true;
        }
        else {
            return false;
        }
    }
    //快速排序核心实现排序区间的划分,将排序区间以标志王牌(joker)划分成两个区间
    public int partition(int[] a,int aStart,int aEnd){
        int joker = a[aEnd];//将区间终止位的元素作为划分依据joker。
        int i = aStart - 1;
        for (int j = aStart; j < aEnd;j++){
              if(a[j] <= joker){
                  int temp;
                  i = i + 1;
                  temp = a[i];
                  a[i] = a[j];
                  a[j] = temp;
              }
            }
        a[aEnd] = a[i+1];
        a[i+1] = joker;
        return i+1;
        }

}


//测试模块
import QuickSort.QuickSort;

public class Test {
    public static void main(String[] args) {
        int[] a = {96,38,78,54,14,23,74,12,63,45,41,};
        QuickSort q = new QuickSort();
        q.setA(a);
        for (int p:q.getA()
             ) {
            System.out.println(p);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值