链表排序相关算法题|删除节点输出有序结果|不带头节点单链表排序|带头节点单链表排序|单链表快排(C)

删除节点输出有序结果

给定一个带表头节点的单链表,设head为头指针,data为整型元素
按递增次序输出单链表中的各节点的数据元素,并释放节点所占的存储空间
不允许使用数组做辅助空间

算法思想

应对链表进行遍历,在每趟遍历中查找出整个链表最小值元素,输出并释放节点所占空间;再查找最小值元素,输出并释放节点,如此下去直到链表为空,最后释放头节点所占的存储空间
![[Pasted image 20241112214041.png]]

遍历一遍后,prev的next为最小值节点
![[Pasted image 20241112214110.png]]

输出prev的next的data值
创建指针del保存prev的next
![[Pasted image 20241112214150.png]]

prev的next指向del的next
![[Pasted image 20241112214221.png]]

释放del节点
![[Pasted image 20241112214234.png]]

完成删除
从头开始再次遍历,最终输出的结果成递增排列

void MiniDelete(LinkList &head)
{
	// 循环到只剩头节点
	while (head->next)
	{
		// prev保存最小值节点的前驱节点的指针,初始假定prev的next是最小的
		LNode* prev = head;
		// cur为工作指针
		LNode* cur = prev->next;
		while (cur->next)
		{
			// 如果cur的next的值小于prev的next的值,将prev指向cur
			if (cur->next->data < prev->next->data)
			{
				prev = cur;
			}
			// cur往后移
			cur = cur->next;
		}
		// 输出元素最小值的数据
		printf("%d\n", prev->next->data);

		// 删除元素值最小的节点,释放节点空间
		LNode* del = prev->next;
		prev->next = del->next;
		free(del);
	}
	// 释放头节点
	free(head);
}

不带头节点单链表排序

已知不带头节点的线性链表head,将该链表按节点数据域大小从小到大重新链接
要求链接过程中不得使用除该链表以外的任何链节点空间

算法思想

本质上是排序问题
链表上排序采用直接插入排序比较方便
首先假定第一个节点有序,然后从第二个节点开始,依次插入到前面有序链表当中,最终达到整个链表有序

创建工作指针cur指向head的next
![[Pasted image 20241112223036.png]]

将第一个节点断开,变为有序链表
![[Pasted image 20241112223052.png]]

cur指针遍历整个待排序链表,直到cur指向NULL
创建指针next保存cur的下一个
![[Pasted image 20241112223138.png]]

创建一个指针指向有序链表中要插入位置的前一个节点
![[Pasted image 20241112223556.png]]

如果cur的值比head的节点的值小
需要将cur的next指向head
![[Pasted image 20241112223628.png]]

将最小的节点变为head节点,即cur节点
![[Pasted image 20241112224014.png]]

cur指向next,继续遍历待排序链表
![[Pasted image 20241112224040.png]]

下一轮循环,next指向cur的next
![[Pasted image 20241112224052.png]]

如果cur的值比head的值大
需要遍历有序链表,查找有序链表中小于cur的值的最后一个节点
用prev指针遍历,直到prev的next指向NULL,或者prev的next的值大于等于cur的值
这样cur直接插入在prev的后面

cur的next指向prev的next
![[Pasted image 20241112224449.png]]

prev的next指向cur
![[Pasted image 20241112224518.png]]

LinkList LinkListSort(LinkList head)
{
	// cur是工作指针,指向待排序的当前元素
	LNode* cur = head->next;
	// 假定第一个元素有序,即链表中现在只有head一个节点
	head->next = NULL;

	while (cur)
	{
		// next是cur的后继
		LNode* next = cur->next;
		// 每次循环将prev重新指向有序链表的第一个节点
		LNode* prev = head;
		// 处理待排序节点cur比第一个元素节点小的情况
		if (prev->data > cur->data)
		{
			// 链表指针指向最小元素
			cur->next = head;
			head = cur;
		}
		else
		{
			// 查找有序链表中小于cur的值的最后一个节点
			while(prev->next && prev->next->data < cur->data)
			{
				prev = prev->next;
			}
			// 将当前排序节点链入有序链表中
			cur->next = prev->next;
			prev->next = cur;
		}
		// cur指向下一个待排序节点
		cur = next;
	}
	return head;
}

带头节点单链表排序

设L为单链表的头节点地址,其数据节点的数据域都是正整数且无相同的
利用直接插入的原则把该链表整理成数据递增的有序单链表的算法

算法思想

单链表带头节点,要求用直接插入排序原则,从第二个节点开始,将各节点依次插入到有序链表中

LinkList LinkListInsertSort(LinkList &L)
{
	// 如果L不为空表
	if (L->next)
	{
		// cur指向第一节点的后继
		LNode* cur = L->next->next;
		// 认为第一元素有序,从第二个元素开始依次插入
		L->next->next = NULL;
	}
	
	while (cur)
	{
		// 暂存cur的后继
		LNode* next = cur->next;
		LNode* prev = L;
		// 查找插入的位置
		while (prev->next && prev->next->data < cur->data)
		{
			prev = prev->next;
		}
		// 将cur节点链入链表
		cur->next = prev->next;
		prev->next = cur;
	}
	cur = next;

	return L;
}

单链表快排

给一个链表的头节点head,将其按升序排列并返回排序后的链表

算法思想

遍历获取链表节点值,利用快排函数,qsort进行排序,再存储

int compare(void* a, void* b)
{
	// 排升序
	return *(int*)a - *(int*)b;
}
LinkList sortList(LinkList &head)
{
	// 若该链表是空表,返回NULL
	if (head == NULL)
		return NULL;

	// 创建一个足够大的数组,全部初始化为0
	int num[50000] = {0};
	int numsize = 0;
	// 创建一个工作指针cur指向head头节点
	LNode* cur = head;
	// 开始遍历,将链表中的数据存储到数组中
	while (cur)
	{
		num[numsize++] = cur->val;
		cur = cur->next;
	}
	// qsort将数组中的数据排序
	qsort(num, numsize, sizeof(int), compare);
	// 初始化cur指针和数组下标
	cur = head;
	numsize = 0;
	// 再遍历链表,将数组中的值依次存储到节点中
	while (cur)
	{
		cur->val = num[numsize++];
		cur = cur->next;
	}
	// 返回头节点
	return head;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值