排序-快速排序

快速排序:

快速排序是最流行的排序算法,在大多数情况下,快速排序都是最快的,执行时间为O(N*logN)级。
快速排序算法本质上通过把一个数组划分为两个子数组,然后递归调用自身为每一个子数组进行快速排序实现的。
快速排序有三个基本的步骤:
1.把数组或者子数组分成左边(较小的关键字)的一组和右边(较大的关键字)的一组
2.调用自身对左边进行排序
3.再次调用自身对右边的一组进行排序。

经过一次划分之后,所有在左边子数组的数据项都小于在右边子数组的数据项,只要对左边子数组和右边子数组分别进行排序,整个数组就是有序的了,也通过递归调用排序算法自身就可以。

传递给recQuickSort()方法的参数决定了要排序数组的左右两端位置,这个方法首先检查数组是否只包含一个数据项,如果数组只包含一个数据项,那么就定义数组已经有序,方法立即返回,这就是递归的基值条件(递归的出口)。

如果数组包含两个或者更多的数据项,算法就调用partitionIt()方法对数组进行划分。方法返回分隔边界的下标数值(partition),它指向右边(较大关键字)z子数组最左端的数据项。

这里写图片描述

对数组进行划分之后,recQuickSort()递归的调用自身,数组左边的部分调用一次,对从left到partition-1位置上的数据项进行排序,数组右边的部分也调用一次,对从partition到right位置上的数据项进行排序。注意这两个递归都不包含数组下标为partition的数据项,为什么呢?原因在于轴值(枢纽)的选择

选择轴值:partitionIt()方法应该使用什么样的轴值呢,下面是一些相关的想法:
–应该选择具体的一个数据项的关键字的值作为轴值,这个数据项称为pivot(轴值)
–可以选择任意一个数据项作为轴值。为了简便,我们总是假设总是选择待划分的子数组的最右端的数据项作为轴值
—划分完成之后,如果轴值插到左右子数组之间的分界处,那么轴值就落在排序之后的最终位置上。

这里写图片描述

为了实现把把轴值放入正确位置的操作,只要交换轴值和右边子数组的最左端的数据项就可以了。这个交换操作把轴值放在了正确的位置上,也就是左右子数组之间

完整代码:


public class QuickSortTest
{
    private  int[]  array;
    private  int  number;
    public  QuickSortTest(int  max)
    {
        array = new int[max];
        number = 0;
    }

    public  void insert(int  value)
    {
        array[number] = value;
        number++;
    }
    public  void display()
    {
        for (int i = 0; i < number; i++)
        {
            System.out.print(array[i]+" ");
            System.out.print(" ");
        }
    }

    public  void quickSort()
    {
        recQuickSort(0, number-1);
    }

    //递归调用的方法
    public  void recQuickSort(int  left,int  right)
    {
        if(right -left <= 0)
            return;
        else
        {
            int pivot =array[right]; //选定最右边元素作为轴值

            int partition = partitionIt(left, right, pivot);
            recQuickSort(left, partition-1);  //递归,将左边的元素排序
            recQuickSort(partition+1, right);  //递归,将右边的元素排序

        }
    }

    //分隔数组的方法
    public  int partitionIt(int  left,int right,int  pivot)
    {
        int leftPointer= left-1;   //左指针
        int rightPointer= right;    //右指针
        while(true)
        {
            //左指针移动,移动到下一个元素比轴值小  ,不用交换
            //因为我们的目的是找到所有比轴值小的元素放在轴值左边,所有比轴值大的元素放在轴值右边
            while(array[++leftPointer] < pivot); 
            //右指针移动,移动到下一个元素如果比轴值大,不用交换
            while(rightPointer>0   &&  array[rightPointer--]>pivot);
            //z左指针大于等于右指针,也就是两个指针相遇了,就停下来。
            if(leftPointer >= rightPointer)
            break;
            else
            swap(leftPointer,rightPointer);
        }
        swap(leftPointer,right); //将轴值与左指针交换
        return leftPointer;  //返回轴值的位置
    }

    //用于交换两个元素的方法
    public   void  swap(int  index1,int index2)
    {
        int  temp =array[index1];
        array[index1] = array[index2];
        array[index2] = temp;
    }


    public static void main(String[] args)
    {
        int  max=16;
        QuickSortTest  array=new QuickSortTest(max);
        array.insert(76);
        array.insert(78);
        array.insert(78);
        array.insert(7);
        array.insert(8);
        array.insert(478);
        array.insert(728);
        array.quickSort();
        array.display();
    }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值