单链表排序----快排 & 归并排序

原文:http://blog.csdn.net/u012658346/article/details/51141288

  题目描述: 
  给定一个乱序的单链表的头节点,对该链表中的节点进行排序 
   要求时间复杂度为O(nlgn),空间复杂度为O(1)   
   
  分析: 
  由于题目要求时间复杂度我O(nlgn),因此选择排序和插入排序可以排除。 
  在排序算法中,时间复杂度为O(nlgn)的主要有:归并排序、快速排序、堆排序。 
  其中堆排序的空间复杂度为(n),也不符合要求,因此也可以排除。 
  归并排序在对数组进行排序时,需要一个临时数组来存储所有元素,空间复杂度为O(n)。但是利用归并算法对单链表进行排序时,可以通过next指针来记录元素的相对位置,因此时间复杂度也为O(1)。 
  因此可以考虑用快排和归并来实现单链表的排序。 
   
   快速排序: 
   快速排序的主要思想是: 
   1)选定一个基准元素 
   2)经过一趟排序,将所有元素分成两部分 
   3)分别对两部分重复上述操作,直到所有元素都已排序成功 
   因为单链表只能从链表头节点向后遍历,没有prev指针,因此必须选择头节点作为基准元素。这样第二步操作的时间复杂度就为O(n)。由于之后都是分别对两部分完成上述操作,因此会将链表划分为lgn个段,因此时间复杂度为O(nlgn) 
   
   示意图如下: 
    
   
  代码:   

    void swap(int *a,int *b){int t=*a;*a=*b;*b=t;}ListNode *partion(ListNode *pBegin,ListNode *pEnd){if(pBegin==pEnd||pBegin->next==pEnd)    return pBegin;int key=pBegin->val;    //选择pBegin作为基准元素ListNode *p=pBegin,*q=pBegin;while(q!=pEnd){   //从pBegin开始向后进行一次遍历if(q->val<key){p=p->next;swap(&p->val,&q->val);}q=q->next;}swap(&p->val,&pBegin->val);return p;}void quick_sort(ListNode *pBegin,ListNode *pEnd){if(pBegin==pEnd||pBegin->next==pEnd)    return;ListNode *mid=partion(pBegin,pEnd);quick_sort(pBegin,mid);quick_sort(mid->next,pEnd);}ListNode* sortList(ListNode* head) {if(head==NULL||head->next==NULL)    return head;quick_sort(head,NULL);return head;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

  归并排序: 
  归并排序的也是基于分治的思想,但是与快排不同的是归并是先划分,然后从底层开始向上合并。 
  归并排序的主要思想是将两个已经排好序的分段合并成一个有序的分段。除了找到中间节点的操作必须遍历链表外,其它操作与数组的归并排序基本相同。

  代码:  

    ListNode* merge_sort(ListNode* head) {if(head == NULL || head->next == NULL)return head;ListNode* head1 = head;ListNode* head2 = getMid(head);  //获取中间节点,将链表分为两段head1 = merge_sort(head1);   //分别对两段链表进行排序head2 = merge_sort(head2);return merge(head1, head2);  //将两段有序链表合并}ListNode* merge(ListNode* head1, ListNode* head2) //合并两个有序链表{ListNode* newhead = new ListNode(-1);ListNode* newtail = newhead;while(head1 && head2){if(head1->val <= head2->val){newtail->next = head1;head1 = head1->next;}else{newtail->next = head2;head2 = head2->next;}newtail = newtail->next;newtail->next = NULL;}if(head1)   newtail->next = head1;if(head2)   newtail->next = head2;return newhead->next;  //链表头节点}ListNode* getMid(ListNode* head)  //获取中间节点并分段{ListNode* fast = head->next;ListNode* slow = head->next;ListNode* prev = head;while(true){if(fast == NULL) break;fast = fast->next;if(fast == NULL)    break;fast = fast->next;prev = slow;slow = slow->next;}prev->next = NULL;  //将链表分为两段return slow;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

  因此归并排序的关键在于将单链表变为两个排序好的分段。 
  getMid 示意图如下: 
   
  

单链表排序----快排 归并排序相关推荐

  1. 面试题精选:单链表排序也能玩出花来

    今天国庆节,祝大家中秋节快乐,顺便给大家拜个早年[狗头].不过最近还在准备面试的同学们不要浪太狠,还是要好好学习的鸭. 单链表的排序在数据结构类的面试题中简直是集大成者,什么排序.链表.链表删除.添加 ...

  2. 单链表排序之直接插入排序

    ****单链表排序之直接插入排序**** /*前段时间刚学会几种排序方法,最近学习了单链表,就用来试试,本篇链表的排序方法<一>讲述的是单链表的直接插入排序:(注意:请仔细看准节点结构体的 ...

  3. python单链表排序_单链表排序之选择排序

    单链表排序是单链表的常见编程任务之一,也是面试中经常出现的题目.单链表排序的关键是交换算法,需要额外考虑.选择排序是比较直观的排序算法之一,这里就使用选择排序实现单链表的排序. C实现代码如下: Li ...

  4. 牛客 - 单链表排序

    单链表排序 **BM12** **单链表的排序** 链接 问题描述 代码 BM12 单链表的排序 链接 单链表的排序_牛客题霸_牛客网 (nowcoder.com) 问题描述 给定一个节点数为n的无序 ...

  5. 单链表的应用--对单链表排序

      对单链表进行排序,利用前文写好的链表的框架,在链表类中补充Sort方法. 对单链表排序 一.问题分析 二.代码分析 1.链表类LinkList 2.链表方法Sort 三.测试代码 1.主函数 2. ...

  6. 单链表排序(交换节点)

    单链表排序(移动节点) 单链表排序利用了选择排序的方式: 创建一个单链表结构体 typedef int data_t;//为了能适应存储其他类型数据,可以将int换成其他数据类型而不通用一个一个更改程 ...

  7. P1309 [NOIP2011 普及组] 瑞士轮-快排+归并排序

    [NOIP2011 普及组] 瑞士轮 题目背景 在双人对决的竞技性比赛,如乒乓球.羽毛球.国际象棋中,最常见的赛制是淘汰赛和循环赛.前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高.后者的特点是较 ...

  8. C语言版--单链表排序,冒泡排序,选择排序,插入排序,快速排序,应有尽有,保证看懂,没有bug!交换节点版本!

    一.废话不多说,直接上代码.如果想看双向循环链表的朋友,可以在我的博客里找. 你好 #include <stdio.h> #include <stdlib.h>typedef ...

  9. 排序 ---- 快排(C语言)

    思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都要比另一部分的所有数据要小,然后再按此方法对这两部分数据分别进行快排,整个过程可以递归进行,以此达到整个数据变成有序序列. 时 ...

最新文章

  1. Android APK文件学习调研
  2. 阿里云联合中国信通院发布《云计算开放应用架构》标准,加速云原生应用规模化落地进程
  3. [Mummy Maze] 宽度优先搜索
  4. 推荐一款.NET Core开源爬虫神器:DotnetSpider
  5. 飞畅科技-PoE交换机的常见问题解答
  6. stone 的 log4j配置详解
  7. Sigma Function(LightOJ-1336)
  8. cuda11.0 cudnn 11.0 torch1.7.1+cu110 torchvision 0.8.2+cu110 安装包
  9. 中国大数据与智能计算产业联盟“开源软件工作委员会”成立会议在京召开
  10. 安装天文软件karma和设置环境变量---conda安装和环境变量设置
  11. 2019-CS224n-Assignment3
  12. matlab2010 mex,怎样在Matlab2010a中使用VS2010的mex
  13. java 网络五子棋游戏_基于JAVA的网络五子棋游戏
  14. 薪火相传,构建生态——记约束求解基础与应用训练营
  15. 2019年部分实习面经回顾
  16. ELK整合:ElasticSearch定期删除过期数据
  17. 编程_三大编程思想:POP、OOP、AOP
  18. linux系统资源分析 - CPU篇
  19. 三极管计数系统的设计与实现matlab,运动控制系统课程设计-双闭环直流电动机调速系统设计及MATLAB仿真汇.docx...
  20. 小学计算机奥林匹克试题,历届小学数学奥林匹克试题:91届A卷

热门文章

  1. 内核中的几种内存分配器
  2. Linux系统时间和时序,什么是时序竞态 Linux系统时序竞态问题分析
  3. 利用计算机解决问题实际依赖,行测答题技巧:准确把握加强、削弱的“相关性”...
  4. java可以多重继承吗_Java中的多重继承与组合vs继承
  5. php错误密码也能登陆账号,php用户登陆代码(限制用户错误登录次数)(1/2
  6. html编写个人博客_第 06 篇:博客从“裸奔”到“有皮肤”
  7. python网上授课_python完整课程
  8. python樱花树画法图片_用Python敲出樱花绽放 | 附代码
  9. mysql嵌套实战_艰难的mysql嵌套表结果挑战
  10. 一个半径为r的球体均匀带电_静电现象——一个易被忽略的细节