广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言实现单链表的快速排序算法
  • 501
分享到

C语言实现单链表的快速排序算法

2024-04-02 19:04:59 501人浏览 薄情痞子
摘要

目录背景设计思路算法主要步骤快速排序算法实现整个程序源代码测试案例总结背景 传统QuickSort算法最大不足之处在于,由于其基于可索引存储结构设计(一般为数组或索引表),因而无法用

背景

传统QuickSort算法最大不足之处在于,由于其基于可索引存储结构设计(一般为数组或索引表),因而无法用于链式存储结构,而链式存储结构的实际应用非常广泛,例如动态存储管理、动态优先级调度等等,故本文针对于单向链表,以QuickSort的分治策略为基础,提出一种可用于单向链表的快速排序算法。

设计思路

将单向链表的首节点作为枢轴节点,然后从单向链表首部的第二个节点开始,逐一遍历所有后续节点,并将这些已遍历节点的key与枢轴节点的key进行比较,根据比较结果,重新将这些节点链接为less和more两个单向链表,less中所包含节点的key均小于枢轴节点的 key;more中所包含节点的key均大于或等于枢轴节点的key。然后再对得到的两个单链表进行递归操作,将进行内部递归排序最后连接到枢轴上。同时为达到在每次划分后将规模更小的两个单向链表链接到枢轴节点上,必须记录各自的尾节点位置,即需要设置两个指向尾节点的指针。less链表的首节点指针设定为lesshead,尾节点指针设定为lessTail;more链表的首节点指针设定为 moreHead,尾节点指针设定为moreTail。当前正在遍历的节点指针设定为current。当单向链表遍历结束后,亦即完成了一趟划分, 如此递归进行,便可完成整个单向链表的排序。除此之外,为了简化将 less和more单向链表链接到枢轴节点前、后部的过程,还需设定两个指向单向链表尾节点的指针 lessTail和moreTail。在递归过程中,得到的单链表的长度会依次减小,直到长度减小到一的时候即为递归出口。

算法主要步骤

步骤1:算法接收两个指针,其中listHead指 向单向链表首节点,listTail为空指针,划分过程中,listTail将指向单向链表的尾节点,划分后用于链接less单向链表到枢轴节点前。
步骤2:如果单向链表listHead仅有一个节点,则说明已有序,本层递归结束,返回listHead。
步骤3:令lessHead、lessTail、moreHead和 moreTail为空,令current为listHead的next域,即单向链表的第二个节点。
步骤4:如果current节点为空,则转入步骤13。
步骤5:如果current节点的key小于枢轴节点(即listHead)的key,则current节点应链接到 less单向链表,转入步骤6;否则,current节点应链 接到more单向链表,转入步骤9。
步骤6:修改lessTail指针使其指向current 节点。如果lessHead为空,则转入步骤7;否则转入步骤8。
步骤7:将less节点链接为单链表的首节点。
步骤8:将current节点链接为less单链表的尾结点;
步骤9:修改moreTail指针使其指向current 节点。如果moreHead为空,则转入步骤10;否则转入步骤11。
步骤10:将currnet节点链接为more单向链表的首节点。
步骤11:将currnet节点链接为more单向链表的尾节点。
步骤12:将current节点移动到单向链表的下一个节点。
步骤13:如果more单向链表不为空,则转入步骤14;否则转入步骤18。
步骤14:标记more单向链表的结束位置,即 置moreTail的next域为空。
步骤15:递归调用本算法,继续划分more单 向链表,传人moreHead和moreTail。步骤16将经过递归排序的more单向链表 链接到枢轴节点后。
步骤17:修改listTail指针使其指向more— Tail,以便本层递归结束后供上层递归过程使用。
步骤18:由于more单向链表为空,则枢轴节 点便是尾节点,即置listHead的next域为空。 步骤19:修改listTail指针使其指向listHead。
步骤20:如果less单向链表不为空,则转入 步骤21;否则转入步骤24。
步骤21:标记less单向链表的结束位置,即 置lessTail的next域为空。
步骤22:递归调用本算法,继续划分less单 向链表,传人lessHead和lessTail。 步骤23将经过递归排序的less单向链表链 接到枢轴节点前。
步骤24:由于less单向链表为空,则枢轴节 点便是首节点,即置lessHead为listHead。
步骤25:本层递归结束,返回lessHead。
示意图如下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

