重写单链表的快速排序

2018年第一次试着写单链表的快速排序。所使用的方法虽然代码非常简洁,只有20行,但可惜并不是纯正的快速排序,而且使用的是数据交换也不是节点链接改变,造成效率也有点问题。后来又于2022年重写单链表的快速排序。这一次想出了一种很容易理的解方法,且是比较纯正的快速排序了,但可惜代码行数较多,近60行了,且其中引入了2个局部变量作为辅助,并不那么干净。
以上这一切都记录在拙作《单链表的快速排序与归并排序》中了。(这篇文章还另外介绍了单链表的归并排序)

今天忽有兴趣重写一下单链表的快速排序。写之前没有看以前的代码,使得思维并没有受到之前程序的影响。完成后,只觉今是而昨非。现在的代码比之前的有了许多进步,比如:是纯正的快速排序了;行数也由近60行缩减到39行了。虽然还觉得有哪里不那么完美,奈何水平有限,暂且如此吧。

算法本身不再介绍了;但在贴出代码之前,还是先介绍下具体写法。
首先,这是一个函数,比如就叫quick_sort_singly_linked_list吧。
第1个问题,它返回的是什么?有2种写法皆可。
第一种写法,它返回一个Node *,代表排序后的单链表的首节点;
第二种写法,它什么也不返回,即返回值为void; 这也是可以的,因为可以将首节点作为一个参数放在参数列表中,比如弄一个二级指针。
为简便起见,这里还是采用大家耳熟能详的写法,即返回Node *.

第2个问题,它的参数是什么呢?
可以和数组的快速排序做对比。因此,应该有2个参数,即 (Node * head, Node * tail).
这里的tail是取不到的,即需要做排序的节点是在[head, tail)这个区间。这也符合一开始的时候tailnullptr.

核心的做法是什么呢?

  • 使用指针p遍历[head, tail)
  • 指针h1代表第一个链表的首节点,即所有小于等于head的节点组成的链表
  • 指针h1p代表第一个链表的游标,因此其最后值代表第一个链表的最后一个节点
  • 指针h2代表第二个链表的首节点,及所有大于head的节点组成的链表
  • 指针h2p代表第二个链表的游标,因此其最后的值代表第二个链表的最后一个节点,也即tail的前一个节点
  • nullptr作为h1h1p的初始值,因为一个链表里未必有比head小或等的节点
  • head作为h2h2p的初始值
  • 一次遍历走完以后,需要使用if (h1) h1p->next = head;来把第一个链表和第二个链表连接成一个链表
  • 之后,需根据h1是否为nullptr来判定如何进行递归处理
  • 普通情况下,以(h1, head)(head->next, tail)分别对这2段链表进行递归的快速排序; 然后再用head->next = p2;将递归后的2段结果进行连接(p2为第二段链表递归调用的返回值)
  • 若是h1nullptr的情况,则更简单,只需对(head->next, tail)进行递归排序,等于只是排除了head这一个元素,因为它就是最小的;
  • 最终返回的是递归后的第一个链表的首节点p1;(若h1nullptr, 则将递归的结果赋给head->next, 然后返回head即可)

文字写出来实在是太罗嗦了。看代码则简洁很多。

