S1E45:单链表1(头插法) 课后作业

测试题:
0. 相比起数组来说,单链表具有哪些优势呢?

答:长度非固定,可以申请添加长度

答案:对于数组来说,随机插入或者删除其中间的某一个元素,都是需要大量的移动操作,而单链表则完全没有这个问题。
数组插入图示:

单链表插入图示:


1. 相比起单链表来说,数组又具有哪些优势呢?$

答:简单明了

答案:对于单链表来说,随机访问中间的某一个元素,都是需要大量的跳转操作(从第一个元素开始,然后通过指针一个一个往后跳,最后抵达目标位置),而数组则完全没有这个问题(直接通过下标索引值一步到位地访问)。.E


2. 现在要求编写一个记账小程序,那么你应该考虑使用数组还是单链表来存放数据呢?依据是什么?

答:使用单链表,依据是记账是可持续的,存储长度需要可调节

答案:应该使用单链表比较合适,因为记账小程序要求随时可以从中间位置插入数据,并且具有写入操作多(每天记一记),读取操作少(月底看下总结)的特点,所以选择单链表来实现会更合适。
 

3. 请问下面代码存在什么问题?

struct A
{
        struct B b;
};
    
struct B
{
        struct A a;
}

答:无限嵌套,死循环

答案:还是无限递归。
解析:在 A 结构体声明中定义 B 结构体,但在 B 结构体中又定义 A 结构体。
这就相当于当某人问你和你女朋友什么时候结婚,你们的回复都是“她/他说什么时候就什么时候,我绝对不会告诉你什么时候”酱紫……

4. 本节视频最后的代码演示中小甲鱼在写 releaseLibrary 函数的时候犯了一个比较明显的错误,你能找出来并改正吗?

