zoukankan      html  css  js  c++  java
  • 链表的归并排序:来自STL_ list_ sort 算法

    侯捷STL源码剖析中列出了list的sort算法源码,感觉挺有意思:

     

    template <class T, class Alloc>

    void list<T,Alloc>::sort()

    {

    if (node->next==node||link_type(node->next)->next==node)

        return;

      list<T,Alloc> carry;

      list<T,Alloc> counter[64];

      int fill = 0;

      while (!empty())

      {

         carry.splice(carry.begin(),*this,begin());

         int i=0;

         while (i<fill&&!counter[i].empty())

         {

            counter[i].merge(carry);

            carry.swap(counter[i++]);

         }

         carry.swap(counter[i]);

         if (i==fill) ++fill;

      }

       for (int i=1; i<fill; i++)

             counter[i].merge(counter[i-1]);

       swap(counter[fill-1];32

    }

     

    其实就是归并排序,不过采用的不是自顶向下的递归,而是自底向上的归并。

    counter数组用来保存有序的子串,其实就是起到递归栈的作用。其中counter[i]保存的是长度为2i的子串。carray是一个临时容器。

    归并的顺序大致是这样的:首先从原list中取一个元素,将这个元素看做是一个长度为k=1的串,然后从counter数组的第i=1个list开始检查,如果这个list为空,则将子串放入counter[i];否则将carry和counter[i]归并为长度为2k的子串,再检查counter[i+1],以此类推。当原list为空时,将counter数组中各list归并起来就可以了。

     

    因此我认为fill这个变量唯一的意义就在于记录一下counter数组最大利用长度,提高一下最终归并(最后一个for循环)的效率而已。

     

    这个算法的实现限定了它所能排序的最长list为 264-1,这个数也确实足够大了。

     

    一般来说程序里面不应该出现所谓的魔法数字,上面的(64),不过STL都在此处如此使用,看来只要有足够的理由(264-1对一般程序来说已经是个天文数字),规则也是可以打破的。硬编码的数组可以让代码更加干净整洁。

  • 相关阅读:
    ES6入门 阮一峰
    NPM
    移动端BUG
    配置每次git push 不需要输入账号密码
    移动端rem布局,用户调整手机字体大小或浏览器字体大小后导致页面布局出错问题
    课程表
    岛屿数量
    二叉树的右视图
    c++设计模式——工厂模式
    克隆图
  • 原文地址:https://www.cnblogs.com/longhuihu/p/10423379.html
Copyright © 2011-2022 走看看