快速排序算法实现

Linklist Quicksort(Linklist *listHead, Linklist *listTail)
{
	Lnode *current;
	Lnode* lessHead = NULL, *lessTail = NULL, *moreHead = NULL, *moreTail = NULL;
	current = (*listHead)->next;//每次取首节点为枢纽,current指向第二个节点用于遍历
	if ((*listHead)->next != NULL)//当链表节点数不为1时(说明链表未排好序)
	{
		for (current = (*listHead)->next; current; current = current->next)
		{
			if (current->key < (*listHead)->key)
			{
				if (lessHead == NULL)
					lessHead = current;
				else
					lessTail->next = current;
				lessTail = current;
			}//current结点key小于枢纽key时放入less链表
			else
			{
				if (moreHead == NULL)
					moreHead = current;
				else
					moreTail->next = current;
				moreTail = current;
			}//current结点key大于枢纽key时放入more链表
		}
		//根据枢纽结点将T链表分为less和more两个链表
		if (moreTail)
			moreTail->next = NULL;
		if (lessTail)
			lessTail->next = NULL;
		//将more链表尾结点next域置空
		if (moreHead != NULL)
		{
			moreTail->next = NULL;
			Quicksort(&moreHead, &moreTail);
			(*listHead)->next = moreHead;
			*listTail = moreTail;
		}
		//若moreHead不空,则current为more链表的尾结点,对more链表进行递归处理,将more链表接在枢纽节点后
		else
		{
			(*listHead)->next = NULL;
			*listTail = *listHead;
		}
		//若moreHead为空,则只有less链表(即结点key全小于枢纽),将枢纽结点接在less节点后
		if (lessHead != NULL)
		{
			lessTail->next = NULL;
			Quicksort(&lessHead, &lessTail);
			lessTail->next = *listHead;
			*listHead = lessHead;
		}
		//若lesseHead不空,对less链表进行递归处理,再将枢纽节点接在less链表后
		else
		{
			lessHead = *listHead;
		}
		//若lesseHead为空,则枢纽结点作为首节点
		return lessHead;
	}
	else
		return *listHead;
}

整个程序源代码

