在第9章例9.9和例9.10的基础上,写一个函数del,用来删除动态链表中指定的结点。

在第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);
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值