zoukankan      html  css  js  c++  java
  • list 的 sort 算法

    list 的 sort 算法

    由于 STL 本身的排序算法 sort 接受的输入迭代器是随机访问迭代器,但是双向 list 链表容器的访问方式是双向迭代器,因此,不能使用 STL 本身的排序算法 sort,必须自己定义属于自己访问的排序算法。

    template <class _Tp, class _Alloc>
    void list<_Tp, _Alloc>::sort()
    {
      //@ 如果链表为空或者链表只有一个元素则不做任何操作
      if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node) 
      {
        list<_Tp, _Alloc> __carry;	//@ carry 链表起到搬运的作用
    	//@ counter 作为中间的存储载体
    	/*
    	*其中对于counter[i]里面最多的存储数据为2^(i+1)个节点
    	*若超出则向高位进位即counter[i+1]
    	*/
        list<_Tp, _Alloc> __counter[64];
        int __fill = 0;
        while (!empty()) 
    	{//@ 若不是空链表
    	  //@ step1:
    	  //@ 把当前链表的第一个节点放在 carry 链表头
          __carry.splice(__carry.begin(), *this, begin());
          int __i = 0;
          while(__i < __fill && !__counter[__i].empty()) 
    	  {
            //@ step2:
    		  __counter[__i].merge(__carry);	//@ 把链表carry合并到counter[i]
            //@ step3:
    		  __carry.swap(__counter[__i++]);	//@ 交换链表carry和counter[i]内容
          }
          //@ step4:
    	  __carry.swap(__counter[__i]);	//@ 交换链表carry和counter[i]内容         
          //@ step5:
    	  if (__i == __fill) ++__fill;
        } 
    
        for (int __i = 1; __i < __fill; ++__i)
         //@ step6:
         //@ 把低位不满足进位的剩余数据全部有序的合并到上一位
    	  __counter[__i].merge(__counter[__i-1]);
        //@ step7:
        //@ 最后把已排序好的链表内容交换到当前链表
    	swap(__counter[__fill-1]);	
      }
    }
    

    图解 list sort 算法

    待排序的原始链表:

    • 第一次执行 while 循环

      • 执行步骤 step1:carry 取出当前链表的第一个数据节点 7。
      • 执行步骤 step4:交换 carry 和 counter 的内容。
      • 执行步骤 step5:更新 fill 值,fill=1。
    • 第二次执行 while 循环

      • 执行步骤 step1:carry 取出当前链表的第一个数据节点 5。
      • 执行步骤 step2:将 carry 链表的内容有序的合并到 counter 链表中。
      • 执行步骤 step3:交换 carry 和 counter[0] 内容且 i++。
      • 执行步骤 step4:交换carry 和 counter[1] 的内容。
      • 执行步骤 step5:更新 fill 的值,fill=2。
    • 第三次执行 while 循环

      • 执行步骤 step1:carry 取出当前链表的第一个数据节点 8。
      • 执行步骤 step4:交换 carry 和 counter[0] 的内容。
    • 第四次执行while循环:

      • 执行步骤 step1:carry 取出当前链表的第一个数据节点 1。
      • 执行步骤 step2:将 carry 链表的内容有序的合并到 counter[0] 链表中。
      • 执行步骤 step3:交换 carry 和 counter[0] 内容且 i++。
      • 再执行步骤 step2:将 carry 的内容有序的合并到 counter[1] 链表中。
      • 再执行步骤step3:交换 carry 和 counter[1] 的内容且 i++。
      • 执行步骤 step4:交换carry 和 counter[2] 的内容。
      • 执行步骤 step5:更新 fill 的值,fill=3。
    • 最后

      • 执行步骤 step6:合并 counter。
      • 执行步骤 step7:交换当前链表和 counter[2] 。
  • 相关阅读:
    使用ueditor实现多图片上传案例——Servlet层(UploadServlet)
    使用ueditor实现多图片上传案例——截取字符串层Util(SubString_text)
    [转载]oracle删除数据后的恢复
    [转载]oracle删除数据后的恢复
    为什么在定义hashcode时要使用31这个数呢?
    为什么在定义hashcode时要使用31这个数呢?
    [转载]hashCode和equals
    [转载]hashCode和equals
    Oracle HINT的用法
    Oracle HINT的用法
  • 原文地址:https://www.cnblogs.com/xiaojianliu/p/12595501.html
Copyright © 2011-2022 走看看