链表的快速排序

本文探讨了如何在单链表上应用快速排序算法,虽然比数组实现稍有复杂,但理解起来更为直观。通过取首元素为哨兵,将链表分为小于、等于和大于三个部分,再递归地对小于和大于部分进行排序,最后重新连接三个子链表,完成排序过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

感觉链表的快速排序也挺好写的,甚至比数组更容易理解,但不知道为什么看到很多人都说快排不适合单链表结构的数据。

思想:

  1. 取第一个元素为哨兵,遍历链表,将小于、等于、大于的元素分成3个子链表;
  2. 递归整理“小于”链表;
  3. 递归整理“大于”链表;
  4. 将3个链表连接起来。
代码实现如下:
//链表快速排序,返回最后一个元素的地址
myNode* quickSortForList(myNode* &head)
{
	if(head==nullptr||head->next==nullptr) return head;

	//分成小于,等于,大于哨兵的3个链表
	auto pivot=head;//取第一个元素为哨兵
	auto pt=head;//遍历指针
	myNode* ls_head=new myNode;//小于哨兵的链表头,该链表第一个元素无效
	myNode* eq_head=head;//等于哨兵的链表头,该链表第一个元素有效
	myNode* bg_head=new myNode;//大于哨兵的链表头,该链表第一个元素无效
	myNode* ls_pt=ls_head, *eq_pt=eq_head, *bg_pt=bg_head;
	while(pt=pt->next)
	{
		if(pt->val < pivot->val)
		{//小于哨兵,加到第一个链表后面
			ls_pt->next=pt;
			ls_pt=ls_pt->next;
		}
		else if(pt->val == pivot->val)
		{
			eq_pt->next=pt;
			eq_pt=eq_pt->next;
		}
		else 
		{
			bg_pt->next=pt;
			bg_pt=bg_pt->next;
		}
	}
	ls_pt->next=nullptr;//链表最后一个元素指向空指针
	eq_pt->next=nullptr;
	bg_pt->next=nullptr;
	

	ls_pt=quickSortForList(ls_head->next);//整理小于哨兵的链表,返回整理后的链表的最后一个元素的地址
	bg_pt=quickSortForList(bg_head->next);//

	if(ls_pt) //如果小于哨兵的链表不为空,则将3个链表首尾链接在一起
	{
		ls_pt->next=eq_head;
		eq_pt->next=bg_head->next;//由于第一个元素无效,bg_head->next才是头
		head=ls_head->next;//整理后链表的头指针
	}
	else
	{//如果小于哨兵的链表为空,合并其他2个链表
		eq_pt->next=bg_head->next;
		head=eq_head;
	}

	delete ls_head;
	delete bg_head;
	//如果大于哨兵的链表不为空返回该链表的最后一个元素的位置
	//否则返回等于哨兵的链表的最后一个元素的位置
	if(bg_pt) return bg_pt;
	else return eq_pt;

}

myNode定义:
class myNode
{
public :
	int val;
	myNode* next;
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值