排序算法之快速排序

最近重新学习了快速排序,在这留下现在的想法,以免以后忘了,还可以重新回来看看。

快排的基本思想:   通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分关键字小,则分别对这两部分继续进行排序,直到整个序列有序。 把整个序列看做一个数组,把第零个位置看做中轴,和最后一个比,如果比它小交换,比它大不做任何处理;交换了以后再和小的那端比,比它小不交换,比他大交换。这样循环往复,一趟排序完成,左边就是比中轴小的,右边就是比中轴大的,然后再用分治法,分别对这两个独立的数组进行排序。

设一个index = a[0],作为基准数,左右排序,把小于index的都移到左边,大于index的移到右边

第一趟,将4作为关键字{4,5,1,2,8,6,7,3,10,9}

{4,5,1,2,8,6,7,3,10,9}       一开始从右侧查找比 数组中 a[j] 比index小的数,没找到就j--;

{4,5,1,2,8,6,7,3,10,9}      当找到a[j]比index小的,则把a[j]的元素放到a[i](一开始应该是a[0]))                                             

{4,5,1,2,8,6,7,3,10,9}               //实现代码 (哨兵i)                         while(a[j]>=index&&i<j) {   j--;    }      

{3,5,1,2,8,6,7,4,10,9}                                                                        if (i<j) {  a[i] = a[j];  i++;   } 

{3,4,1,2,8,6,7,5,10,9}       

{3,4,1,2,8,6,7,5,10,9}            开始查找a[i]比基准数index大的数,a[i]不是则i++,如果找到a[i]比index大,则开始把此时把a[i]的元素

{3,4,1,2,8,6,7,5,10,9}            放到刚才a[j]的位置,重新开始判断a[j],直到i>=j;   在两侧查找的过程中一定要判断好i<j  ,因为在

{3,4,1,2,8,6,7,5,10,9}           每一个过程中都牵扯到了i 与 j 的++ 或者 --,很有可能在某个过程中i 不再 小于  j;

{3,2,1,4,8,6,7,5,10,9}        //实现代码     (哨兵j)                                 while(a[i]<=index&&i<j) {   i++;    }  

第一趟排序结果:{[3,2,1],4,[8,6,7,5,10,9]}                                             if  (i<j) {  a[j] = a[i];  j--;   } 

第二趟排序结果{1,2,3,4,5,6,7,8,[10,9]}

第三趟排序结果:{1,2,3,4,5,6,7,8,[9],10};

 

把以上两个代码块比作两个哨兵  i j ,i的功能就是找到左侧比基准数大的然后放到右边,然后j 的功能就是把在右侧查找比基准数index小的数,放到右边。在判断过程中一定要时刻注意i 与  j 的大小关系,  因为i 与 j 时刻在变化。

在代码实现的过程中

一定要注意取基准数要在判断完i<j之后再取,否则有可能报数组越界异常(ArrayIndexOutOfBoundsException),因为在最后递归过程中,执行i++有可能导致i超出数组边界,然后下一个递归过程中先取基准数会用到a[i],因此会报错

public class QuickSort {

    public static void quickSort(int[] a,int low,int high) {
        int i = low;//
        int j = high;//
       
        if(low>=high) {
            return;        //如果数组中没有元素,直接结束。
        }
        int index = a[low];//排序要比较的基准数,一般取数组的第一个元素
        while(i<j) {
            while(a[j]>=index&&i<j) {   // while用来从右侧查找比index小的数,如果a[j]比 
                                        //  index大,则j往左移
                j--;                    // 继续查找,当找到a[j]比index小之后跳出 while 执行 
                                        // 下面的if语句此时
                                        //如果j还比i大 则把a[j]放到a[i]的位置,i++。
            }                         
            if (i<j) {                 
                                     
                a[i] = a[j];
                i++;
            }
            
            
            while(a[i]<=index && i<j) {
                i++;                      //此时再从左侧查找a[i]比index大的数,
            }                             //与上面过程同理,当找到一个a[i]比index大时,把a[i] 
                                          //放到a[j]处,
            if (i<j) {                    //此时再开始上面的的判断a[j]
                a[j] = a[i];
                j--;
            }
            
        }
        a[i] = index;                //当上面while过程完成后a[i]处是基准数index应该在的位置
        quickSort(a, 0, i-1);        //因此在a[i]放入index
        quickSort(a, i+1, high);     //执行完会分成三部分{ 小于index的数 ,a[i],大于index的数  }
                                     //因此递归两边的数分别再进行排序,直到最后都排完序
        
    }
    
    public static void main(String[] args) {
        
        int[] a = {5,2,1,8,9,3,7,0,4,6};
        quickSort(a, 0, a.length-1);
        
        System.out.println(Arrays.toString(a));
        
    }
    
}

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值