C语言:已有a,b两个链表,每个链表中的节点包括学号,成绩。要求把两个链表合并,按学号的升序排列
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言:已有a,b两个链表,每个链表中的节点包括学号,成绩。要求把两个链表合并,按学号的升序排列相关的知识,希望对你有一定的参考价值。
//(未完成)已有a,b两个链表,每个链表中的节点包括学号,成绩。要求把两个链表合并,按学号的升序排列
#include<stdio.h>
#define NULL 0
struct student
long num;
float score;
struct student * next;
;
struct student a[5]=
1005,10.23,&a[1],
1004,10.54,&a[2],
1003,11.55,&a[3],
1002,12.32,&a[4],
1001,15.65,NULL
;
struct student b[5]=
2005,11.23,&b[1],
2004,12.54,&b[2],
2003,16.55,&b[3],
2002,14.32,&b[4],
2001,17.65,NULL
;
void print(struct student * head)//打印链表的函数
struct student * p;
p=head;
if(head==NULL)
else
do
printf("%ld %f \n",p->num,p->score);
p=p->next;
while(p!=NULL);
void * sx(struct student * head)//升序函数,返回值是head的地址。将所有的节点按升序排列。
/*
这里是需要编写升序程序的代码区域,我不会。你帮帮我。谢谢!
*/
return (head);
void main()
a[4].next=&b[0];//将两个链表先连接起来
struct student * head;
head=&a[0];
print(head);
printf("num 按升序排列之后的输出结果是 :\n");
head=sx(head);//将经过升序排列之后的节点链表的首地址,赋值给head
print(head);//打印升序之后的链表
// 用递归,每次找出原链表中学号最小的元素,插入到新链表的后面。
struct student *cursor, *first, *prev, *min;
first = NULL;
if (head == NULL)
return NULL;
for (cursor = min = head; cursor->next != NULL; cursor = cursor->next)
if (cursor->next->num < min->num)
prev = cursor;
min = cursor->next;
first = min;
if (min == head)
head = head->next;
else
prev->next = min->next;
first->next = sx(head);
return first;
本回答被提问者采纳
⭐算法入门⭐《链表》简单01 —— 237. 删除链表中的节点
🔥让天下没有难学的算法🔥
C语言免费动漫教程,和我一起打卡! 🌞《光天化日学C语言》🌞
入门级C语言真题汇总 🧡《C语言入门100例》🧡
几张动图学会一种数据结构 🌳《画解数据结构》🌳
组团学习,抱团生长 🌌《算法入门指引》🌌
竞赛选手金典图文教程 💜《夜深人静写算法》💜
一、题目
1、题目描述
请编写一个函数,使其可以删除某个链表中给定的(非尾)结点。传入函数的唯一参数为 要被删除的结点,注意:没有给定头结点 head。
样例输入:head = [3,4,5,6], node = 4
样例输出:[3,5,6]
2、基础框架
- C语言 版本给出的基础框架代码如下:
void deleteNode(struct ListNode* node){
}
3、原题链接
二、解题报告
1、思路分析
由于链表 删除结点 需要知道 前驱结点 是什么,而这个问题只给了 当前结点,所以没有办法删除 当前结点。
所以,我们可以把它的 后继结点 的数据拷贝到 当前结点,并且删除它的后继结点即可。
2、时间复杂度
- 这个问题相当于转换成删除某个结点的 后继结点,时间复杂度为 O ( 1 ) O(1) O(1)。
3、代码详解
- 首先,我们实现一个辅助函数,它的作用是在一个可重复数组中,找到一个数 v v v ,且下标最小,如果找不到,返回 − 1 -1 −1;实现方法就是二分。
struct ListNode* doDeleteNode(struct ListNode* head, int val){
struct ListNode *pre, *now;
if(head == NULL) {
return NULL; // (1)
}
if(head->val == val) { // (2)
return head->next;
}
pre = head, now = head->next; // (3)
while(now) {
if(now->val == val) { // (4)
pre->next = now->next;
break; // (5)
}
pre = now;
now = now->next; // (6)
}
return head; // (7)
}
void deleteNode(struct ListNode* node){
int tmp = node->val; // (8)
node->val = node->next->val;
node->next->val = tmp;
doDeleteNode(node, tmp); // (9)
}
- ( 1 ) (1) (1) 空链表直接返回空即可;
- ( 2 ) (2) (2) 等于头结点的情况,直接返回头结点的后继结点;
- ( 3 ) (3) (3) 记录 前驱结点 和 当前结点;
- ( 4 ) (4) (4) 找到需要删除的结点,直接让 它的前驱 指向 它的后继;
- ( 5 ) (5) (5) 由于题目要求只有一个,所以直接退出循环即可;
- ( 6 ) (6) (6) 前驱结点 和 当前结点 的指针都往前行进一格;
- ( 7 ) (7) (7) 返回列表头结点;
- ( 8 ) (8) (8) 需要 删除的结点 和 它的 后继结点 值进行交换;
- ( 9 ) (9) (9) 删掉它的后继结点;
三、本题小知识
文中的
doDeleteNode
是一个删除链表中某个结点的通用模板,其实这个问题实现可以很简单,但是其思想却是非常经典,需要有一层联想。
以上是关于C语言:已有a,b两个链表,每个链表中的节点包括学号,成绩。要求把两个链表合并,按学号的升序排列的主要内容,如果未能解决你的问题,请参考以下文章