在第9章例9.9和例9.10的基础上,写一个函数del,用来删除动态链表中指定的结点。
方法一:(删除成绩为99的学生)
#include <stdio.h>
#include <stdlib.h>
struct Student
{
int num;
float score;
struct Student *prev; //此处为增加的指向上一个结构体变量的指针
struct Student *next;
};
struct Student *input(); //定义输入函数
struct Student* del(struct Student *head, float n); //定义删除函数
void print(struct Student *stu); //定义输出函数
int main()
{
struct Student *stud; //定义结构体变量并输入动态链表
stud=input();
print(del(stud, 99)); //调用输出函数,参数为删除函数返回的指针值
return 0;
}
//输入函数
struct Student *input()
{
struct Student *p1, *p2, *head;
int n=0;
p1=p2=(struct Student*)malloc(sizeof(struct Student));
printf("Please enter No.%d student info: ", n+1);
scanf("%d %f", &p1->num, &p1->score);
head=NULL;
while (p1->num!=0)
{
n++;
if (n==1)
{
head=p1;
p1->prev=NULL; //在原例题基础上,将上一个指针指向上一个结构体指针
}
else
{
p2->next=p1;
p1->prev=p2;
}
p2=p1;
p1=(struct Student*)malloc(sizeof(struct Student));
printf("Please enter No.%d student info: ", n+1);
scanf("%d %f", &p1->num, &p1->score);
}
p2->next=NULL;
return head;
}
//删除函数
struct Student* del(struct Student *head, float n)
{
struct Student *p, *next;
for (p=head; p!=NULL; p=next) /*(①:执行第一个if,删除的是头结点②:执行第二个和第三个if,删除的是中间的结点
③:执行第二个if不执行第三个if,删除的是尾结点) */
{
next=p->next;
if (p->score==n)//若指针p指向的结构体的score成员和要删除的n大小相等,则执行if语句
{
if (p==head)//若指针p和头结点在同一位置,说明第一个结点就有符合要删除的score99 (适用于该结构体有两个结点以上的结点,且删除第一个结点)
head=p->next;//则把头指针head指向下一个结点,即删除第一个结点
if (p->prev!=NULL)//若指针p所指向的结点之前还有结点 (适用于该结构体有两个结点以上的结点,且删除不是第一个结点的中间结点或尾结点)
p->prev->next=p->next;//则把p的前一个结点的next指针指向p的下一个结点,即删除p所指向的结点
if (p->next!=NULL)//若p的下一个结点不为空(适用于该结构体有两个结点以上的结点,且删除不是第一个结点的中间结点)
p->next->prev=p->prev;//则把p的下一个结点的前指针指向p的前面一个结点,即删除p所指向的结点
free(p);
}
}
return head;//改变stu和stud所指向的地址
}
//输出函数
void print(struct Student *stu)
{
struct Student *p;
for (p=stu; p!=NULL; p=p->next)
{
printf("%d %.2f\n", p->num, p->score);
}
}
在VS2019下,需将源文件的scanf改为scanf_s:
#include <stdio.h>
#include <stdlib.h>
struct Student
{
int num;
float score;
struct Student* prev; //此处为增加的指向上一个结构体变量的指针
struct Student* next;
};
struct Student* input(); //定义输入函数
struct Student* del(struct Student* head, float n); //定义删除函数
void print(struct Student* stu); //定义输出函数
int main()
{
struct Student* stud; //定义结构体变量并输入动态链表
stud = input();
print(del(stud, 99)); //调用输出函数,参数为删除函数返回的指针值
return 0;
}
//输入函数
struct Student* input()
{
struct Student* p1, * p2, * head;
int n = 0;
p1 = p2 = (struct Student*)malloc(sizeof(struct Student));
printf("Please enter No.%d student info: ", n + 1);
scanf_s("%d %f", &p1->num, &p1->score);
head = NULL;
while (p1->num != 0)
{
n++;
if (n == 1)
{
head = p1;
p1->prev = NULL; //在原例题基础上,将上一个指针指向上一个结构体指针
}
else
{
p2->next = p1;
p1->prev = p2;
}
p2 = p1;
p1 = (struct Student*)malloc(sizeof(struct Student));
printf("Please enter No.%d student info: ", n + 1);
scanf_s("%d %f", &p1->num, &p1->score);
}
p2->next = NULL;
return head;
}
//删除函数
struct Student* del(struct Student* head, float n)
{
struct Student* p, * next;
for (p = head; p != NULL; p = next) /*(①:执行第一个if,删除的是头结点②:执行第二个和第三个if,删除的是中间的结点
③:执行第二个if不执行第三个if,删除的是尾结点) */
{
next = p->next;
if (p->score == n)//若指针p指向的结构体的score成员和要删除的n大小相等,则执行if语句
{
if (p == head)//若指针p和头结点在同一位置,说明第一个结点就有符合要删除的score99 (适用于该结构体有两个结点以上的结点,且删除第一个结点)
head = p->next;//则把头指针head指向下一个结点,即删除第一个结点
if (p->prev != NULL)//若指针p所指向的结点之前还有结点 (适用于该结构体有两个结点以上的结点,且删除不是第一个结点的中间结点或尾结点)
p->prev->next = p->next;//则把p的前一个结点的next指针指向p的下一个结点,即删除p所指向的结点
if (p->next != NULL)//若p的下一个结点不为空(适用于该结构体有两个结点以上的结点,且删除不是第一个结点的中间结点)
p->next->prev = p->prev;//则把p的下一个结点的前指针指向p的前面一个结点,即删除p所指向的结点
free(p);
}
}
return head;//改变stu和stud所指向的地址
}
//输出函数
void print(struct Student* stu)
{
struct Student* p;
for (p = stu; p != NULL; p = p->next)
{
printf("%d %.2f\n", p->num, p->score);
}
}
方法二:(删除成绩为99的学生)
#include <stdio.h>
#include <stdlib.h>
struct Student
{
int num;
float score;
struct Student *prev; //此处为增加的指向上一个结构体变量的指针
struct Student *next;
};
struct Student *input(); //定义输入函数
void del(struct Student *stu, float n); //定义删除函数
void print(struct Student *stu); //定义输出函数
int main()
{
struct Student *stud; //定义结构体变量并输入动态链表
stud=input();
del(stud, 99); //调用输出函数,参数为删除函数返回的指针值
print(stud);
return 0;
}
//输入函数
struct Student *input()
{
struct Student *p1, *p2, *head;
int n=0;
p1=p2=(struct Student*)malloc(sizeof(struct Student));
printf("Please enter No.%d student info: ", n+1);
scanf("%d %f", &p1->num, &p1->score);
head=NULL;
while (p1->num!=0)
{
n++;
if (n==1)
{
head=p1;
p1->prev=NULL; //在原例题基础上,将上一个指针指向上一个结构体指针
}
else
{
p2->next=p1;
p1->prev=p2;
}
p2=p1;
p1=(struct Student*)malloc(sizeof(struct Student));
printf("Please enter No.%d student info: ", n+1);
scanf("%d %f", &p1->num, &p1->score);
}
p2->next=NULL;
return head;
}
//删除函数
void del(struct Student *stu, float n)
{
struct Student *p, *next;
struct Student *head = stu;
for (p=head; p!=NULL; p=next) /*(①:执行第一个if,删除的是头结点②:执行第二个和第三个if,删除的是中间的结点
③:执行第二个if不执行第三个if,删除的是尾结点) */
{
next=p->next;
if (p->score==n)//若指针p指向的结构体的score成员和要删除的n大小相等,则执行if语句
{
if (p==head)//若指针p和头结点在同一位置,说明第一个结点就有符合要删除的score99 (适用于该结构体有两个结点以上的结点,且删除第一个结点)
head=p->next;//则把头指针head指向下一个结点,即删除第一个结点
if (p->prev!=NULL)//若指针p所指向的结点之前还有结点 (适用于该结构体有两个结点以上的结点,且删除不是第一个结点的中间结点或尾结点)
p->prev->next=p->next;//则把p的前一个结点的next指针指向p的下一个结点,即删除p所指向的结点
if (p->next!=NULL)//若p的下一个结点不为空(适用于该结构体有两个结点以上的结点,且删除不是第一个结点的中间结点)
p->next->prev=p->prev;//则把p的下一个结点的前指针指向p的前面一个结点,即删除p所指向的结点
//free(p);此处不加free(p),因为stu和被free的p有相同的地址,进行解引用会导致崩溃
}
}
*stu=*head;//改变sud和stud所指向的内存的内容
}
//输出函数
void print(struct Student *stu)
{
struct Student *p;
for (p=stu; p!=NULL; p=p->next)
{
printf("%d %.2f\n", p->num, p->score);
}
}
在VS2019下,需将源文件的scanf改为scanf_s:
#include <stdio.h>
#include <stdlib.h>
struct Student
{
int num;
float score;
struct Student* prev; //此处为增加的指向上一个结构体变量的指针
struct Student* next;
};
struct Student* input(); //定义输入函数
void del(struct Student* stu, float n); //定义删除函数
void print(struct Student* stu); //定义输出函数
int main()
{
struct Student* stud; //定义结构体变量并输入动态链表
stud = input();
del(stud, 99); //调用输出函数,参数为删除函数返回的指针值
print(stud);
return 0;
}
//输入函数
struct Student* input()
{
struct Student* p1, * p2, * head;
int n = 0;
p1 = p2 = (struct Student*)malloc(sizeof(struct Student));
printf("Please enter No.%d student info: ", n + 1);
scanf_s("%d %f", &p1->num, &p1->score);
head = NULL;
while (p1->num != 0)
{
n++;
if (n == 1)
{
head = p1;
p1->prev = NULL; //在原例题基础上,将上一个指针指向上一个结构体指针
}
else
{
p2->next = p1;
p1->prev = p2;
}
p2 = p1;
p1 = (struct Student*)malloc(sizeof(struct Student));
printf("Please enter No.%d student info: ", n + 1);
scanf_s("%d %f", &p1->num, &p1->score);
}
p2->next = NULL;
return head;
}
//删除函数
void del(struct Student* stu, float n)
{
struct Student* p, * next;
struct Student* head = stu;
for (p = head; p != NULL; p = next) /*(①:执行第一个if,删除的是头结点②:执行第二个和第三个if,删除的是中间的结点
③:执行第二个if不执行第三个if,删除的是尾结点) */
{
next = p->next;
if (p->score == n)//若指针p指向的结构体的score成员和要删除的n大小相等,则执行if语句
{
if (p == head)//若指针p和头结点在同一位置,说明第一个结点就有符合要删除的score99 (适用于该结构体有两个结点以上的结点,且删除第一个结点)
head = p->next;//则把头指针head指向下一个结点,即删除第一个结点
if (p->prev != NULL)//若指针p所指向的结点之前还有结点 (适用于该结构体有两个结点以上的结点,且删除不是第一个结点的中间结点或尾结点)
p->prev->next = p->next;//则把p的前一个结点的next指针指向p的下一个结点,即删除p所指向的结点
if (p->next != NULL)//若p的下一个结点不为空(适用于该结构体有两个结点以上的结点,且删除不是第一个结点的中间结点)
p->next->prev = p->prev;//则把p的下一个结点的前指针指向p的前面一个结点,即删除p所指向的结点
//free(p);此处不加free(p),因为stu和被free的p有相同的地址,进行解引用会导致崩溃
}
}
*stu = *head;//改变sud和stud所指向的内存的内容
}
//输出函数
void print(struct Student* stu)
{
struct Student* p;
for (p = stu; p != NULL; p = p->next)
{
printf("%d %.2f\n", p->num, p->score);
}
}
方法一改进:(删除任意成绩的学生)
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
struct Student
{
int num;
float score;
struct Student* prev;
struct Student* next;
};
struct Student* input();
void print(struct Student* stu);
struct Student* del(struct Student* stu, float n);
int main()
{
struct Student* stud;
float del_score;
stud = input();
printf("Please enter delete score: "); //从主函数中输入要删除的数据
scanf("%f", &del_score);
stud = del(stud, del_score);
print(stud);
return 0;
}
struct Student* input()
{
struct Student* p1, * p2, * head;
int n = 0;
p1 = p2 = (struct Student*)malloc(sizeof(struct Student));
printf("Please enter No.%d student info: ", n + 1);
scanf("%d %f", &p1->num, &p1->score);
head = NULL;
while (p1->num != 0)
{
n++;
if (n == 1)
{
head = p1;
p1->prev = NULL;
}
else
{
p2->next = p1;
p1->prev = p2;
}
p2 = p1;
p1 = (struct Student*)malloc(sizeof(struct Student));
printf("Please enter No.%d student info: ", n + 1);
scanf("%d %f", &p1->num, &p1->score);
}
p2->next = NULL;
return head;
}
struct Student* del(struct Student* head, float n)
{
struct Student* p, * next;
for (p = head; p != NULL; p = next) /*(①:执行第一个if,删除的是头结点②:执行第二个和第三个if,删除的是中间的结点
③:执行第二个if不执行第三个if,删除的是尾结点) */
{
next = p->next;
if (p->score == n)//若指针p指向的结构体的score成员和要删除的n大小相等,则执行if语句
{
if (p == head)//若指针p和头结点在同一位置,说明第一个结点就有符合要删除的score99 (适用于该结构体有两个结点以上的结点,且删除第一个结点)
head = p->next;//则把头指针head指向下一个结点,即删除第一个结点
if (p->prev != NULL)//若指针p所指向的结点之前还有结点 (适用于该结构体有两个结点以上的结点,且删除不是第一个结点的中间结点或尾结点)
p->prev->next = p->next;//则把p的前一个结点的next指针指向p的下一个结点,即删除p所指向的结点
if (p->next != NULL)//若p的下一个结点不为空(适用于该结构体有两个结点以上的结点,且删除不是第一个结点的中间结点)
p->next->prev = p->prev;//则把p的下一个结点的前指针指向p的前面一个结点,即删除p所指向的结点
free(p);
}
}
return head;//改变stu和stud所指向的地址
}
void print(struct Student* stu)
{
struct Student* p;
for (p = stu; p != NULL; p = p->next)
{
printf("%d %.2f\n", p->num, p->score);
}
}
在VS2019下,需将源文件的scanf改为scanf_s:
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
struct Student
{
int num;
float score;
struct Student* prev;
struct Student* next;
};
struct Student* input();
void print(struct Student* stu);
struct Student* del(struct Student* stu, float n);
int main()
{
struct Student* stud;
float del_score;
stud = input();
printf("Please enter delete score: "); //从主函数中输入要删除的数据
scanf_s("%f", &del_score);
stud = del(stud, del_score);
print(stud);
return 0;
}
struct Student* input()
{
struct Student* p1, * p2, * head;
int n = 0;
p1 = p2 = (struct Student*)malloc(sizeof(struct Student));
printf("Please enter No.%d student info: ", n + 1);
scanf_s("%d %f", &p1->num, &p1->score);
head = NULL;
while (p1->num != 0)
{
n++;
if (n == 1)
{
head = p1;
p1->prev = NULL;
}
else
{
p2->next = p1;
p1->prev = p2;
}
p2 = p1;
p1 = (struct Student*)malloc(sizeof(struct Student));
printf("Please enter No.%d student info: ", n + 1);
scanf_s("%d %f", &p1->num, &p1->score);
}
p2->next = NULL;
return head;
}
struct Student* del(struct Student* head, float n)
{
struct Student* p, * next;
for (p = head; p != NULL; p = next) /*(①:执行第一个if,删除的是头结点②:执行第二个和第三个if,删除的是中间的结点
③:执行第二个if不执行第三个if,删除的是尾结点) */
{
next = p->next;
if (p->score == n)//若指针p指向的结构体的score成员和要删除的n大小相等,则执行if语句
{
if (p == head)//若指针p和头结点在同一位置,说明第一个结点就有符合要删除的score99 (适用于该结构体有两个结点以上的结点,且删除第一个结点)
head = p->next;//则把头指针head指向下一个结点,即删除第一个结点
if (p->prev != NULL)//若指针p所指向的结点之前还有结点 (适用于该结构体有两个结点以上的结点,且删除不是第一个结点的中间结点或尾结点)
p->prev->next = p->next;//则把p的前一个结点的next指针指向p的下一个结点,即删除p所指向的结点
if (p->next != NULL)//若p的下一个结点不为空(适用于该结构体有两个结点以上的结点,且删除不是第一个结点的中间结点)
p->next->prev = p->prev;//则把p的下一个结点的前指针指向p的前面一个结点,即删除p所指向的结点
free(p);
}
}
return head;//改变stu和stud所指向的地址
}
void print(struct Student* stu)
{
struct Student* p;
for (p = stu; p != NULL; p = p->next)
{
printf("%d %.2f\n", p->num, p->score);
}
}
方法二改进:(删除任意成绩的学生)
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
struct Student
{
int num;
float score;
struct Student *prev;
struct Student *next;
};
struct Student *input();
void print(struct Student *stu);
void del(struct Student *stu, float n);
int main()
{
struct Student *stud;
float del_score;
stud=input();
printf("Please enter delete score: "); //从主函数中输入要删除的数据
scanf("%f", &del_score);
del(stud, del_score);
print(stud);
return 0;
}
struct Student *input()
{
struct Student *p1, *p2, *head;
int n=0;
p1=p2=(struct Student*)malloc(sizeof(struct Student));
printf("Please enter No.%d student info: ", n+1);
scanf("%d %f", &p1->num, &p1->score);
head=NULL;
while (p1->num!=0)
{
n++;
if (n==1)
{
head=p1;
p1->prev=NULL;
}
else
{
p2->next=p1;
p1->prev=p2;
}
p2=p1;
p1=(struct Student*)malloc(sizeof(struct Student));
printf("Please enter No.%d student info: ", n+1);
scanf("%d %f", &p1->num, &p1->score);
}
p2->next=NULL;
return head;
}
void del(struct Student *stu, float n)
{
struct Student *p, *next;
struct Student *head = stu;
for (p=head; p!=NULL; p=next) /*(①:执行第一个if,删除的是头结点②:执行第二个和第三个if,删除的是中间的结点
③:执行第二个if不执行第三个if,删除的是尾结点) */
{
next=p->next;
if (p->score==n)//若指针p指向的结构体的score成员和要删除的n大小相等,则执行if语句
{
if (p==head)//若指针p和头结点在同一位置,说明第一个结点就有符合要删除的score99 (适用于该结构体有两个结点以上的结点,且删除第一个结点)
head=p->next;//则把头指针head指向下一个结点,即删除第一个结点
if (p->prev!=NULL)//若指针p所指向的结点之前还有结点 (适用于该结构体有两个结点以上的结点,且删除不是第一个结点的中间结点或尾结点)
p->prev->next=p->next;//则把p的前一个结点的next指针指向p的下一个结点,即删除p所指向的结点
if (p->next!=NULL)//若p的下一个结点不为空(适用于该结构体有两个结点以上的结点,且删除不是第一个结点的中间结点)
p->next->prev=p->prev;//则把p的下一个结点的前指针指向p的前面一个结点,即删除p所指向的结点
//free(p);此处不加free(p),因为stu和被free的p有相同的地址,进行解引用会导致崩溃
}
}
*stu=*head;//改变sud和stud所指向的内存的内容
}
void print(struct Student *stu)
{
struct Student *p;
for (p=stu; p!=NULL; p=p->next)
{
printf("%d %.2f\n", p->num, p->score);
}
}
在VS2019下,需将源文件的scanf改为scanf_s:
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
struct Student
{
int num;
float score;
struct Student* prev;
struct Student* next;
};
struct Student* input();
void print(struct Student* stu);
void del(struct Student* stu, float n);
int main()
{
struct Student* stud;
float del_score;
stud = input();
printf("Please enter delete score: "); //从主函数中输入要删除的数据
scanf_s("%f", &del_score);
del(stud, del_score);
print(stud);
return 0;
}
struct Student* input()
{
struct Student* p1, * p2, * head;
int n = 0;
p1 = p2 = (struct Student*)malloc(sizeof(struct Student));
printf("Please enter No.%d student info: ", n + 1);
scanf_s("%d %f", &p1->num, &p1->score);
head = NULL;
while (p1->num != 0)
{
n++;
if (n == 1)
{
head = p1;
p1->prev = NULL;
}
else
{
p2->next = p1;
p1->prev = p2;
}
p2 = p1;
p1 = (struct Student*)malloc(sizeof(struct Student));
printf("Please enter No.%d student info: ", n + 1);
scanf_s("%d %f", &p1->num, &p1->score);
}
p2->next = NULL;
return head;
}
void del(struct Student* stu, float n)
{
struct Student* p, * next;
struct Student* head = stu;
for (p = head; p != NULL; p = next) /*(①:执行第一个if,删除的是头结点②:执行第二个和第三个if,删除的是中间的结点
③:执行第二个if不执行第三个if,删除的是尾结点) */
{
next = p->next;
if (p->score == n)//若指针p指向的结构体的score成员和要删除的n大小相等,则执行if语句
{
if (p == head)//若指针p和头结点在同一位置,说明第一个结点就有符合要删除的score99 (适用于该结构体有两个结点以上的结点,且删除第一个结点)
head = p->next;//则把头指针head指向下一个结点,即删除第一个结点
if (p->prev != NULL)//若指针p所指向的结点之前还有结点 (适用于该结构体有两个结点以上的结点,且删除不是第一个结点的中间结点或尾结点)
p->prev->next = p->next;//则把p的前一个结点的next指针指向p的下一个结点,即删除p所指向的结点
if (p->next != NULL)//若p的下一个结点不为空(适用于该结构体有两个结点以上的结点,且删除不是第一个结点的中间结点)
p->next->prev = p->prev;//则把p的下一个结点的前指针指向p的前面一个结点,即删除p所指向的结点
//free(p);此处不加free(p),因为stu和被free的p有相同的地址,进行解引用会导致崩溃
}
}
*stu = *head;//改变sud和stud所指向的内存的内容
}
void print(struct Student* stu)
{
struct Student* p;
for (p = stu; p != NULL; p = p->next)
{
printf("%d %.2f\n", p->num, p->score);
}
}