链表排序(冒泡、选择、插入、快排、归并、希尔、堆排序)

参考http://www.cnblogs.com/TenosDoIt/p/3666585.html

插入排序(算法中是直接交换节点,时间复杂度O(n^2),空间复杂度O(1)

 1 class Solution {
 2 public:
 3     ListNode *insertionSortList(ListNode *head) {
 4         // IMPORTANT: Please reset any member data you declared, as
 5         // the same Solution instance will be reused for each test case.
 6         if(head == NULL || head->next == NULL)return head;
 7         ListNode *p = head->next, *pstart = new ListNode(0), *pend = head;
 8         pstart->next = head; //为了操作方便,添加一个头结点
 9         while(p != NULL)
10         {
11             ListNode *tmp = pstart->next, *pre = pstart;
12             while(tmp != p && p->val >= tmp->val) //找到插入位置
13                 {tmp = tmp->next; pre = pre->next;}
14             if(tmp == p)pend = p;
15             else
16             {
17                 pend->next = p->next;
18                 p->next = tmp;
19                 pre->next = p;
20             }
21             p = pend->next;
22         }
23         head = pstart->next;
24         delete pstart;
25         return head;
26     }
27 };

 


选择排序(算法中只是交换节点的val值,时间复杂度O(n^2),空间复杂度O(1)

 1 class Solution {
 2 public:
 3     ListNode *selectSortList(ListNode *head) {
 4         // IMPORTANT: Please reset any member data you declared, as
 5         // the same Solution instance will be reused for each test case.
 6         //选择排序
 7         if(head == NULL || head->next == NULL)return head;
 8         ListNode *pstart = new ListNode(0);
 9         pstart->next = head; //为了操作方便,添加一个头结点
10         ListNode*sortedTail = pstart;//指向已排好序的部分的尾部
11         
12         while(sortedTail->next != NULL)
13         {
14             ListNode*minNode = sortedTail->next, *p = sortedTail->next->next;
15             //寻找未排序部分的最小节点
16             while(p != NULL)
17             {
18                 if(p->val < minNode->val)
19                     minNode = p;
20                 p = p->next;
21             }
22             swap(minNode->val, sortedTail->next->val);
23             sortedTail = sortedTail->next;
24         }
25         
26         head = pstart->next;
27         delete pstart;
28         return head;
29     }
30 };

 


快速排序1(算法只交换节点的val值,平均时间复杂度O(nlogn),不考虑递归栈空间的话空间复杂度是O(1))

这里的partition我们参考数组快排partition的第二种写法(选取第一个元素作为枢纽元的版本,因为链表选择最后一元素需要遍历一遍),具体可以参考here

这里我们还需要注意的一点是数组的partition两个参数分别代表数组的起始位置,两边都是闭区间,这样在排序的主函数中:

void quicksort(vector<int>&arr, int low, int high)

{

  if(low < high)

  {

   int middle = mypartition(arr, low, high);

   quicksort(arr, low, middle-1);

   quicksort(arr, middle+1, high);

  }

}

对左边子数组排序时,子数组右边界是middle-1,如果链表也按这种两边都是闭区间的话,找到分割后枢纽元middle,找到middle-1还得再次遍历数组,因此链表的partition采用前闭后开的区间(这样排序主函数也需要前闭后开区间),这样就可以避免上述问题

 

 1 class Solution {
 2 public:
 3     ListNode *quickSortList(ListNode *head) {
 4         // IMPORTANT: Please reset any member data you declared, as
 5         // the same Solution instance will be reused for each test case.
 6         //链表快速排序
 7         if(head == NULL || head->next == NULL)return head;
 8         qsortList(head, NULL);
 9         return head;
10     }
11     void qsortList(ListNode*head, ListNode*tail)
12     {
13         //链表范围是[low, high)
14         if(head != tail && head->next != tail)
15         {
16             ListNode* mid = partitionList(head, tail);
17             qsortList(head, mid);
18             qsortList(mid->next, tail);
19         }
20     }
21     ListNode* partitionList(ListNode*low, ListNode*high)
22     {
23         //链表范围是[low, high)
24         int key = low->val;
25         ListNode* loc = low;
26         for(ListNode*i = low->next; i != high; i = i->next)
27             if(i->val < key)
28             {
29                 loc = loc->next;
30                 swap(i->val, loc->val);
31             }
32         swap(loc->val, low->val);
33         return loc;
34     }
35 };

 

快速排序2(算法交换链表节点,平均时间复杂度O(nlogn),不考虑递归栈空间的话空间复杂度是O(1))

这里的partition,我们选取第一个节点作为枢纽元,然后把小于枢纽的节点放到一个链中,把不小于枢纽的及节点放到另一个链中,最后把两条链以及枢纽连接成一条链。

这里我们需要注意的是,1.在对一条子链进行partition时,由于节点的顺序都打乱了,所以得保正重新组合成一条新链表时,要和该子链表的前后部分连接起来,因此我们的partition传入三个参数,除了子链表的范围(也是前闭后开区间),还要传入子链表头结点的前驱;2.partition后链表的头结点可能已经改变

class Solution {
public:ListNode *quickSortList(ListNode *head) {// IMPORTANT: Please reset any member data you declared, as// the same Solution instance will be reused for each test case.//链表快速排序if(head == NULL || head->next == NULL)return head;ListNode tmpHead(0); tmpHead.next = head;qsortList(&tmpHead, head, NULL);return tmpHead.next;}void qsortList(ListNode *headPre, ListNode*head, ListNode*tail){//链表范围是[low, high)if(head != tail && head->next != tail){ListNode* mid = partitionList(headPre, head, tail);//注意这里head可能不再指向链表头了qsortList(headPre, headPre->next, mid);qsortList(mid, mid->next, tail);}}ListNode* partitionList(ListNode* lowPre, ListNode* low, ListNode* high){//链表范围是[low, high)int key = low->val;ListNode node1(0), node2(0);//比key小的链的头结点,比key大的链的头结点ListNode* little = &node1, *big = &node2;for(ListNode*i = low->next; i != high; i = i->next)if(i->val < key){little->next = i;little = i;}else{big->next = i;big = i;}big->next = high;//保证子链表[low,high)和后面的部分连接little->next = low;low->next = node2.next;lowPre->next = node1.next;//为了保证子链表[low,high)和前面的部分连接return low;}
};

 

 


归并排序(算法交换链表节点,时间复杂度O(nlogn),不考虑递归栈空间的话空间复杂度是O(1))                        本文地址

首先用快慢指针的方法找到链表中间节点,然后递归的对两个子链表排序,把两个排好序的子链表合并成一条有序的链表。归并排序应该算是链表排序最佳的选择了,保证了最好和最坏时间复杂度都是nlogn,而且它在数组排序中广受诟病的空间复杂度在链表排序中也从O(n)降到了O(1)

class Solution {
public:ListNode *mergeSortList(ListNode *head) {// IMPORTANT: Please reset any member data you declared, as// the same Solution instance will be reused for each test case.//链表归并排序if(head == NULL || head->next == NULL)return head;else{//快慢指针找到中间节点ListNode *fast = head,*slow = head;while(fast->next != NULL && fast->next->next != NULL){fast = fast->next->next;slow = slow->next;}fast = slow;slow = slow->next;fast->next = NULL;fast = sortList(head);//前半段排序slow = sortList(slow);//后半段排序return merge(fast,slow);}}// merge two sorted list to oneListNode *merge(ListNode *head1, ListNode *head2){if(head1 == NULL)return head2;if(head2 == NULL)return head1;ListNode *res , *p ;if(head1->val < head2->val){res = head1; head1 = head1->next;}else{res = head2; head2 = head2->next;}p = res;while(head1 != NULL && head2 != NULL){if(head1->val < head2->val){p->next = head1;head1 = head1->next;}else{p->next = head2;head2 = head2->next;}p = p->next;}if(head1 != NULL)p->next = head1;else if(head2 != NULL)p->next = head2;return res;}
};

 

 


冒泡排序(算法交换链表节点val值,时间复杂度O(n^2),空间复杂度O(1))

class Solution {
public:ListNode *bubbleSortList(ListNode *head) {// IMPORTANT: Please reset any member data you declared, as// the same Solution instance will be reused for each test case.//链表快速排序if(head == NULL || head->next == NULL)return head;ListNode *p = NULL;bool isChange = true;while(p != head->next && isChange){ListNode *q = head;isChange = false;//标志当前这一轮中又没有发生元素交换,如果没有则表示数组已经有序for(; q->next && q->next != p; q = q->next){if(q->val > q->next->val){swap(q->val, q->next->val);isChange = true;}}p = q;}return head;}
};

 



转载于:https://www.cnblogs.com/StarZhai/p/9984230.html

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

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

相关文章

zookeeper使用和原理探究

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 zookeeper介绍 zookeeper是一个为分布式应用提供一致性服务的软件&#xff0c;它是开源的Hadoop项目中的一个子项目&#xff0c;并且根据…

thinkphp如何部署到宝塔面板nginx服务器

原理&#xff1a;一般本地都会使用apache服务器&#xff0c;这个对pathinfo&#xff08;两个&#xff0c;一个是环境变量$_SERVER[PATH_INFO]&#xff0c;另一个是pathinfo函数&#xff09;路由解析非常支持的&#xff0c;不需要部署什么&#xff0c; 但是nginx是对pathinfo函…

Android获取所有应用的资源id和对应的uri

背景在某些应用中&#xff0c;为了实现应用apk资源放入重复利用&#xff0c;或者使用反射得到本应用的资源&#xff0c;需要使用反射方式获得&#xff0c;但Resources类中也自带了这种获取方式&#xff0c;并且功能更加强大你可以获取string,color,drawable,raw,xml等文件&…

nginx的脚本引擎(一)

nginx的脚本的语法和shell是很像的&#xff0c;我大致看了一下觉得挺有意思的&#xff0c;就想写写记录一下。我没看过shell脚本的引擎&#xff0c;不知道nginx脚本引擎和shell脚本引擎像不像&#xff0c;但是我觉得nginx的脚本引擎有点像C和汇编。 ngx_http_script_engine_t这…

一个待办事列表todolist

最近有位老师让我做的&#xff0c;图片在下面&#xff0c;做了4个多小时&#xff0c;ui有的简陋&#xff0c;可以再美化一下&#xff0c;这个会更好看&#xff0c;毕竟我也不是专业前端&#xff0c;测试网站http://todolist.sshouxin.top/使用的是thinkphp5.1的框架&#xff0c…

详细说明 SourceTree 免登录,跳过初始设置的方法(Windows 版 )

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 首先&#xff0c;安装完 SourceTree 以后先运行一次&#xff0c;弹出初始化登录页面后退出。 2. 进入这个文件夹&#xff1a;C:\Users…

什么是好的API设计?

摘要&#xff1a;有人言&#xff0c;API设计是编程工作中最难的事情。甚至有人认为至少要有10年的工作经验才能接触它。不过这里提出了一个引人思考的问题&#xff1a;究竟是构建什么样的库需要花费10年的时间去学习&#xff1f; 有人言&#xff0c;API设计是编程工作中最难的事…

Linux学习记录-文件、目录与磁盘

用户和群组 用户和群组主要是为了区分用户对文件的操作权限。 账号在/etc/passwd个人密码在/etc/shadow组信息在/etc/group 不要乱动这3个文件文件权限和目录配置 文件属性 文件前缀解释&#xff0c;例如&#xff1a; 第一个字符代表这个文件是『目录、文件或链接文件等等』&am…

php curl模拟https请求

https请求(支持GET和POST) function http_request($url,$data null){$curl curl_init();curl_setopt($curl, CURLOPT_URL, $url);curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);if(!empty($data)){curl_setopt($cur…

springboot集成环信sdk报错

import io.swagger.client.ApiException; import io.swagger.client.api.MessagesApi; import io.swagger.client.model.Msg 这个是因为少两个包&#xff0c;只需要把在你的pom.xml添加以下代码即可&#xff0c;不要忘记点赞哈只需要添加两个包即可&#xff0c;你可以自行网上下…

解决 error: Your local changes to the following files would be overwritten by merge:XXXX

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 idea 上将本地代码推送到 git后 , 报错如下图 error: Your local changes to the following files would be overwritten by merge:src/…

深度有趣 | 30 快速图像风格迁移

简介 使用TensorFlow实现快速图像风格迁移&#xff08;Fast Neural Style Transfer&#xff09; 原理 在之前介绍的图像风格迁移中&#xff0c;我们根据内容图片和风格图片优化输入图片&#xff0c;使得内容损失函数和风格损失函数尽可能小 和DeepDream一样&#xff0c;属于网络…

转型从思维习惯的转变开始

摘要&#xff1a;首先建议大家不要轻易转向管理岗位&#xff0c;要认清自己是否适合做管理。转型过程中应把握好几点&#xff1a;良好的技术基础&#xff0c;它是赢得团队信任的前提&#xff0c;是把握团队整体方向的关键&#xff1b;培养大局观&#xff0c;只有站得高才能看得…

数据库小知识点(一直更新)

一、mysql查询是否含有某字段&#xff1a; mysql数据库查询带有某个字段的所有表名 SELECT * FROM information_schema.columns WHERE column_namecolumn_name; oracle数据库查询带有某个字段的所有表名 select column_name,table_name,from user_tab_columns where column_n…

其他运算符

原文地址&#xff1a;https://wangdoc.com/javascript/ void运算符 void运算符的作用是执行一个表达式&#xff0c;然后不返回任何值&#xff0c;或者说返回undefined。 void 0 // undefined void(0) // undefined 上面是void运算符的两种写法&#xff0c;都正确。建议采用后一…

git pull --rebase 做了什么? 以及 Cannot rebase: You have unstaged changes 解决办法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 最近刚学 git rebase&#xff0c;觉得很牛逼的样子&#xff0c; 结果今天就被打脸了。 git pull --rebase 1 报错&#xff1a; Cann…

vue如何实现单页缓存方案分析

实现全站的页面缓存&#xff0c;前进刷新&#xff0c;返回走缓存&#xff0c;并且能记住上一页的滚动位置&#xff0c;参考了很多技术实现&#xff0c;github上的导航组件实现的原理要么使用的keep-alive&#xff0c;要么参考了keep-alive的源码&#xff0c;但是只用keep-alive…

C语言常用函数简介

一、字符测试函数 isupper()测试字符是否为大写英文字ispunct()测试字符是否为标点符号或特殊符号isspace()测试字符是否为空格字符isprint()测试字符是否为可打印字符islower()测试字符是否为小写字母isgraphis()测试字符是否为可打印字符isdigit()测试字符是否为阿拉伯数字i…

thinkphp如何增加session的过期时间

原理&#xff1a;我们都知道session是建立在cookie的基础上的&#xff0c;如果浏览器cookie清楚了&#xff0c;则tp就会重新建立一个session。 操作&#xff1a;直接增加浏览器的cookie的到期时间&#xff0c;就可以使tp的session增加。

需求心得

电路图是人们为研究、工程规划的需要。我们组项目需要设计实现一个矢量图编辑器。在通过对变电站的电路图进行矢量绘图后&#xff0c;就可以通过矢量图的缩放详细信息。在分析需求后&#xff0c;写下心得&#xff01; 分析需求主要有一下几个步骤&#xff1a; 1. 获取和引导需求…