#include <iostream>
using namespace std;struct Node {int val;Node * next;Node(int v, Node * p=nullptr) : val(v), next(p) {}
};void print_linked_list(Node *p) {while (p) {cout << p->val << " ";p = p->next;}cout << endl;
}void delete_linked_list(Node *p) {while (p != nullptr) {Node * tmp = p->next;delete p;p = tmp;}
}// For [head, tail), put the head in the middle, so that, 
// left nodes <= head < right nodes
// Return: the latest head node of the singly linked list 
Node * quick_sort_singly_linked_list(Node * head, Node * tail)
{if (head == tail || head->next == tail) return head;Node *h1 = nullptr, *h1p = nullptr;Node *h2 = head, *h2p = head;Node * p = head->next; while (p != tail) {if (p->val <= head->val) {if (h1) {h1p->next = p;h1p = p;}else { // h1 is nullptr, i.e. this is the first smaller nodeh1 = h1p = p;}}else { // p->val > head->val h2p->next = p; h2p = p;}p = p->next; }// Join the 2 linked list if (h1) h1p->next = head;h2p->next = tail; if (h1 == nullptr) { // head is the minimum node in [head, tail)head->next = quick_sort_singly_linked_list(head->next, tail);return head;}Node * p1 = quick_sort_singly_linked_list(h1, head);Node * p2 = quick_sort_singly_linked_list(head->next, tail);head->next = p2;return p1;   
}void test_case_01()
{Node * a1 = new Node(10);Node * a2 = new Node(5);Node * a3 = new Node(8);Node * a4 = new Node(20);Node * a5 = new Node(26);Node * a6 = new Node(18);a1->next = a2;a2->next = a3;a3->next = a4;a4->next = a5;a5->next = a6;print_linked_list(a1);Node * h = quick_sort_singly_linked_list(a1, nullptr);print_linked_list(h);delete_linked_list(h);
}int main()
{test_case_01();return 0;
}

(END)

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

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

相关文章

贪吃蛇(C语言实现)

贪食蛇&#xff08;也叫贪吃蛇&#xff09;是一款经典的小游戏。 —————————————————————— 本博客实现使用C语言在Windows环境的控制台中模拟实现贪吃蛇小游戏。 实行的基本功能&#xff1a; • 贪吃蛇地图的绘制 • 蛇吃食物的功能&#xff08;上、…

详解DNS服务

华子目录 概述产生原因作用连接方式 因特网的域名结构拓扑分类域名服务器类型划分 DNS域名解析过程分类解析图图过程分析注意 搭建DNS域名解析服务器概述安装软件bind服务中的三个关键文件 配置文件分析主配置文件共4部分组成区域配置文件作用区域配置文件示例分析正向解析反向…

动态规划 Leetcode 70 爬楼梯

爬楼梯 Leetcode 70 学习记录自代码随想录 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xff1a;有两种方法可以爬到…

SpringCloud 微服务架构编码构建

一、前言 接下来是开展一系列的 SpringCloud 的学习之旅&#xff0c;从传统的模块之间调用&#xff0c;一步步的升级为 SpringCloud 模块之间的调用&#xff0c;此篇文章为第一篇&#xff0c;即不使用 SpringCloud 组件进行模块之间的调用&#xff0c;后续会有很多的文章循序渐…

️ IP代理实操指南:如何在爬虫项目中避免封禁和限制 ️‍♂️

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

moreutils yum安装

在基于RPM的Linux发行版中&#xff0c;如CentOS、Red Hat Enterprise Linux或Fedora&#xff0c;你可以使用yum&#xff08;在较旧版本中&#xff09;或dnf&#xff08;在较新版本中&#xff09;来安装moreutils软件包。不过需要注意的是&#xff0c;默认的官方仓库可能并未包含…

企业战略管理 找准定位 方向 使命 边界 要干什么事 要做多大的生意 资源配置投入

AI突破千行百业&#xff0c;也难打破护城河 作为每个企业或个人的立命生存之本&#xff0c;有的企业在某个领域长期努力筑起了高高的护城河。 战略是什么&#xff1f;用处&#xff0c;具体内容 企业战略是指企业为了实现长期目标&#xff0c;制定的总体规划和长远发展方向。…

通过Forms+Automate+Lists+审批,实现用车申请流程

因为Sham公司目前用的用车申请流程是使用的K2系统&#xff0c;用户申请后&#xff0c;我们还需要单独另行输入Excel来汇总申请记录&#xff0c;当然K2也能导出&#xff0c;但是需要每次导出也是很麻烦的&#xff0c;而且不灵活。 刚好最近发现Forms与Automate能联通&#xff0…

华容道问题求解_详细设计(六)之简单互动和动画

简单互动 为了增加趣味性&#xff0c;增加了简单的互动功能&#xff0c;即实现了一个简单的华容道游戏。在HrdGame中有两个鼠标操作的函数&#xff0c;在传入的控件中调用这个两个函数就可以了。 代码如下&#xff1a; Click事件 private void pnl_GameBoard_MouseClick(objec…

华为OD面试分享9(2024年)

1.3 告知简历筛选通过 1.8 资格面,就简单问了一下gap原因,离职原因,期望薪水,还问了一下技术栈 这期间本来在准备机试,结果机试我上半年考了一次,但是后面没去od,hr告知成绩好像还有效就没有重新机试。具体题目忘了。 1.17 技术一面 上来先自我介绍,然后问了一下上…

Java服务器-Disruptor使用注意

最近看了一下部署后台的服务器状况&#xff0c;发现我的一个Java程序其占用的CPU时长超过100%&#xff0c;排查后发现竟是Disruptor引起的&#xff0c;让我们来看看究竟为什么Disruptor会有这样的表现。 发现占用CPU时间超过100%的进程 首先是在服务器上用top命令查看服务器状…

C语言 寻找单身狗(2个

此题知识&#xff1a;a^0a;a^a0;传值调用和传址调用要分清作用 题目&#xff1a;在 1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;6&#xff0c;1&#xff0c;3&#xff0c;4&#xff0c;5这几个数字中找出只出现一次的数字并打印在屏幕上 解题思路&…

vue,provide和inject,备忘

在Vue.js应用中&#xff0c;provide 和 inject 是一对API&#xff0c;用于实现组件间的跨层级依赖注入。provide 在父组件中定义要向下传递的属性或方法&#xff0c;而 inject 在子组件中声明它需要从祖先组件那里注入的属性。 具体到您的例子&#xff1a; // 在根组件或任意…

超越基础:提升你的数据采集策略与IP代理的高级应用

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

【AI辅助研发】-趋势:大势已来,行业变革

【AI辅助研发】-趋势&#xff1a;大势已来&#xff0c;行业变革 引言 在科技日新月异的今天&#xff0c;人工智能&#xff08;AI&#xff09;技术已逐渐渗透到各行各业&#xff0c;其中软件研发行业更是受益匪浅。AI辅助研发已成为大势所趋&#xff0c;不仅提高了软件开发的效…

鸿蒙Harmony应用开发—ArkTS声明式开发(通用属性:动态属性设置)

动态设置组件的属性&#xff0c;支持开发者在属性设置时使用if/else语法&#xff0c;且根据需要使用多态样式设置属性。 说明&#xff1a; 从API Version 11开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 attributeModifier attributeMo…

js之原型链

在JavaScript中&#xff0c;原型链是一种用于实现继承和属性查找的机制。每个对象都有一个内部属性[[Prototype]]&#xff0c;这个属性指向创建该对象时使用的构造函数的“prototype"属性。对象的方法和属性定义在它的原型对象上。 1.原型&#xff08;Prototypes&#xf…

RHCE——一、OpenEuler22.03安装部署及例行性任务

RHCE 一、OpenEuler22.03安装部署及例行性任务 一、网络服务1.准备工作2、RHEL9操作系统的安装部署3、配置并优化OpenEuler22.034、网络配置实验&#xff1a;修改网络配置 二、例行性工作1、 单一执行的例行性任务&#xff1a;at&#xff08;一次性&#xff09;at命令详解 2、循…

AI赋能下的研发新时代:2024年研发趋势展望

引言&#xff1a; 在技术的迅猛发展下&#xff0c;人工智能&#xff08;AI&#xff09;已经不再是科幻小说中的幻想&#xff0c;而是我们日常生活和工作中不可或缺的一部分。特别是在研发领域&#xff0c;AI的应用已经逐渐渗透到了各个环节&#xff0c;为科学家、工程师和研究…

[综述笔记]Graph Neural Networks in Network Neuroscience

论文网址&#xff1a;Graph Neural Networks in Network Neuroscience | IEEE Journals & Magazine | IEEE Xplore 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xf…