快速排序(JAVA版)

快速排序

快速排序是冒泡排序的改进版,是目前已知的最快的排序方法。

已知一组无序数据a[1]、a[2]、……a[n],需将其按升序排列。首先任取数据a[x]作为基准(pivot)。比较a[x]与其它数据并排序,使a[x]排在数据的第k位,并且使a[1]~a[k-1]中的每一个数据<a[x],a[k+1]~a[n]中的每一个数据>a[x],然后采用分治的策略分别对a[1]~a[k-1]和a[k+1]~a[n]两组数据进行快速排序。

基本思想:

1、首先选取以及基准(pivot),这里选取数组最右侧的元素

2、将数组中比基数小的元素放在数组的左边,将数组中比基准大的元素放在基准的右边。具体的方法是设置两个扫描指针leftPtr和rightPtr。leftPtr指向数组的第一个元素的前一个位置,rightPtr指向数组倒数第一个元素。leftPtr向右扫描比基准(pivot)大的元素,leftPtr右移,rightPtr向左扫描比左准(pivot)小的元素,rightPtr左移,同时交换leftScan扫描到的比基准(pivot)大的元素和rightScan扫描到的比基准(pivot)小的元素。直到leftScan与rightScan相遇,一次分组完成。

3、依次对两组数组进行快速排序。

 

public class quickSort {

    public static void main(String[] args)

    {

       int maxSize=100;

       ArrayPar arr;

       arr=new ArrayPar(maxSize);

       arr.insert(77);

       arr.insert(99);

       arr.insert(44);

       arr.insert(55);

       arr.insert(22);

       arr.insert(88);

       arr.insert(11);

       arr.insert(00);

       arr.insert(66);

       arr.insert(33);

       arr.display();

       arr.quickSort();

       arr.display();

    }

}

 

class ArrayPar

{

    private int[] a;

    private int nElems;

   

    //构造函数

    public ArrayPar(int max)

    {

       a=newint[max];

       nElems=0;

    }

   

    //插入数据

    public void insert(int value)

    {

       a[nElems]=value;

       nElems++;

    }

   

   

    //显示数组数据

    public void display()

    {

       for(int j=0;j<nElems;j++)

           System.out.println(a[j]+" ");

           System.out.println(" ");

    }

   

    //交换元素

    public void swap(int one,int two)

    {

       int temp=a[one];

       a[one]=a[two];

       a[two]=temp;

    }

   

   

    //分组

    public void reQuickSort(int left,int right)

    {

       if(right-left<=0)

           return;

       else

       {

           int pivot=a[right];

           intpartition=partitionIt(left,right,pivot);

           reQuickSort(left,partition-1);

           reQuickSort(partition+1,right);

       }

    }

    public void quickSort()

    {

       reQuickSort(0,nElems-1);

    }

   

    //分组

   

    public int partitionIt(int left,int right,int pivot)

    {

       int leftPtr=left-1;

       int rightPtr=right;

       while(true)

       {

           while(a[++leftPtr]<pivot);

           while(rightPtr>0&&a[--rightPtr]>pivot);

           if(leftPtr>=rightPtr)

              break;

           else

              swap(leftPtr,rightPtr); 

       }

       swap(leftPtr,right);

       return leftPtr;

    }

}

分析快速排序分析:

第一次分组过程:(直到数组的leftPtr>=rightPtr,第一次分组过程结束)

原数组:    77 99 44 55 22 88 11 066 33   基准选最后一个元素 33

      leftPtr=-1往右找比33大的数  往右找比33小的数rightPtr=9

 

找第一个比基准33大的元素和第一个比基准33小的元素 

 77 99 44 55 22 88 11 0 66 33   基准选最后一个元素 33

      leftPtr=0往右找比33大的数  往右找比33小的数rightPtr=7

第一次交换后的数组:

 0 99 4455 22 88 11 77 66 33 

     

leftPtr=0               rightPtr=7

 

 

找第二个比基准33大的元素和第二个比基准33小的元素 

 0 99 44 55 22 88 11 77 66 33   基准选最后一个元素 33

         leftPtr=1             rightPtr=6

第二次交换后的数组:

 0 11 4455 22 88 99 77 66 33 

     

leftPtr=1               rightPtr=6

 

找第三个比基准33大的元素和第二个比基准33小的元素

 0 99 44 55 22 88 11 77 66 33   基准选最后一个元素 33

            leftPtr=2   rightPtr=4

第三次交换后的数组:

 0 11 22 55 44 88 99 77 66 33 

     

leftPtr=2  rightPtr=4

 

找第四个比基准33大的元素和第四个比基准33小的元素

 0 11 22 55 44 88 99 77 66 33   基准选最后一个元素 33

      rightPtr=2       leftPtr=3 

此时rightPtr<leftPtr,将leftPtr所指元素与基准交换位置,得到第一次的分组,第一次分组结束。

第一次分组后的数组:

         0 11 22 33 44 88 99 77 66 55

一般情况下,快速排序的效率为:o(N*logN),是目前最快的排序算法。但是,当将本方法运用到完全逆序的数组排序时,效率降到了o(N*N)。

改进如下:



public class quickSort {
public static void main(String[] args)
{
int maxSize=100;
ArrayPar arr;
arr=new ArrayPar(maxSize);
arr.insert(77);
arr.insert(99);
arr.insert(44);
arr.insert(55);
arr.insert(22);
arr.insert(88);
arr.insert(11);
arr.insert(00);
arr.insert(66);
arr.insert(33);
arr.display();
arr.quickSort();
arr.display();
}
}


class ArrayPar
{
private int[] a;
private int nElems;

//构造函数
public ArrayPar(int max)
{
a=new int[max];
nElems=0;
}

//插入数据
public void insert(int value)
{
a[nElems]=value;
nElems++;
}


//显示数组数据
public void display()
{
for(int j=0;j<nElems;j++)
System.out.println(a[j]+" ");
System.out.println(" ");
}

//交换元素
public void swap(int one,int two)
{
int temp=a[one];
a[one]=a[two];
a[two]=temp;
}

//找出中间值作为基准
public int medianOf3(int left,int right)
{
int center=(left+right)/2;
if(a[left]>a[center])
swap(left,center);
if(a[left]>a[right])
swap(left,right);
if(a[center]>a[right])
swap(center,right);
swap(center,right-1);
return a[right-1];
}

public void manualSort(int left,int right)
{
int size=right-left+1;
if(size<=1)
return;
if(size==2)
{
if(a[left]<a[right])
swap(left,right);
return;
}
else
{
if(a[left]>a[right-1])
swap(left,right-1);
if(a[right-1]>a[right])
swap(right,right-1);
if(a[left]>a[right])
swap(left,right);
}
}


//分组
public void reQuickSort(int left,int right)
{
int size=right-left+1;
if(size<=3)
manualSort(left,right);  //数组小进行手动排序
else                         //数组大进行快速排序
{
int median=medianOf3(left,right);
int partition=partitionIt(left,right,median);
reQuickSort(left,partition-1);
reQuickSort(partition+1,right);
}
}
public void quickSort()
{
reQuickSort(0,nElems-1);
}



public int partitionIt(int left,int right,int pivot)
{
int leftPtr=left;
int rightPtr=right-1;
while(true)
{
while(a[++leftPtr]<pivot);
while(rightPtr>0&&a[--rightPtr]>pivot);
if(leftPtr>=rightPtr)
break;
else 
swap(leftPtr,rightPtr);
}
swap(leftPtr,right-1);
return leftPtr;
}


}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值