c++链表归并排序的迭代版本
之前用js写了个归并排序非递归版,而这一次,c++封装链表的时候也遇到了一个归并排序的接口。邓老师实现了递归版本的归并排序,但是递归的调用函数栈的累积是很占内存空间的。于是乎,那试试在链表结构上实现以下归并排序吧。但是一旦开始,就遇到难题了,在链表下,我们无法按索引访问,所以,在迭代过程中,左右序列就无法很好的用o(1)时间就解决。先看看我实现的代码吧,初步测试没问题,如果有什么问题,希望大神指出,不知为何,用c++写东西总觉得哪里有问题,即使程序可以运行。
template<typename T>
void List<T>::mergeSort(Posi(T) p, int n)
{
Posi(T) h = p->pred;
Posi(T) r_p;
for (int i = ; i < n; i*=)
{
p = h->next;
r_p = p;
int count = ;
while (count*<n)
{
int r_len = ;
while (r_len<i&&r_p!=trailer)
{
r_p = r_p->next;
r_len++;
count++; //右链表移动的次数
}
if (r_p == trailer)
{
break;
}
if (count*>n)
{
r_len = n%i;
}
p = merge(p, i, r_p, r_len);
r_p = p;
}
}
}
这是主干程序,大体思路是从一开始的一个一个归并并,到四个四个合并,到最后二路归并,一开始,因为这个接口是在给定位置的p点已经后面的n-1个元素进行排序,所以我无法直接使用header,于是,用p点的前一个左右目前头结点,为什么这么做呢,一开始的时候,我是打算用p左右每次迭代的开始,如果你对迭代版归并熟悉的话,那么应该很容易理解,每一次合并完所有链表上的分列表,都需要重新从第一个结点开始,然后继续合并下一个循环,而因为链表是动态的,很有可能,一次合并后,你的p就不是现在的第一个结点了,这是h变量的含义,他是一个头结点,当然,按照这个接口,尾结点也需要重新定义,然而定义尾结点需要n时间复杂度,所以这里,我的代码是假设n个的下一个刚好是尾结点。之后是需要合并的右链表的位置,一开始是和左链表重合,然后通过循环来达到它的位置,count变量是r_p走的步数,这个步数两倍是可能超过长度n的,一旦超过,说明了r_p时间上已经到达了末尾,这时候一个级数的合并已经完成,可以进入下一个迭代归并。
而r_len = n%i;的意义是如果越界,那么需要取得余数,是正好等于尾巴的长度。
如果不这么做,那么merge函数可能链表越界,接下来看看别的部件。
template<typename T>//包括p在内的n个元素
Posi(T) List<T>::merge(Posi(T) left_p, int left_len,Posi(T) right_p, int right_len)
{
while (left_len > &&right_len > )
{
if (left_p->data < right_p->data)
{
left_p = left_p->next;
left_len--;
}
else
{
Posi(T) temp_p = right_p->next;
insertAsPre(right_p, left_p);
right_p = temp_p;
right_len--;
}
}
while (right_len-->)
{
right_p = right_p->next;
}
return right_p;
}
template<typename T> //重写接口,以至于可以插入已有节点,同一个链表的节点
Posi(T) List<T>::insertAsPre(Posi(T) p, Posi(T) n)
{
p->next->pred = p->pred;
p->pred->next = p->next;
p->pred = n->pred;
p->next = n;
n->pred = p;
p->pred->next = p;
return p;
}
现在可以分析下这个算法的时间复杂度了。
最外层的for循环应该是logn,这个很好理解,而为了得到左指针的while循环必然是n/2,merge函数花费是n,while和merge同级,所以花费是3n/2.
如果算上这个接口尾指针。应该是o(3n/2*logn+n),整体是比数组的归并要慢一点,但是还是在同一个数量级的,这是值得开心的。
c++链表归并排序的迭代版本的更多相关文章
- STL 源码分析《1》---- list 归并排序的 迭代版本, 神奇的 STL list sort
最近在看 侯捷的 STL源码分析,发现了以下的这个list 排序算法,乍眼看去,实在难以看出它是归并排序. 平常大家写归并排序,通常写的是 递归版本..为了效率的考虑,STL库 给出了如下的 归并排序 ...
- SICP 换零钱的迭代版本
看到换零钱方式统计这里, 书中给出了递归的实现但没有给出迭代版本说要留给读者作为挑战, 既然说是作为挑战那肯定是能解决的,在想了一天无果之后最终在别人博客的帮助下终于实现了迭代的版本...也算是经历坎 ...
- [Leetcode]148. 排序链表(归并排序)
题目 在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序. 示例 1: 输入: 4->2->1->3 输出: 1->2->3->4 示例 2: ...
- 21 Merge Two Sorted Lists(两链表归并排序Easy)
题目意思:对两个递增链表进行归并排序 思路:没什么好说的,二路归并 /** * Definition for singly-linked list. * struct ListNode { * int ...
- [LeetCode]148. Sort List链表归并排序
要求时间复杂度O(nlogn),空间复杂度O(1),采用归并排序 传统的归并排序空间复杂度是O(n),原因是要用一个数组表示合并后的数组,但是这里用链表表示有序链表合并后的链表,由于链表空间复杂度是O ...
- c#循环迭代匿名类链表(可迭代的匿名类)
Main(){ //为什么?object是基类啊!! //报错.不能从List<anonymous>换成List<object>. //var q=(List<objec ...
- git在多迭代版本的应用
名词解释: 1.迭代: 就是对于项目功能的一个分类.如项目需要新增一个地图功能,则地图功能是一个迭代. 2.gitlab机器人 操作: 1.如果将要进行一个新功能的开发,从稳定分支上拉取创建一个新的分 ...
- [LeetCode] 148. 排序链表 ☆☆☆(归并排序)
148.排序链表 描述 在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序. 示例 1: 输入: 4->2->1->3输出: 1->2->3-> ...
- Python 3.9.0 首个迭代版本发布了
Python 3.9.0 alpha 1 发布了,这是 3.8 之后的首个 3.9 系列版本. ! 官方没有介绍新特性,也没有添加新模块,但是以下模块有所改进: ast asyncio curses ...
随机推荐
- Android课程---视图组件总结
- eclipse汉化过程
第一步: 打开浏览器,浏览“参考资料”内给出的“eclipse语言包下载”地址,在博客新页面找到地址链接,如图所示.“Babel Language...”开头的一栏下面就是各个eclise版本的语言包 ...
- Unable to establish connection to tokens
安装openstack后遇到的第一个问题. 执行命令nova list得到如下结果: [root@localhost ~(keystone_admin)]# nova list No handlers ...
- support HTML5 in IE8
<!--this code is used to support HTML5 in IE8--> <!--[if IE]><script type="text/ ...
- 字符串数组(String []) 去掉重复值的方法
public class Demo { /** * 去掉重复值 */ public static void main(String[] args) { String test = "100, ...
- Java提高篇——equals()与hashCode()方法详解
java.lang.Object类中有两个非常重要的方法: 1 2 public boolean equals(Object obj) public int hashCode() Object类是类继 ...
- win7 安装 memcached
1. 下载 memcached-win32-1.4.4-14.zip,里面包含6个文件,将解压后的文件夹随便放在什么位置.如果需要win64版,下载 memcached-win64-1.4.4-14. ...
- LUA语言注意点归集
统计元素个数接口--只计算以整数为下标的 第一段连续元素的数目 #tab 和 table.getn() http://ju.outofmemory.cn/entry/29450 我们修改table: ...
- RDIFramework.NET(.NET快速开发框架) 答客户问(2014-02-23)
1.框架的部署安装,服务器端和客户端 答:开发版以上版本支持SOA模式,也即真正的面向服务端的模式,在实际使用过程中,可根据项目的实际需要,来选择性的进行部署(直连模式或SOA模式),如需要分布式应用 ...
- 向ES6看齐,用更好的JavaScript(二)
本文是ES6系列的第二篇,主要介绍ES6中对现有对象方法属性的拓展,先上传送门: 1 变量部分 2 现有对象拓展 3 新增数据类型/数据结构 4 新的异步编程模式 5 类和模块 1 增加了模板字符串 ...