• 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] 。
  • 相关阅读:
    面向对象深入:继承01——子类
    面向对象的基础知识——小结
    IP地址配置
    二、RPM包管理-rpm命令管理
    一、软件包管理简介
    关机重启命令
    网络命令
    权限管理命令
    字符截取命令
    shell-正则表达式(二)
  • 原文地址:https://www.cnblogs.com/xiaojianliu/p/12595501.html
Copyright © 2020-2023  润新知