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

      看了《程序设计实践》的开头,就碰到一个习题叫用用循环实现快速排序,开始准备pass掉的,但是一想学习过程中要注意细节,也就决定去写了,零零散散的花了不少时间,可见其中的一些微妙之处。喜欢其中的一句话,算是激励的:“Hoare描述了用循环写快速排序是如何困难的,进而发现用递归做快速排序实在是太方便了”,也就更有一些动力了,^_^。

      首先,写了一个递归的快速排序。

    int quick_sort(int array[], int start, int end)
    {
            if (start >= end) return 0;
    
            int nPoint = array[start];
            int nLast = start+1;
    
            for (int i = start+1; i < end; i++)
            {
                    if (array[i] < nPoint)
                    {
                            swap(array[i], array[nLast]);
                            nLast++;
                    }
            }
            swap(array[start], array[nLast-1]);
            quick_sort(array, start, nLast-1);
            quick_sort(array, nLast, end);
            return 1;
    }

      小结:

    (1)自己觉得写完之后,有一种很笨拙的感觉。特别是下标那里,不是很清晰,要调试打印,发现不对之后,再把坐标改成1啊,加个1之类的。自己觉得非常的不专业,也希望老手给点建议和宝贵经验。

    (2)写完之后,对于快速排序有了一个清晰的认识:就是找到一个基准点,然后保证基准点两边都是比该点大或者比该点小的。另外一个觉得有点意思的就是,会对算法复杂度认识更清晰一些,简单的考虑一个就是:如果你要和基准点比较,起码要便利一遍(n),二分的规则就是log2n,那就是O(n*log2n)。那最坏情况n^2怎么理解呢?例如,所有元素都相等,那么每次遍历都是比较n次,而二分法在他最坏的情况下,也就是n了,所以就是O(n^2)。对于复杂度,就是静下心来看进去,最后发现也就是1+1=2的清晰逻辑,会很舒服。

      接下来,是自己实现的循环实现的快速排序。

    // 循环-快速排序
    int quick_sort_onetime(int array[], int start, int end);
    int quick_sort_for(int array[], int start, int end){
            int nPoint[32] = {0};
            int nPointTemp[32] = {0};
            int nNum = 0;
            int k = 0;      //for nPointTemp
    
            int nTimes = (int)(log(end)/log(2));
            nNum = 1;
            k = 1;
            nPoint[0] = 0;
            for(int i = 0; i <= nTimes; i++)
            {
                    k = 0;//根据节点循环,第一次是一个
                    for (int j = 0; j < nNum; j++)
                    {int nSubStart = nPoint[j];
                            int nSubN = end - nSubStart;if(j+1 < nNum)
                                    nSubN = nPoint[j+1]-nSubStart;
                            int nTemp = quick_sort_onetime(array, nSubStart, nSubN);
                            nPointTemp[k++] = nPoint[j];
                            nPointTemp[k++] = nTemp+1;      //从后面一位开始
                    }
    
                    for(int i = 0; i < k; i++)
                            nPoint[i] = nPointTemp[i];
                    nNum = k;
            }
            return 1;
    }
    
    int quick_sort_onetime(int array[], int start, int end)
    {
            if (end <= 1) return 0;
    
            int nPoint = array[start];
            int nLast = start+1;for(int i1 = start; i1 < start+end; i1++)
                    printf("%d
    ", array[i1]);
    
            for (int i = start+1; i < start+end; i++)
            {
                    if (array[i] < nPoint)
                    {
                            swap(array[i], array[nLast]);
                            nLast++;
                    }
            }
            swap(array[start], array[nLast-1]);for(int i2 = start; i2 < start+end; i2++)
                    printf("%d
    ", array[i2]);
            return nLast-1;
    }    

       小结:

    (1)也是非常的糟糕,像小孩子的作品。

    (2)而这,自己却花了相对于不少的时间。一个是,用递归的思路写循环你就是找死。其次,用递归的复杂度去写这个问题,就明晰起来,就是每次遍历一遍,比较n次。中间有很多节点,一节一节的像个火车,每次处理一节车厢,然后找到该节车厢基准点继续把车厢截断成更小的,知道车厢是最小的一个单元的时候,也就不需要比较了。说的有点模糊,看下图:

    (3)自己写完之后,搜索了一下别人的结果。下面是一位别人写的,使用栈实现的,看起来就专业很多,但思想还是差不多,主要是保存中间节点的方式不一样。【http://www.cnblogs.com/zhangchaoyang/articles/2234815.html

  • 相关阅读:
    Go语言踩过的坑---记录GOPATH在GOLAND中的坑
    反射小例子
    制作pip包
    mac常用软件安装链接
    YCSB压测elasticsearch
    SSO和Auth2.0
    JAVA内部类的四大作用
    修改fastadmin,添加模糊查询
    AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.18.0.2. Set the 'ServerName' directive globally to suppress this message
    taro3.x: 封装实现chat emit on
  • 原文地址:https://www.cnblogs.com/pk-run/p/3679159.html
Copyright © 2011-2022 走看看