#include<stdio.h>
#include<malloc.h> 
typedef struct Lnode
{
	int key;
	struct Lnode* next;
}Lnode, *Linklist;
//链表结构体类型
Linklist createList(Linklist L, int n)
{
	L = (Linklist)malloc(sizeof(Lnode));
	L->next = NULL;
	Lnode *p, *r;
	r = L;
	p = (Lnode*)malloc(sizeof(Lnode));
	scanf("%d", &r->key);
	for (int i = 1; i < n; i++)
	{
		p = (Lnode*)malloc(sizeof(Lnode));
		scanf("%d", &p->key);
		r->next = p;
		r = p;
	}
	r->next = NULL;
	return L;
}
//初始初始化及尾插法(正序)创建单链表
Linklist getTail(Linklist L)
{
	while (L->next)
		L = L->next;
	return L;
}
//得到尾指针
void Print(Linklist L)
{
	Lnode *p;
	p = L;
	while (p)
	{
		printf("%d ", p->key);
		p = p->next;
	}
}
//遍历单链表
Linklist Quicksort(Linklist *listHead, Linklist *listTail)
{
	Lnode *current;
	Lnode* lessHead = NULL, *lessTail = NULL, *moreHead = NULL, *moreTail = NULL;
	current = (*listHead)->next;//每次取首节点为枢纽,current指向第二个节点用于遍历
	if ((*listHead)->next != NULL)//当链表节点数不为1时(说明链表未排好序)
	{
		for (current = (*listHead)->next; current; current = current->next)
		{
			if (current->key < (*listHead)->key)
			{
				if (lessHead == NULL)
					lessHead = current;
				else
					lessTail->next = current;
				lessTail = current;
			}//current结点key小于枢纽key时放入less链表
			else
			{
				if (moreHead == NULL)
					moreHead = current;
				else
					moreTail->next = current;
				moreTail = current;
			}//current结点key大于枢纽key时放入more链表
		}
		//根据枢纽结点将T链表分为less和more两个链表
		if (moreTail)
			moreTail->next = NULL;
		if (lessTail)
			lessTail->next = NULL;
		//将more链表尾结点next域置空
		if (moreHead != NULL)
		{
			moreTail->next = NULL;
			Quicksort(&moreHead, &moreTail);
			(*listHead)->next = moreHead;
			*listTail = moreTail;
		}
		//若moreHead不空,则current为more链表的尾结点,对more链表进行递归处理,将more链表接在枢纽节点后
		else
		{
			(*listHead)->next = NULL;
			*listTail = *listHead;
		}
		//若moreHead为空,则只有less链表(即结点key全小于枢纽),将枢纽结点接在less节点后
		if (lessHead != NULL)
		{
			lessTail->next = NULL;
			Quicksort(&lessHead, &lessTail);
			lessTail->next = *listHead;
			*listHead = lessHead;
		}
		//若lesseHead不空,对less链表进行递归处理,再将枢纽节点接在less链表后
		else
		{
			lessHead = *listHead;
		}
		//若lesseHead为空,则枢纽结点作为首节点
		return lessHead;
	}
	else
		return *listHead;
}
int main()
{
	Lnode* L = NULL;
	int n;
	printf("请输入元素个数\n");
	scanf("%d", &n);
	printf("请输入元素\n");
	L = createList(L, n);
	Lnode* listTail;
	listTail = getTail(L);
	Quicksort(&L, &listTail);
	printf("排序后元素序列为\n");
	Print(L);
	return 0;
}

整个程序已在Visual Studio 2017上运行通过

测试案例

(1)一般数据样例

在这里插入图片描述

(2)只有一个数据时

在这里插入图片描述

(2)有重复数据时

在这里插入图片描述

总结

到此这篇关于C语言实现单链表的快速排序算法的文章就介绍到这了,更多相关C语言快速排序算法内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C语言实现单链表的快速排序算法