答:看不出来(错误

答案:

解析:
从逻辑上来说这是矛盾的:既然 library 指向的堆空间已经释放了,那么 library->next 理论上就是一个不存在的值,又何来 library = library->next; 呢?
应该这么改:

void releaseLibrary(struct Book *library)
{
        struct Book *temp;
    
        while (library != NULL)
        {
                temp = library;
                library = library->next;
                free(temp);
        }
}

5. 请问下面代码中,为什么 addBook(struct Book **library) 函数要使用两个星号(**)?

#include <stdio.h>
#include <stdlib.h>
    
struct Book
{
        char title[128];
        char author[40];
        struct Book *next;
};
        
void addBook(struct Book **library)
{
        struct Book *book;
        
        book = (struct Book *)malloc(sizeof(struct Book));
        if (book == NULL)
        {
                printf("内存分配失败了!\n");
                exit(1);
        }
        
        strcpy(book->title, "《零基础入门学习C语言》");
        strcpy(book->author, "小甲鱼");
        
        *library = book;
        book->next = NULL;
}
        
int main(void)
{
        struct Book *library = NULL;
        
        addBook(&library);
        
        return 0;
}

答:不理解(错误

答案:这就是传值和传地的区别啦。
上面代码的内存存储结构如下:

但是,如果你把代码改成下面这样(一个星号):

#include <stdio.h>
#include <stdlib.h>
    
struct Book
{
        char title[128];
        char author[40];
        struct Book *next;
};
        
void addBook(struct Book *library)
{
        struct Book *book;
        
        book = (struct Book *)malloc(sizeof(struct Book));
        if (book == NULL)
        {
                printf("内存分配失败了!\n");
                exit(1);
        }
        
        strcpy(book->title, "《零基础入门学习C语言》");
        strcpy(book->author, "小甲鱼");
        
        *library = book;
        book->next = NULL;
}
        
int main(void)
{
        struct Book *library = NULL;
        
        addBook(library);
        
        return 0;
}

那么,内存的存储结构就会变成:

看出区别来了吗?
addBook(library) 传递的是 library 指针的值,也就是把 NULL 传过去了;而 addBook(&library) 传递的是 library 指针的地址,自然,传过去的是指针的地址,那么要接住它就必须使用指向指针的指针(两个星号)啦~H

动动手:
0. 还记得上一节课后作业吗?
我们帮社区大妈编写了一个打疫苗的登记程序^o^Q
不过,那个只是实验品,因为它只能接受 3 个数据(小李、老王和法外狂徒张三)
这次,我们要求使用单链表来动态存储登记的数据(从堆中申请的空间记得在程序结束前要释放哦~)v
程序实现效果:

答:参考答案解答

#include <stdio.h>
#include <stdlib.h>

struct Date
{
	int year;
	int month;
	int day;
};


struct Record
{
	char name[16];
	int age;
	struct Date first;
	struct Date second;
	struct Record *next;
	
};


void getInput(struct Record *record)
{
	char ch;
	
	printf("请问姓名是:");
	scanf("%s",record->name);
	
	printf("请问年龄是:");
	scanf("%d",&record->age);
	
	printf("请问是否接种过疫苗(Y/N):");
	getchar();
	if(getchar() != 'Y')
	{
		record->first.year = 0;
		printf("请尽快接种疫苗!\n"); 	
	}
	else
	{
		printf("请输入第一针疫苗接种的日期(yyyy-mm-dd):");
		scanf("%d-%d-%d",&record->first.year,&record->first.month,&record->first.day);
	
		printf("请问是否接种第二针疫苗(Y/N):");	
		getchar();
		if(getchar() != 'Y')
		{
			record->first.year = 0;
			printf("请尽快接种第二针疫苗!\n"); 
		}
		else{
			printf("请输入第二针疫苗接种的日期(yyyy-mm-dd):");
			scanf("%d-%d-%d",&record->second.year,&record->second.month,&record->second.day);
		}
	}
	printf("\n");
}


void printRecord(struct Record *head)
{
	struct Record *record;
	
	record = head;
	
	while(record != NULL)
	{
		printf("姓名:%s",record->name);
		printf("年龄:%d\n",record->age);
		if(record->first.year == 1)
		{
			printf("第一针疫苗接种日期:%d-%d-%d\n",record->first.year,
			record->first.month,record->first.day);
			if(record->second.year == 1)
			{
				printf("第一针疫苗接种日期:%d-%d-%d\n",record->second.year,
				record->second.month,record->second.day);
			}
			else
			{
				printf("未接种第二针疫苗!\n"); 
			}
		}
		else
		{
				printf("未接种疫苗!\n"); 
		} 
		record = record->next;
	}
}

void addRecord(struct Record **head)
{
	struct Record *record, *temp;
	
	record = (struct Recoed *)malloc(sizeof(struct Record));
	if(record == NULL)
	{
		printf("内存分配失败\n");
		exit(1); 
	}
	getInput(record);
	
	if(*head != NULL)
	{
		temp = *head;
		*head = record;
		record->next = temp;
	}
	else
	{
		*head = record;
		record->next = NULL;
	}
	
}


void releaseRecord(struct Record *head)
{
	struct Record *temp;
	
	while(head != NULL)
	{
		temp = head;
		head = head->next;
		free(temp);
		
	}
	
}



int main(void)
{
	struct Record *record;
	int i,ch;
	
	while(1)
	{
		printf("是否需要录入(Y/N):");
		do
		{
			ch = getchar();
		}
		while(ch != 'Y' && ch !='N');
		
		if(ch == 'Y')
		{
			addRecord(&record);
		}
		else
		{
			break;
		}
	}
	printf("请问是否需要打印已录入数据(Y/N):");
    do
    {
            ch = getchar();
    } while (ch != 'Y' && ch != 'N');

    if (ch == 'Y')
    {
            printRecord(record);
    }

    releaseRecord(record);

    return 0;
	
	
	
}

 

答案:

#include <stdio.h>
#include <stdlib.h>
    
struct Date
{
        int year;
        int month;
        int day;
};
    
struct Record
{
        char name[16];
        int age;
        struct Date first;
        struct Date second;
        struct Record *next;
};
void getInput(struct Record *record);
void printRecord(struct Record *head);
void addRecord(struct Record **head);
void releaseRecord(struct Record *head);
    
void getInput(struct Record *record)
{
        printf("请问姓名是:");
        scanf("%s", record->name);
        printf("请问年龄是:");
        scanf("%d", &record->age);
        printf("请问是否接种过疫苗(Y/N):");
    
        getchar();
        if (getchar() != 'Y')
        {
                record->first.year = 0;
                printf("请尽快接种疫苗!\n");
        }
        else
        {
                printf("请输入第一针疫苗接种的日期(yyyy-mm-dd):");
                scanf("%d-%d-%d", &record->first.year, &record->first.month, &record->first.day);
    
                printf("请问是否接种第二针疫苗(Y/N):");
                getchar();
                if (getchar() != 'Y')
                {
                        record->second.year = 0;
                        printf("请尽快接种第二针疫苗!\n");
                }
                else
                {
                        printf("请输入第二针疫苗接种的日期(yyyy-mm-dd):");
                        scanf("%d-%d-%d", &record->second.year, &record->second.month, &record->second.day);
                }
        }
        putchar('\n');
}
    
void printRecord(struct Record *head)
{
        struct Record *record;
    
        record = head;
    
        while (record != NULL)
        {
                printf("姓名:%s,年龄:%d\n", (*record).name, (*record).age);
    
                if (record->first.year == 0)
                {
                        printf("未接种疫苗!\n\n");
                }
                else
                {
                        printf("第一针疫苗接种日期:%d-%d-%d,", (*record).first.year, (*record).first.month, (*record).first.day);
                }
    
                if ((*record).first.year != 0 && (*record).second.year == 0)
                {
                        printf("未接种第二针疫苗!\n\n");
                }
                else if((*record).first.year != 0)
                {
                        printf("第二针疫苗接种日期:%d-%d-%d\n\n", (*record).second.year, (*record).second.month, (*record).second.day);
                }
    
                record = record -> next;
        }
}
    
void addRecord(struct Record **head)
{
        struct Record *record, *temp;
    
        record = (struct Record *)malloc(sizeof(struct Record));
        if (record == NULL)
        {
                printf("内存分配失败!\n");
                exit(1);
        }
    
        getInput(record);
    
        if (*head != NULL)
        {
                temp = *head;
                *head = record;
                record->next = temp;
        }
        else
        {
                *head = record;
                record->next = NULL;
        }
}
    
void releaseRecord(struct Record *head)
{
        struct Record *temp;
    
        while (head != NULL)
        {
                temp = head;
                head = head->next;
                free(temp);
        }
}
    
int main(void)
{
        struct Record *head = NULL;
        int ch;
    
        while (1)
        {
                printf("请问是否需要录入(Y/N):");
                do
                {
                        ch = getchar();
                } while (ch != 'Y' && ch != 'N');
    
                if (ch == 'Y')
                {
                        addRecord(&head);
                }
                else
                {
                        break;
                }
        }
    
        printf("请问是否需要打印已录入数据(Y/N):");
        do
        {
                ch = getchar();
        } while (ch != 'Y' && ch != 'N');
    
        if (ch == 'Y')
        {
                printRecord(head);
        }
    
        releaseRecord(head);
    
        return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值