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++。

 

 

 

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

转载于:https://www.cnblogs.com/hustxujinkang/p/4111510.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/257973.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

cmd更换编码类型

chcp 65001 UTF-8 65001 GBK 936 本文出自 “曾颐楠的播客” 博客&#xff0c;请务必保留此出处http://zengyinan.blog.51cto.com/9524976/1721475 转载于:https://www.cnblogs.com/zengyinanos/p/5042732.html

代码混淆之后定位线上bug

代码混淆的目的 代码混淆的目的是防止竞争对手通过反编译来阅读项目代码。 Android中通过ProGuard来做代码混淆&#xff08;当然也还有其他的产品可以做代码混淆&#xff09;。 bug日志反混淆 资料&#xff1a;错误log、mapping.txt 异常log&#xff1a; mapping.txt&#xff…

linux怎么切换不同版本的r,在linux中用同一个版本的R 同时安装 Seurat2 和 Seurat3

在linux中用同一个版本的R 同时安装 Seurat 2 和 Seurat 3Seurat 作为单细胞分析中的重量级R包&#xff0c;有多好用用&#xff0c;用过的人都知道。Seurat 分析流程基本涵盖了单细胞分析中的所有常见分析方法&#xff0c;包括filtering&#xff0c;tSNE&#xff0c;UMAP降维及…

Unity手游之路四3d旋转-四元数,欧拉角和变幻矩阵

http://blog.csdn.net/janeky/article/details/17272625 今天我们来谈谈关于Unity中的旋转。主要有三种方式。变换矩阵&#xff0c;四元数和欧拉角。 定义 变换矩阵可以执行任意的3d变换&#xff08;平移&#xff0c;旋转&#xff0c;缩放&#xff0c;切边&#xff09;并且透视…

本地通知

本地通知&#xff0c;local notification&#xff0c;用于基于时间行为的通知&#xff0c;比如有关日历或者todo列表的小应用。另外&#xff0c;应用如果在后台执行&#xff0c;iOS允许它在受限的时间内运行&#xff0c;它也会发现本地通知有用。比如&#xff0c;一个应用&…

Redux 并不慢,只是你使用姿势不对 —— 一份优化指南

原文地址&#xff1a;Redux 并不慢&#xff0c;只是你使用姿势不对 —— 一份优化指南原文作者&#xff1a;Julian Krispel译文出自&#xff1a;掘金翻译计划本文永久链接&#xff1a;github.com/xitu/gold-m…译者&#xff1a;reid3290校对者&#xff1a;sunui&#xff0c;xek…

把windows装到linux下,如何将WSL(Windows Subsystem for Linux 2)安装到Windows 10?

原标题&#xff1a;如何将WSL(Windows Subsystem for Linux 2)安装到Windows 10&#xff1f;Windows 10凭借大受欢迎的WSL(Windows Subsystem for Linux)进入Linux领域。由于最近推出了WSL的最新版WSL2&#xff0c;用户现在可以利用实际的Linux内核从Windows执行Linux任务。现在…

TWRP-recovery中文界面安装方法[转]

把下载到的ui.zip放入sdcard1/twrp文件夹。注意&#xff0c;是内置存储卡中。如没有上述文件夹&#xff0c;自行建立后通过文件管理器放入&#xff0c;不是卡刷。文件夹应如下所示&#xff1a;sdcard1&#xff08;内置SD&#xff09; &#xff5c; ┕--twrp&#xff08;文件夹…

如何定期备份网站数据

产生这个问题的背景是我在维护两个个人的网站&#xff0c;因为采用的是虚拟主机&#xff0c;有时候空间续费不及时等&#xff0c;都可能造成数据的丢失&#xff0c;为了保障数据不丢失&#xff0c;因为有必要每15天左右对网站数据进行备份以防止发生不当的事情。 我们希望做的就…

初创团队可能不适合应届生小孩

