16、创建动态链表并实现插入、删除等功能
题目:编程实现下列函数,并将以下所有函数组织在一个 C 程序中:
(1)编写函数 struct student *creat(void),建立一个有 n 名学生数据的头指针为 head 的单向动态链表。链表的结点类型为struct student,如下所示:
struct student{
long num; //学号
int score; //分数
struct student *next; //结点指针域
};
(2)编写函数 struct student *insert(struct student *head),从头指针为 head 的学生链表插入一 个新的学生数据结点。
(3)编写函数 struct student *del(struct student *head, long key), 从头指针为 head 的学生链表中删除 学号为 key 的那个结点。
(4)编写函数 int sum(struct student *head),返回头指针为 head 的学生链表中所有结点分数的和值。
(5)编写函数 void find(struct student *head), 输出头指针为 head 的学生链表中分数最高的学生的学号和分数。
(6)编写函数 void print(struct student *head), 输出头指针为 head 的学生链表中所有结点的内容。
#include<stdio.h>
#include<stdlib.h>
struct student{
long num;
int score;
struct student *next;
};
#define LEN sizeof(struct student) //LEN为结构体类型的存储大小 (define前要有#)
int n=0; //n为链表结点个数
struct student *creat(void);
struct student *insert(struct student *head);
struct student *del(struct student *head, long key);
int sum(struct student *head);
void find(struct student *head);
void print(struct student *head);
int main(){
struct student *head, *p1, *p2;
//学号与成绩输入“0 0”表示链表创建完成或插入结束或删除结束
printf("请按学号大小由小到大输入数据创建链表:\n");
head=creat();
printf("请输入插入结点的学号与成绩:\n");
head=insert(head);
long key;
printf("请输入要删除的结点的学号:\n");//(/与\要注意)
scanf("%d", &key);
head=del(head, key);
printf("所有分数的和值为:%d\n",sum(head));
//最高分的学号与成绩
find(head);
//输出链表全部内容
print(head);
return 0;
}
struct student *creat(void){ //创建链表的详细解释在C语言书P314
struct student *head, *p1, *p2; //当结点数(n)大于1时,p2为相邻两结点的前一个结点,而p1为相邻两结点的后一个结点
head=NULL; //初始时没有结点,故令head为NULL
p2=p1=(struct student*)malloc(LEN); //(p2=)p1=...的括号内容不能少,因为若一开始就输入0 0(即没有结点),执行p2->next= NULL需要p2有初始指向
scanf("%ld %d", &p1->num, &p1->score);//(少了取地址符编译不会报错,但运行程序时会出错)
while(p1->num != 0){ //注意最后要输入0 0才能结束循环
n++;
if(n==1) head=p1;
else p2->next = p1;
p2=p1;
p1=(struct student*)malloc(LEN);
scanf("%ld %d",&p1->num, &p1->score);
}
p2->next=NULL;
return head;
}
struct student *insert(struct student *head){
struct student *p1, *p2, *input;
p1=head;
input=(struct student*)malloc(LEN);
scanf("%ld %d", &input->num, &input->score);
if(head->num > input->num){
input->next = head; //插入到链表的表首之前
head=input;
}else{
while(p1 != NULL){
//因不同学生的学号不可能相同,故不必考虑p1->next == input->next的情况
if(p1->num < input->num){
p2=p1;
p1=p2->next;
}else{
p2->next = input; //插入到链表之中
input->next = p1;
break; //该break很关键,不可少,否则p1不会再移动,该while循环陷入死局不断重复执行else语句
}
}
}
if(p1 == NULL){
p1->next = input; //插入到链表的表尾之后
input->next = NULL;
}
return head;
}
struct student *del(struct student *head, long key){
struct student *p1, *p2;
p1=head;
if(head->num == key){
head=head->next;
n--;
}else{
while(p1!=NULL){
if(p1->num == key){
p2->next = p1->next;
n--;
break;
}else{
p2=p1;
p1=p2->next;
}
}
}
return head;
}
int sum(struct student *head){
struct student *p = head;
int s=0;
while(p != NULL){
s += p->score;
p=p->next;
}
return s;
}
void find(struct student *head){
struct student *p1, *p2;
p1=p2=head;
while(p1 != NULL){
//假设只有一个最高分
if(p2->score < p1->score){
p2=p1;
}
p1=p1->next;
}
printf("最高分为%d,该学生学号为%ld\n", p2->score, p2->num);
}
void print(struct student *head){
struct student *p1 = head;
printf("所有学生的学号与成绩为:\n");
while(p1 != NULL){
printf("%ld %d\n", p1->num, p1->score);
p1=p1->next;
}
}