一、简单总结:

1.冒泡:不断把大的往后移一步,维护排序终点;

2.插入:维护排序起点,从链表起点开始找插入位置,把小的往前插;

3.选择:维护排序起点,把最小挑出来放前面(注意:链表如果不允许交换值,因为对于每个节点都要维护pre, cur, next,因此可能造成排序起点的cur与最小节点的pre重叠的现象,需要分类讨论,祥见代码);

4.归并:两个辅助函数,findMid()负责寻找链表中间点,mergeTwoList()负责合并两个有序链表;

主程序,先递归将链表拆分(注意把中间点的next置为nullptr,否则会导致findMid()错误),拆分完不断两两合并链表,得到有序链表;

5.快排:只能将最左边的节点作为参照数(Pivot),快慢指针,快指针负责找比pivot小的节点,慢指针负责不断将大于等于pivot的节点与快指针节点进行值交换,其它思想与数组快排相同;

二、代码及注释

#include<iostream>
using namespace std;struct ListNode {int val;ListNode* next;ListNode() :val(0), next(nullptr) {};ListNode(int _val) :val(_val), next(nullptr) {};
};void print_list(ListNode* head) {ListNode* cur = head;while (cur) {cout << cur->val << " ";cur = cur->next;}cout << endl;
}// 冒泡排序
ListNode* bubble_sort(ListNode* head) {ListNode* dummy = new ListNode();dummy->next = head;ListNode* tail = nullptr; // 维护遍历终点// 不断把大的值往右转移,遍历终点总是能变成最大值,再更新遍历终点while (tail != head) {ListNode* pre = dummy;ListNode* cur = pre->next;ListNode* nxt = cur->next;while (nxt != tail) {if (nxt->val < cur->val) { // 穿针引线交换节点pre->next = nxt;cur->next = nxt->next;nxt->next = cur;}else {cur = cur->next;}pre = pre->next;nxt = cur->next;}tail = cur;}head = dummy->next;dummy = nullptr;delete dummy;return head;
}// 插入排序
ListNode* insert_sort(ListNode* head) {ListNode* dummy = new ListNode();dummy->next = head; ListNode* last_sorted = head; // 维护遍历起点ListNode* cur = head->next;while (cur) {// 如果排序起点<=当前节点值,说明位置正确,不用插入if (last_sorted->val <= cur->val) {last_sorted = last_sorted->next;}else {// 从开始往后遍历找到插入位置ListNode* pre = dummy;while (pre->next->val <= cur->val) pre = pre->next;last_sorted->next = cur->next;cur->next = pre->next;pre->next = cur;}cur = last_sorted->next;}head = dummy->next;dummy = nullptr;delete dummy;return head;
}// 选择排序
ListNode* select_sort(ListNode* head) {ListNode* dummy = new ListNode();dummy->next = head;ListNode* last_sorted = dummy; // 维护遍历起点while (last_sorted->next) {ListNode* pre = last_sorted;ListNode* cur = last_sorted->next;ListNode* min_cur = cur;ListNode* min_pre = pre;// 从遍历起点开始,寻找链表中的最小值while (cur) {if (cur->val < min_cur->val) {min_cur = cur;min_pre = pre;}cur = cur->next;pre = pre->next;}cur = last_sorted->next;pre = last_sorted;if (min_cur != cur) { // 如果存在比出发点小的最小节点if (min_pre == cur) { // 注意:可能会出现最小节点的前继节点刚好是cur节点的情况cur->next = min_cur->next;min_cur->next = cur;pre->next = min_cur;}else { ListNode* nxt = cur->next;min_pre->next = cur;cur->next = min_cur->next;pre->next = min_cur;min_cur->next = nxt;}}last_sorted = last_sorted->next;}head = dummy->next;dummy = nullptr;delete dummy;return head;
}// 归并排序
ListNode* mergeTowList(ListNode* L1, ListNode* L2) { // 合并两条有序链表if (!L1 || !L2) return L1 ? L1 : L2;if (L1->val < L2->val) {L1->next = mergeTowList(L1->next, L2);return L1;}else {L2->next = mergeTowList(L1, L2->next);return L2;}
}ListNode* findMid(ListNode* head) { // 找到链表中间点if (!head || !head->next) return head;   // 这里head->next也要考虑ListNode* slow = head, * fast = head->next; // 0 1 2 3 得到 1while (fast && fast->next) {slow = slow->next;fast = fast->next->next;}return slow;
}ListNode* merge_sort(ListNode* head) {if (!head || !head->next) return head; // 这里不要等到head == nullptr再返回,不然会栈溢出ListNode* mid = findMid(head);ListNode* nxt = mid->next; mid->next = nullptr; // 将链表拆成两条,这里必须断开,不然findMid返回结果出错ListNode* left = merge_sort(head);ListNode* right = merge_sort(nxt);return mergeTowList(left, right); // 合并两条排序链表
}// 快速排序
void q_sort(ListNode* head, ListNode* tail) {if (head == tail || head->next == tail) return; // head->next == tail直接返回(单个节点)ListNode* slow = head, *fast = head;int pivot = head->val;while (fast != tail) {if (fast->val < pivot) { // 如果快指针的值小于隔板值,慢指针往前一步,交换慢指针与快指针的值(因为此时慢指针肯定满足 >= pivot)slow = slow->next;int tmp = slow->val;slow->val = fast->val;fast->val = tmp;}fast = fast->next;}// 最后将隔板值换到中间,形成隔板左边都< pivot 隔板右边都 >= pivothead->val = slow->val;slow->val = pivot;q_sort(head, slow->next);q_sort(slow->next, tail);
}
ListNode* quick_sort(ListNode* head) {q_sort(head, nullptr);return head;
}//int main() {
//  srand((unsigned)time(NULL));
//  ListNode* head = new ListNode(rand() % 20);
//  ListNode* cur = head;
//  for (int i = 0; i < 9; ++i) {
//      cur->next = new ListNode(rand() % 20);
//      cur = cur->next;
//  }
//  print_list(head);
//  //head = insert_sort(head);
//  //head = bubble_sort(head);
//  //head = select_sort(head);
//  //head = merge_sort(head);
//  // head = quick_sort(head);
//  print_list(head);
//  while (head) {
//      ListNode* tmp = head->next;
//      delete head;
//      head = tmp;
//  }
//  return 0;
//}

