zoukankan      html  css  js  c++  java
  • STL 中的链表排序

    一直以来学习排序算法, 都没有在链表排序上下太多功夫,因为用得不多。最近看STL源码,才发现,原来即使是链表,也能有时间复杂度为O(nlogn)的算法,

    大大出乎我的意料之外,一般就能想到个插入排序。

    下面的代码就是按照源码写出的(去掉了模板增加可读性),注意forward_list是C++11新加的单向链表,这里选这个是因为它更接近我们自己实现链表时的做法。

    void sort_list(forward_list<int>& l){
    	auto it = l.begin();
    	if (l.empty() || ++it == l.end())
    		return;
    	forward_list<int> carry;
    	forward_list<int> counter[64];//总共只设立了64个桶,因为第i个桶被填充的时候,里面至多2^i个元素,2^64,远超一般元素数目
    	int fill = 0; //fill记录的是当前填到哪个桶了
    	while (!l.empty()){
    		carry.splice_after(carry.cbefore_begin(), l, l.cbefore_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]);
    	l.swap(counter[fill - 1]);
    }
    

      关于此算法的分析:网上很多争论这个到底是快速排序还是归并排序的(侯捷的书上说是快排)。

          为了理解这个代码,可以手动运行一下。

          fill,记录用到了几个桶,最外层循环保证这样一个事实:从第0个桶到第fill - 1个桶里面,要么为空,要么存储有2^fill个元素,而且是有序链表。

          每次与新取下的元素(存储在carry中)合并的桶都是counter[0]。如果第0个桶里没有元素,那就直接放进去carry.swap(counter[i])。下一轮循环的

         时候,因为counter[0]里有元素了,就会进入内层循环,这时候,counter[i].merge(carry)使得第0个桶变为一个含两个元素的链表,然后内层循环第二步,又将这个链表

    转移到carry中,下一轮内层循环的时候,带有两个元素的carry就会争取与第1个桶合并(如果第1个桶不空的话),如果第一个桶为空,它将退出内层循环并将元素放进第一个桶,(此时发现i == fill,于是fill变为2)然后下一轮外层循环继续从链表中取下一个元素,(此时counter[0]为空,counter[1]中含有两个元素),如前面一样,先是发现counter[0]是空的,进不去内层循环,于是直接把元素填到counter[0]中,下一次外层循环又取一个元素,进入内层循环,与counter[0]合并,交换,然后下一轮内层循环中,带有两个元素的carry就会与带有两个元素的counter[1]合并,交换, i == fiil == 2退出内层循环,四个元素变到第2个桶中,fill++。

                    走完这一遍之后,感觉清晰了,但是除了外层循环的循环不变条件以外,实在是很难从基本的快排或归并排序的思想中想到这样去做。

  • 相关阅读:
    1210 BBS admin后台管理及侧边栏筛选个人站点
    1209 BBS 登录
    更换 npm 源国内镜像 cnpm
    Linux软件管理
    apt-get / yum 软件安装源(国内)
    修改pip源为国内镜像源(加速下载)
    修改浏览器搜索引擎:网址应该如何填写
    如何根据实际问题选择一个合适的数学模型
    安装向量和矩阵运算库函数
    配置编译器(GCC和GFortran)
  • 原文地址:https://www.cnblogs.com/hustxujinkang/p/4111510.html
Copyright © 2011-2022 走看看