根据最近招聘中接触到的一些刚毕业小孩的表现&#xff0c;谈谈这个问题&#xff1a; 1、扛不住&#xff0c;初创团队一般最好一人撑一快工作&#xff0c;刚毕业经验比较薄的小孩在这方面一是心理上不敢担当&#xff0c;二是能力上确实还需要磨炼成长 2、初创团队的那个环境可能…

vba执行linux命令,从VBA中的shell命令捕获输出值?

慕盖茨4494581根据Andrew Lessard的回答&#xff0c;这是一个运行命令并将输出作为字符串返回的函数 -Public Function ShellRun(sCmd As String) As StringRun a shell command, returning the output as a stringDim oShell As ObjectSet oShell CreateObject("WScript…

溢出和剪裁,可见性

内容溢出和剪裁 如果一个元素的内容对于元素大小来说过大&#xff0c;就有可能溢出元素本身。对于此情况&#xff0c;有一些解决办法可选。 溢出 overflow 值 visible(默认):内容在元素框外可见。一般会导致内容超出其自己的元素框&#xff0c;但不会改变框的形状scroll:溢出部…

C#= 栈模仿堆的操作

//原理&#xff0c;利用两个栈&#xff0c;互相作用&#xff0c;来模仿堆的效果&#xff0c;先进先出。。 1 using System;2 using System.Collections.Generic;3 using System.Linq;4 using System.Threading.Tasks;5 6 namespace TwoStacksQueue7 {8 public class Progra…

linux计划任务执行日志,linux中centos制定计划任务执行命令并且输出日志

1.写脚本最简单的 写如下代码#!/bin/shABC1.每个命令之间用;隔开说明&#xff1a;各命令的执行给果&#xff0c;不会影响其它命令的执行。换句话说&#xff0c;各个命令都会执行&#xff0c;但不保证每个命令都执行成功。2.每个命令之间用&&隔开说明&#xff1a;若前面…

Java-大集合拆分为指定大小的小集合

因为Oracle数据的in 最大允许1000 ,超过就会报错&#xff0c; 所以需要将集合拆分为多个集合进行处理. /*** 拆分集合* param <T>* param resList 要拆分的集合* param count 每个集合的元素个数* return 返回拆分后的各个集合*/public static <T> List<L…

AsyncTask与多任务

问题由来&#xff1a; 之前看到一篇博文&#xff0c;说AsyncTask不适合运行多任务&#xff0c; 多个任务不会异步执行&#xff0c; 当时只是印象里记住了一下也不确定&#xff0c; 今天把代码看了看&#xff0c; 把原因写出来。 问题的代码演示&#xff1a; 1 public class Asy…

iptables简单应用

可以修改/etc/rc.d/boot.local让规则重启后也能生效&#xff0c;如&#xff1a;/sbin/iptables -F/sbin/iptables -A INPUT -i eth0 -p tcp --sport 80 -j ACCEPT/sbin/iptables -A INPUT -i eth0 -p tcp -j DROP/sbin/iptables -A INPUT -i eth0 -p udp -j DROPiptables是一个…

linux中内部命令有哪些,linux内部命令有哪些

linux中常见的内部命令有&#xff1a;1.exit命令&#xff0c;退出当前的shell&#xff1b;2.history命令&#xff0c;显示历史执行过的命令&#xff1b;3.cd命令&#xff0c;切换当前工作目录&#xff1b;4.source命令&#xff0c;重新执行刚修改的初始化文件&#xff1b;5.ech…

使用SALT-API进入集成开发的简单样例

测试的时候&#xff0c;可以CURL -K&#xff0c;但真正作集成的时候&#xff0c;却是不可以的。 必须&#xff0c;不可以让TOKEN满天飞吧。 现在进入这个阶段了。写个样例先&#xff1a; import salt import salt.auth import salt.log import saltapiopts salt.client.LocalC…

POJ 2778

题意&#xff1a;很Uva项链题目类似。 区别&#xff1a; 1、字符串很多&#xff0c;用map hash超时&#xff0c;用Trie查找。 2、DFS判断连通&#xff0c;和并查集判连通&#xff0c;被我写错的地方时&#xff0c;查森林的时候&#xff0c;还是要Find_Set。 1 #include <ios…