仅作笔记使用~~如有错误还请指正!!!多谢!!如果觉得有帮助可以随便点点赞哈哈哈,溜了溜了~~~

C++ 五大链表排序(冒泡、插入、选择、归并、快排)相关推荐

  1. 排序算法整理(冒泡、选择、快排、堆排序、希尔、归并)

    文章目录 前言 插入排序 希尔排序 关键代码如下 归并排序 快速排序 堆排序 前言 大四了开始学了,希望为时不晚,呜呜. 总结数据结构的相关知识,代码会用java实现 其他相关部分: 2-3树.平衡树 ...

  2. C++数据结构和算法2 栈 双端/队列 冒泡选择插入归并快排 二三分查找 二叉树 二叉搜索树 贪婪 分治 动态规划

    C++数据结构和算法2 栈 双端/队列 冒泡选择插入归并快排 二三分查找 二叉树 二叉搜索树 贪婪 分治 动态规划 博文末尾支持二维码赞赏哦 _ github 章3 Stack栈 和 队列Queue= ...

  3. 10个数比大小(排序)——冒泡和选择

    10个数比大小(排序)--冒泡和选择 一. 冒泡法(起泡法) 冒泡排序的基本概念是(以升序排序为例): 依次比较相邻的两个数,将小数放在前面,大数放在后面.即在第一趟:首先比较第1个和第2个数,将小数 ...

  4. C语言排序算法 选择排序 插入排序 快速排序 qsort实现快排 堆排序

    常见排序算法 选择排序 选择排序(Selection sort)是一种简单直观的排序算法. 它的工作原理如下. 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素 ...

  5. SDUT OJ 数据结构实验之排序一:一趟快排

    数据结构实验之排序一:一趟快排 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem Descrip ...

  6. sdutacm- 数据结构实验之排序一:一趟快排

    数据结构实验之排序一:一趟快排 TimeLimit: 1000MSMemory Limit: 65536KB SubmitStatistic ProblemDescription 给定N个长整型范围内 ...

  7. 八大排序算法之快速排序(下篇)(快排的优化+非递归快排的实现)

    目录 一.前言 1.快速排序的实现: 快速排序的单趟排序(排升序)(快慢指针法实现):​ 2.未经优化的快排的缺陷 二.快速排序的优化 1.三数取中优化 优化思路: 2. 小区间插入排序优化 小区间插 ...

  8. php冒泡 插入选择 排序,说说PHP数组的三种排序(冒泡/选择/插入)方法

    说说PHP数组的三种排序(冒泡/选择/插入)方法 PHP #数组 #排序 #冒泡 #选择 #插入2012-05-30 10:17 一.冒泡排序法 说明:找到最大的数,排列到最后面,然后继续找 例: $ ...

  9. 排序——冒泡、选择、插入、希尔、快速、计数

    目录 创建随机数列 冒泡排序 选择排序 插入排序 希尔排序 快速排序 计数排序 归并排序 结果 常见排序算法比较 创建随机数列 import random import timeit #创建随机的数列 ...

  10. java 比较算法_JAVA排序算法实现和比较:冒泡,桶,选择,快排,归并

    一.冒泡排序: 实现思想: 重复地走访过要排序的元素列,一次比较两个相邻的元素,如果他们的顺序(如从大到小.首字母从A到Z)错误就把他们交换过来.走访元素的工作是重复地进行直到没有相邻元素需要交换,也 ...

