C++ 五大链表排序(冒泡、插入、选择、归并、快排)
一、简单总结:
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++ 五大链表排序(冒泡、插入、选择、归并、快排)相关推荐
- 排序算法整理(冒泡、选择、快排、堆排序、希尔、归并)
文章目录 前言 插入排序 希尔排序 关键代码如下 归并排序 快速排序 堆排序 前言 大四了开始学了,希望为时不晚,呜呜. 总结数据结构的相关知识,代码会用java实现 其他相关部分: 2-3树.平衡树 ...
- C++数据结构和算法2 栈 双端/队列 冒泡选择插入归并快排 二三分查找 二叉树 二叉搜索树 贪婪 分治 动态规划
C++数据结构和算法2 栈 双端/队列 冒泡选择插入归并快排 二三分查找 二叉树 二叉搜索树 贪婪 分治 动态规划 博文末尾支持二维码赞赏哦 _ github 章3 Stack栈 和 队列Queue= ...
- 10个数比大小(排序)——冒泡和选择
10个数比大小(排序)--冒泡和选择 一. 冒泡法(起泡法) 冒泡排序的基本概念是(以升序排序为例): 依次比较相邻的两个数,将小数放在前面,大数放在后面.即在第一趟:首先比较第1个和第2个数,将小数 ...
- C语言排序算法 选择排序 插入排序 快速排序 qsort实现快排 堆排序
常见排序算法 选择排序 选择排序(Selection sort)是一种简单直观的排序算法. 它的工作原理如下. 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素 ...
- SDUT OJ 数据结构实验之排序一:一趟快排
数据结构实验之排序一:一趟快排 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem Descrip ...
- sdutacm- 数据结构实验之排序一:一趟快排
数据结构实验之排序一:一趟快排 TimeLimit: 1000MSMemory Limit: 65536KB SubmitStatistic ProblemDescription 给定N个长整型范围内 ...
- 八大排序算法之快速排序(下篇)(快排的优化+非递归快排的实现)
目录 一.前言 1.快速排序的实现: 快速排序的单趟排序(排升序)(快慢指针法实现): 2.未经优化的快排的缺陷 二.快速排序的优化 1.三数取中优化 优化思路: 2. 小区间插入排序优化 小区间插 ...
- php冒泡 插入选择 排序,说说PHP数组的三种排序(冒泡/选择/插入)方法
说说PHP数组的三种排序(冒泡/选择/插入)方法 PHP #数组 #排序 #冒泡 #选择 #插入2012-05-30 10:17 一.冒泡排序法 说明:找到最大的数,排列到最后面,然后继续找 例: $ ...
- 排序——冒泡、选择、插入、希尔、快速、计数
目录 创建随机数列 冒泡排序 选择排序 插入排序 希尔排序 快速排序 计数排序 归并排序 结果 常见排序算法比较 创建随机数列 import random import timeit #创建随机的数列 ...
- java 比较算法_JAVA排序算法实现和比较:冒泡,桶,选择,快排,归并
一.冒泡排序: 实现思想: 重复地走访过要排序的元素列,一次比较两个相邻的元素,如果他们的顺序(如从大到小.首字母从A到Z)错误就把他们交换过来.走访元素的工作是重复地进行直到没有相邻元素需要交换,也 ...
最新文章
- axios与ajax区别
- mysql开发规范最新版本_MYSQL 开发规范
- 第三方支付账务系统设计难点 16
- 2017美国专利榜:IBM称霸全球!华为、京东方榜上有名!
- 7.IDA-创建结构体
- 谈谈surging 微服务引擎 2.0的链路跟踪和其它新增功能
- power bi 中计算_Power BI中的期间比较
- 11个小技巧,玩转Spring!
- 使用Nodejs将js文件转换成json文件
- 好用的格式化SQL工具SQL Prompt
- nvidia控制面板点了没反应win7_win7 nvidia控制面板没反应打不开 解决办法
- php宠物社交领养网站
- Word另存为PDF时,将目录转换为PDF书签
- 读书笔记 | 《人间处方》夏目漱石写给青年的信
- 《图像处理、分析与机器视觉》(第4版)阅读笔记——第五章 图像预处理
- js中find和findIndex的使用
- 文科类文献综述怎么写?
- 英文写作中单词的用法
- 使用阿里云物联网平台IoT Studio控制海康摄像头旋转
- 我的读书笔记 - 《暗时间》
热门文章
- 赠书 | 程序员学数学和算法基础畅销书单
- 今年护网蓝队防御具体实施方案
- oa 触发器导出流程html,哪些配套产品帮南京OA画龙点睛
- 【龙印】龙芯1c上双路16位AD芯片TM7705的linux驱动
- php接入aws短信,亚马逊短信(AWS-SMS)
- Microsoft Office 不同电脑不同电脑登录用户的数据同步
- 九种流行木马的发现和清除
- 网络技术人员要知道的100个安全工具
- php工厂模式计算器,php设计模式之工厂模式(工厂模式实现计算器功能)
- 飞信2009_那个时代独有的目光局限——浅谈“飞信”的兴衰