本文链接: https://www.lsjlt.com/news/163078.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C语言实现单链表的快速排序算法
    目录背景设计思路算法主要步骤快速排序算法实现整个程序源代码测试案例总结背景 传统QuickSort算法最大不足之处在于,由于其基于可索引存储结构设计(一般为数组或索引表),因而无法用...
    99+
    2022-11-13
  • C语言实现快速排序算法实例
    首先我们要对一组数据进行排序: 在数组中选一个基准数(通常为数组第一个,黄圈圈标记了); 将数组中小于基准数的数据移到基准数左边,大于基准数的移到右边,怎么移动,后面说; 对于基准数...
    99+
    2022-11-13
  • C语言如何实现快速排序算法
    这篇文章将为大家详细讲解有关C语言如何实现快速排序算法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。代码#define  _CRT_SECURE_NO_WARNINGS 1/...
    99+
    2023-06-22
  • C++归并法+快速排序实现链表排序的方法
    本文主要介绍了C++归并法+快速排序实现链表排序的方法,分享给大家,具体如下: 我们可以试用归并排序解决: 对链表归并排序的过程如下。 找到链表的中点,以中点为分界,将链表拆分成...
    99+
    2022-11-12
  • C语言实现快速排序
    目录1. hoare法方法与步骤代码实现2. 挖坑法方法与步骤代码实现3. 前后指针法方法与步骤代码实现4. 快速排序的缺点与优化1.快速排序的缺点2.快速排序的优化① 三数取中法选...
    99+
    2023-05-14
    C语言快速排序算法 C语言快速排序 C语言排序算法
  • C#实现快速排序算法
    快速排序是应用最广泛的排序算法,流行的原因是它实现简单,适用于各种不同情况的输入数据且在一般情况下比其他排序都快得多。 快速排序是原地排序(只需要一个很小的辅助栈),将长度为 N 的...
    99+
    2022-11-13
  • c语言快速排序算法怎么使用
    使用快速排序算法,需要先定义一个快速排序函数,然后在主函数中调用该函数。下面是一个示例的C语言快速排序算法的实现:```c#incl...
    99+
    2023-09-21
    c语言
  • C语言如何实现快速排序
    今天小编给大家分享一下C语言如何实现快速排序的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。交换排序的思想基本思想:所谓交换,...
    99+
    2023-07-02
  • 详解C语言快速排序三种方法的单趟实现
    目录交换排序的思想冒泡排序的思想快速排序的整体框架快速排序单趟实现逻辑1. hoare版本单趟实现(左右指针法)2.挖坑法单趟排序实现3.前后指针法交换排序的思想 基本思想:所谓交换...
    99+
    2022-11-13
  • C语言实现交换排序算法(冒泡,快速排序)的示例代码
    目录前言一、冒泡排序1.基本思想2.优化3.扩展二、快速排序1.基本思想2.优化3.代码前言 查找和排序是数据结构与算法中不可或缺的一环,是前辈们在算法道路上留下的重要且方便的一些技...
    99+
    2022-11-13
  • C语言常见排序算法之交换排序(冒泡排序,快速排序)
    目录前言1.交换排序——冒泡排序1.1 算法思想1.2 动图演示1.3 冒泡最好的情况 2. 交换排序——快速排序...
    99+
    2022-11-13
  • C语言实题讲解快速掌握单链表上
    目录1、移除链表元素2、反转链表3、链表的中间节点4、链表中倒数第k个节点5、合并两个有序链表6、链表分割1、移除链表元素 链接直达: 移除链表元素 题目: 思路: 此题要综合考虑...
    99+
    2022-11-13
  • C语言实题讲解快速掌握单链表下
    目录1、移除链表元素2、反转链表3、链表的中间节点4、链表中倒数第k个节点5、合并两个有序链表6、链表分割1、移除链表元素 链接直达: 移除链表元素 题目:  思路: 此...
    99+
    2022-11-13
  • 详解C++实现链表的排序算法
    目录一、链表排序二、另外一种链表排序方式三、比较两种排序的效率四、下面通过交换结点实现链表的排序一、链表排序 最简单、直接的方式(直接采用冒泡或者选择排序,而且不是交换结点,只交换数...
    99+
    2022-11-12
  • 如何使用C语言实现快速排序
    本篇内容主要讲解“ 如何使用C语言实现快速排序”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“ 如何使用C语言实现快速排序”吧!快速排序的基本思想是:任取待排序数列中的一个数作为 key 值,通过...
    99+
    2023-07-05
  • C语言之快速排序算法(递归Hoare版)介绍
    废话不多说,先看代码 #define _CRT_SECURE_NO_WARNINGS 1 //快速排序算法,递归求解 #include <stdio.h> void ...
    99+
    2022-11-12
  • Python实现快速排序算法及去重的快速排序的简单示例
    快速排序由于排序效率在同为O(N*logN)的几种排序方法中效率较高,因此经常被采用。 该方法的基本思想是: 1.先从数列中取出一个数作为基准数。 2.分区过程,将比这个数大的数全放到它的右边,小于或等于它...
    99+
    2022-06-04
    快速 示例 算法
  • c/c++基础简单易懂的快速排序算法
    快速排序就是找一个基准,然后其左边要比他小,右边要比他大 int partition(int* a, int left, int right) { int pivot = le...
    99+
    2022-11-12
  • c语言如何实现排序算法
    小编给大家分享一下c语言如何实现排序算法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1.选择排序-简单选择排序选择排序是最简单的一种基于O(n2)时间复杂度的排...
    99+
    2023-06-15
  • C语言 单向链表的增删查改快速掌握
    目录前言一、创建二、单向链表的函数声明三、函数实现1.创建节点2.尾插节点3.头插4.尾删5.头删6.查找节点7.修改总结前言 链表是线性表的链式存储结构,它可以以O(1)的时间复杂...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作