zoukankan      html  css  js  c++  java
  • 快速排序精讲

    快速排序是对于冒泡排序的改进

    在这里插入图片描述
    那么它是如何改进的呢??
    假设有n个记录值,冒泡排序的排序过程的最差情况经历n-1趟排序,每一趟排序中
    前后相邻的值进行交换,每个值逐步地移动到它应该有的位置,序列从无序状态到渐进到有序状态(每次交换都是相邻交换),经过n-1趟交换效果的累积,终于达到整体有序
    相比之下快速排序呢是粗精度到高精度的冒泡排序,首先选取一个PivoKey,用以将序列分成相邻的2段,左边为小值,右边为大值,然后分别对左右部分递归地进行快排,从大范围缩小到小范围,通过较大的跨步,来逐渐靠近所应该在的位置。
    (假设其原来在左边,应该的位置在右边,通过快排可以一下子交换过来到右边,而冒泡只能一步步前后交换来到右边,相比之下,大步伐比小步伐走得当然要快)

    算法的大致思路:
    1.设置PivotKey,同时设置low和high指针,low为最前面元素指针,high为后面元素指针,PivotKey一般为方便取最前面元素L->r[0]=L->r[low]。

    那么我可不可以不取L->r[0]而随意取一个数值呢?可以的,只不过稍微比较麻烦一点,详情请见后面解析

    2.通过high–不断往前面查找,直到找到某个元素小于PivotKey
    将L->r[high]赋值L->r[low]。
    (此处不会覆盖原有的L->r[low]值,
    因为L- >r[low]=PivotKey得到保留。赋值完后L->r[high]=L->r[low],按道理我们可以将PivoKey赋值给L->r[high],达到交换值的效果。但是我们的目标是找到PivoKey的位置,并且给这个位置赋值PivoKey,如果此处赋值的话L->r[high]又会被第三步中的赋值覆盖掉,导致此处赋值多余)
    3.通过low++,不断往后面查找,直到有某个元素大于PivotKey,
    L->r[low]赋值L->r[high]
    (此处L->r[high]其实多余,因为在上一步中已经移走,所以将L->r[low]赋值L->r[high]不会因为覆盖而丢失值)
    4.重复上述第2步至第3步,直到low=high,返回low值。
    (通过不断的比较逼近找到PivotKey值的位置,当low=high时,这个位置就是此Pivot值在最后序列中的位置)
    5.通过以上步骤,无序序列已经分为以PivoKey为界,左小右大的两部分。接下来对左右两部分递归执行上述1~4步
    在这里插入图片描述

    #include <stdio.h>
    #include <stdlib.h>
    #define MAXSIZE 30
    typedef struct{
         int  r[MAXSIZE];
         int length;
    }SqList;
    
    int  Partition(SqList *L,int low,int high){
           int  Pivokey=L->r[low];
           while(low<high){
                while(low<high&&L->r[high]>=Pivokey)
                      --high;//当Pivokey,为最小值时high--可能指针越界,所以需要设置low<high
                L->r[low]=L->r[high];
                while(low<high&&L->r[low]<=Pivokey)
                      ++low;//当Pivokey,为最小值时low++可能指针越界,所以需要设置low<high
                L->r[high]=L->r[low];
           }
           L->r[low]=Pivokey;//确定位置后赋值PivotKey
           return  low;//返回位置
    }
    
    void QSort(SqList *L,int low,int high){
         if(low<high){
            int mid=Partition(L,low,high);
            if(mid!=low) //如果刚好是最小值,就会mid=low,此时无需再比较左端
               QSort(L,low,mid-1);
            if(mid!=high)//如果刚好是最大值,就会mid=high,此时无需再比较右端
               QSort(L,mid+1,high);
         }
         return;
    }
    
    void QuickSort(SqList *L){
         QSort(L,0,L->length-1);
         return;
    }
    
    int main()
    {
        SqList L;
        L.length=12;
        for(int i=0;i<12;i++)
            scanf("%d",&L.r[i]);
        printf("Befor Sort:
    ");
        for(int i=0;i<12;i++)
            printf("%d	",L.r[i]);
        QuickSort(&L);
        printf("
    After Sort:
    ");
        for(int i=0;i<12;i++)
            printf("%d	",L.r[i]);
        return 0;
        return 0;
    }
    
    

    在这里插入图片描述
    那么回到之前留下的一个问题:
    如果随意取一个数组元素值该怎么样呢??
    假如赋值L->r[4]赋值给PivotKey,则仍然是从high–找小于PivotKey值,只不过当找到以后L->r[high]不能赋值给L->r[low],而是首先赋值给L->r[4],因为之前L->r[4]赋值给PivotKey,值得以保留,如果赋值给L->r[low],则会出现L->r[low]原值被覆盖丢失
    接下来的步骤便与之前相同,从low++寻找到大于PivotKey的值后赋值给L->r[high],因为原来的L->r[high]赋值给了L->r[4]得以保留。

  • 相关阅读:
    django QuerySet对象转换成字典对象
    HTTP请求中三种参数类型
    django开发中遇到的问题
    win7下mysql8.0.12解压缩版安装
    Django小部件
    程序员上班有什么提高效率的技巧?
    Android应用AsyncTask处理机制详解及源码分析
    Android常用工具类
    Android Volley解析
    Android 开发有哪些新技术出现?
  • 原文地址:https://www.cnblogs.com/zhichao-yan/p/13368514.html
Copyright © 2011-2022 走看看