最新文章

  1. axios与ajax区别
  2. mysql开发规范最新版本_MYSQL 开发规范
  3. 第三方支付账务系统设计难点 16
  4. 2017美国专利榜:IBM称霸全球!华为、京东方榜上有名!
  5. 7.IDA-创建结构体
  6. 谈谈surging 微服务引擎 2.0的链路跟踪和其它新增功能
  7. power bi 中计算_Power BI中的期间比较
  8. 11个小技巧,玩转Spring!
  9. 使用Nodejs将js文件转换成json文件
  10. 好用的格式化SQL工具SQL Prompt
  11. nvidia控制面板点了没反应win7_win7 nvidia控制面板没反应打不开 解决办法
  12. php宠物社交领养网站
  13. Word另存为PDF时,将目录转换为PDF书签
  14. 读书笔记 | 《人间处方》夏目漱石写给青年的信
  15. 《图像处理、分析与机器视觉》(第4版)阅读笔记——第五章 图像预处理
  16. js中find和findIndex的使用
  17. 文科类文献综述怎么写?
  18. 英文写作中单词的用法
  19. 使用阿里云物联网平台IoT Studio控制海康摄像头旋转
  20. 我的读书笔记 - 《暗时间》

热门文章

  1. 赠书 | 程序员学数学和算法基础畅销书单
  2. 今年护网蓝队防御具体实施方案
  3. oa 触发器导出流程html,哪些配套产品帮南京OA画龙点睛
  4. 【龙印】龙芯1c上双路16位AD芯片TM7705的linux驱动
  5. php接入aws短信,亚马逊短信(AWS-SMS)
  6. Microsoft Office 不同电脑不同电脑登录用户的数据同步
  7. 九种流行木马的发现和清除
  8. 网络技术人员要知道的100个安全工具
  9. php工厂模式计算器,php设计模式之工厂模式(工厂模式实现计算器功能)
  10. 飞信2009_那个时代独有的目光局限——浅谈“飞信”的兴衰