已有a,b两个链表,每个链表中的结点包括学号,成绩. 要求把两个链表合并, 按学号升序排列(C语言)

 选择排序

//选择排序
#include <stdio.h>
#include <stdlib.h>
typedef struct student{
	int num;    // 学号
	double grade;    // 成绩
	struct student *next;    // 指向下一个学生的指针
} student;

student *merge(student *a, student *b)
{
	// 先合并,后排序
	student *head = a;    // 头指针指向链表a的第一个节点
	while (a->next != NULL)    // 找到链表a的最后一个节点
	{
		a = a->next;
	}
	a->next = b;    // 将链表b接在链表a的最后一个节点后面

	// 选择排序,每次选最小的,放在未排序的链表头部
	student *p;
	p = head;    // p指向未排序部分的头节点
	while (p->next != NULL)    // 当还有未排序的节点时
	{
		a = p->next;    // a指向未排序部分的第一个节点
		while (a != NULL)    // 遍历未排序部分的节点
		{
			if (p->num > a->num)    // 如果p节点的学号大于a节点的学号,则交换两个节点的数据
			{
				int num = p->num;
				double grade = p->grade;
				p->num = a->num;
				p->grade = a->grade;
				a->num = num;
				a->grade = grade;
			}
			a = a->next;    // a指向下一个节点
		}
		p = p->next;    // p指向下一个未排序部分的头节点
	}
	return head;    // 返回排序后的链表的头指针
}

int main()
{
	student a[3] = { { 1, 79 }, { 4, 36 }, { 5, 79 } };    // 创建数组a,存储学生信息
	for (int i = 0; i < 2; i++)    // 将数组a中的节点连接起来
	{
		a[i].next = &a[i + 1];
	}

	student b[2] = { { 2, 38 }, { 6, 98 } };    // 创建数组b,存储学生信息
	for (int i = 0; i < 1; i++)    // 将数组b中的节点连接起来
	{
		b[i].next = &b[i + 1];
	}

	student *combine = merge(a, b);    // 合并并排序链表a和链表b

	while (combine != NULL)    // 遍历合并后的链表并输出学生信息
	{
		printf("%d -> %.2lf\n", combine->num, combine->grade);
		combine = combine->next;    // 指向下一个节点
	}
	return 0;
}

 插入排序

//插入排序
#include <stdio.h>
#include <stdlib.h>
typedef struct student{
	int num;    // 学号
	double grade;    // 成绩
	struct student *next;    // 指向下一个学生的指针
} student;

student* insertSort(student* head)//链表的插入排序
{
	if (head == NULL || head->next == NULL) //1,检查链表长度:如果链表为空或者只有一个节点,则不需要进行排序,直接返回链表头指针head
	{
		return head;
	}

	student temp; //2,创建辅助节点:用于处理链表头部的插入情况
	temp.next = head;//将辅助节点的next指针指向链表头指针head
	student* lastSorted = head; //3,初始化已排序部分: 创建一个指针lastSorted,指向已排序部分的最后一个节点
	student* current = head->next;//4,遍历链表:指向链表头指针head的下一个节点,即第二个节点
	while (current != NULL)//然后进入循环,遍历整个链表,直到当前节点current为空
	{
		//5,寻找插入位置:在每次循环中,判断当前节点current的学号num是否小于已排序部分的最后一个节点的学号lastSorted->num,如果是,说明当前节点需要插入到已排序部分,需要找到正确的插入位置
		if (current->num < lastSorted->num) 
		{
			//6,使用prev指针寻找插入位置:创建一个指针prev,初始时指向辅助节点dummy
			student* prev = &temp;
			//通过循环遍历已排序部分,直到找到合适的插入位置,即prev->next->num >= current->num
			while (prev->next->num < current->num) 
			{
				prev = prev->next;
			}

			lastSorted->next = current->next; //7,节点插入操作:将当前节点current从已排序部分断开,即lastSorted->next = current->next
			current->next = prev->next; //然后将当前节点插入到prev指针的后面,即current->next = prev->next和prev->next = current。
			prev->next = current;

			current = lastSorted->next;//8,更新当前节点:将当前节点指针current更新为已排序部分的下一个节点,即current = lastSorted->next
		}
		//9,更新已排序部分指针:如果当前节点current的学号不小于已排序部分的最后一个节点的学号,则将已排序部分指针lastSorted和当前节点指针current都向后移动一位
		else 
		{
			lastSorted = lastSorted->next;
			current = current->next;
		}
	}
	return temp.next;//10,返回排序后的链表头指针:最终返回辅助节点temp的next指针作为排序后的链表头指针
}

student* merge(student* a, student* b)
{//1,检查输入链表:首先,函数通过检查输入的两个链表指针a和b是否为空来判断需要合并的链表情况
	//如果其中一个链表为空,则直接返回另一个链表作为结果
	if (a == NULL)
	{
		return b;
	}
	if (b == NULL)
	{
		return a;
	}

	student dummy;//2,创建辅助节点:创建了一个名为dummy的辅助节点,用于构建合并后的链表
	student* tail = &dummy;//同时创建一个指针tail,指向dummy节点,用于记录合并后链表的尾部
	dummy.next = NULL;//3,初始化dummy节点:将辅助节点dummy的next指针置为NULL,表示初始时合并后的链表为空
	//4,合并两个链表:进入循环,在循环中比较两个链表的节点,并将较小的节点插入到合并后的链表中
	while (a != NULL && b != NULL)
	{
		if (a->num < b->num)//5,比较节点值:在每次循环中,比较两个链表当前节点a和b的学号num大小
		{
			//6,节点插入操作:如果节点a的学号小于节点b的学号,则将节点a插入到合并后链表的尾部
			tail->next = a;
			a = a->next; //然后将指针a向后移动一位
		}
		else //否则,将节点b插入到合并后链表的尾部,然后将指针b向后移动一位
		{
			tail->next = b;
			b = b->next;
		}
		tail = tail->next;//最后将tail指针也向后移动一位,指向合并后链表的新尾部。
		//7,处理剩余节点:当其中一个链表的节点全部插入到合并后的链表中后,可能还会有另一个链表中的节点未处理完毕
		//此时,需要将剩余的节点直接连接到合并后链表的尾部
		if (a != NULL)
		{
			tail->next = a;
		}
		else
		{
			tail->next = b;
		}
	}
		//8,返回合并后的链表头指针:最终返回辅助节点dummy的next指针作为合并后的链表头指针
		return dummy.next;
}

int main()
{
	student a[3] = { { 1, 79, NULL }, { 4, 36, NULL }, { 5, 79, NULL } };
	for (int i = 0; i < 2; i++) 
	{
		a[i].next = &a[i + 1];
	}

	student b[2] = { { 2, 38, NULL }, { 6, 98, NULL } };
	for (int i = 0; i < 1; i++)
	{
		b[i].next = &b[i + 1];
	}

	student* combined = merge(a, b);
	student* sorted = insertSort(combined);

	student* current = sorted;
	while (current != NULL) 
	{
		printf("%d -> %.2lf\n", current->num, current->grade);
		current = current->next;
	}
	return 0;
}

  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值