zoukankan      html  css  js  c++  java
  • 理解快速排序

    快速排序(QuickSort)

    1 原理

         快速排序是基于分治思想上的排序,由冒泡排序改进而来.排序效率较高,时间复杂度:O(n*lgn),最坏时是:O(n^2).主要思想如下:

         1 选取基准元素(一般为第一个或最后一个元素)进行分解

         2 将分解后的子数组再排序

         3 合并

    2 实例

        下面结合具体的例子分析:

        数组如下:

    0 1 2 3 4 5

    6

    5  98 45 134 23 54

    78

     

        首先 i = 0, j = 6,temp(哨点)=num[i]=5

        此时已经有temp这个变量保持num[0]的值了,可理解为在此处挖了个坑,需要其他的数据来填充.下面就从j开始往左一直找到一个比temp小的值,然后放在num[0]处,此例中5为最小的所以直到j变为0跟i相等才会停止.i= j = 0,,这样第一轮就结束,i的值没变仍为0,num[0]=temp.就说明num[0]是最小的,这样就把数组分成了两部分:左边的为空,右边的从num[1]~num[6].

        下面要排的就是右边的部分,此时 i = 1, j = 6, temp = num[i] = 98

         还是从右边找比temp小的数,78就符合,那么把78赋值给num[i](即num[1]),[注意此时num[6]的指还是78没变!!!,i=1,j=6].

         数组变为

    0 1 2 3 4 5 6
    5 78 45 134 23 54 78

       现在 i = 1, j = 6, temp = 98, 98的值不在数组中但没消失.

    然后i++,i = 2,现在从左边开始找比temp= 98 大的数,i加到3时,134符合,就把134赋值给num[j],然后j--;

    现在的数组是:

    0 1 2 3 4 5 6
    5 78 45 134 23 54 134

        现在 i = 3, j = 5, temp = 98,此时一轮分解扔未结束!!(因为仍然有i < j)

    现在从 j = 5 从右向左找比98小的数,54符合, num[i= 3]= 54, i++ (i= 4)

    现在的数组是

    0 1 2 3 4 5 6
    5 78 45 54 23 54 134

       现在 i= 4 j = 5 

    然后从 i = 4 找比temp大的数,23不符合则i++; i = j = 5;然后num[i] = temp = 98;至此第二轮分解完毕.

    现在成了

    0 1 2 3 4 5 6
    5 78 45 54 23 98 134

         现在分成了左边的num[1]~ num[4] 比98小,右边比98 大,然后就排num[1]~num[4],右边就一个数不用排了.

    3 代码

        经过上面的实例分析,以下为代码

        

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 
     4 /*   快速排序 QuickSort
     5  *   @Date: 2014-08-05
     6  *   @Author: cjr
     7  */
     8 
     9 int quicksort(int *num,int l,int r)
    10 {
    11     int i,j,temp,k;
    12     if(l < r)
    13     {
    14      i = l,j = r,temp = num[l];
    15     while(i < j)
    16     {
    17         while(num[j] > temp && j > i)   // 从右往左找比哨点小的值
    18             j--;
    19         if(i < j)
    20             num[i++] = num[j];
    21         while(num[i] < temp && i < j)   //  从左往右找比哨点大的值
    22             i++;
    23         if(i < j)
    24             num[j--] = num[i];
    25     }
    26     printf("%d ",i);
    27     num[i] = temp;
    28     for(k = l; k <= r; k++)
    29             printf("%d ",num[k]);
    30     printf("
    ");
    31     quicksort(num,l,i-1);
    32     quicksort(num,i+1,r);
    33     }
    34     return 0;
    35 }
    36 
    37 int main()
    38 {
    39     int num[7] = {5,98,45,134,23,54,78};
    40     int i;
    41     quicksort(num,0,6);
    42     for(i = 0; i < 7; i++)
    43         printf("%d ",num[i]);
    44     return 0;
    45 }

    4 总结反思

         自己写的时候犯的第一个错误:每次找到合适的数时只是进行简单的赋值操作而不是互换,本人依旧像其他排序一样进行了交换.

         需要注意理解何时才算是分解完成,不是把while(i < j)中走了一遍而是走到 i = j,走一遍仍可能有 i  < j 本例就是如此.

         本例中的代码体现的分治的思想还不是很明显;快排还有另外的一种写法,可参考一下文章:

         http://www.cnblogs.com/foreverking/articles/2234225.html 

         http://blog.csdn.net/morewindows/article/details/6684558

         

  • 相关阅读:
    【代码笔记】iOS-传身份证号码可返回生日字符串
    【代码笔记】iOS-抽屉效果的实现
    【代码笔记】iOS-旋转的图片
    【代码笔记】iOS-城市plist
    【代码笔记】iOS-侧滑效果
    【代码笔记】iOS-饼图
    【代码笔记】iOS-标题2个图标,点击的时候,页面跳转
    【代码笔记】iOS-GTMBase64
    【代码笔记】iOS-背景色随机显示
    【代码笔记】iOS-按钮带下划线的写法
  • 原文地址:https://www.cnblogs.com/programmer-cjr/p/3896198.html
Copyright © 2011-2022 走看看