测试题:
0. 相比起数组来说,单链表具有哪些优势呢?
答:长度非固定,可以申请添加长度
答案:对于数组来说,随机插入或者删除其中间的某一个元素,都是需要大量的移动操作,而单链表则完全没有这个问题。
数组插入图示:
单链表插入图示:
答:简单明了
答案:对于单链表来说,随机访问中间的某一个元素,都是需要大量的跳转操作(从第一个元素开始,然后通过指针一个一个往后跳,最后抵达目标位置),而数组则完全没有这个问题(直接通过下标索引值一步到位地访问)。.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;
}