单链表
int main(void){
struct Test{
int x;
int y;
//错误写法:struct Test test;
struct Test *test;//正确写法,指针指向结构体
}
}
链表是一种常见的数据结构,根据需求,我们可以构造出单链表、双链表、循环链表和块状链表等。链表的出现很大程度上弥补了数组的先天不足。
[head]———>>[[信息域(存放信息)] [指针(指向链表的下一个元素)]]———>>[[信息域] [指针]]———>>[[信息域] [指针]]———>>[NULL]
//头插法
#include <stdlib.h>
//建立节点
struct Book{
char title[128];
char author[40];
struct Book *next;
};
void getInput(struct Book *book){
printf("请输入书名:");
scanf("%s", book->title);
printf("请输入作者:");
scanf("%s", book->author);
}
//在单链表中插入元素
//形参字面上的意思:(*library)是头节点指针library进行一层解引用,然后对其指向的内容(地址)再进行一次解引用
void addBook(struct Book **library) {
struct Book *book, *temp;
//新建一个新的节点
book = (struct Book *)malloc(sizeof(struct Book));
if (book == NULL){
printf("内存分配失败了\n");
exit(1);
}
//填充内容
getInput(book);
if (*library != NULL){
temp = *library;
*library = book;
book->next = temp;
}
else{
*library = book;
book->next = NULL;
}
}
void printLibrary(struct Book *library){
struct Book *book;
int count = 1;
book = library;
while (book != NULL){
printf("Book%d:", count);
printf("书名:%s:", book->title);
printf("作者:%s:", book_>author);
book = book->next;
count++;
}
}
void releaseLibrary(struct Book **library){
struct book *temp;
while (*library != NULL){
temp = *library;
*library = (*library) -> next;
free(temp);
}
}
int main(void){
//library作为头节点指针进行解引用,得到其存放的值,即下一个节点的地址指针
struct Book *library = NULL;
while(1){
printf("请问是否需要录入书籍信息(Y/N):");
do{
ch = getchar();
}while (ch != 'Y' && ch != 'N');
if (ch == 'Y'){
addBook(&library);
}
else{
break;
}
}
while(1){
printf("请问是否需要打印书籍信息(Y/N):");
do{
ch = getchar();
}while (ch != 'Y' && ch != 'N');
if (ch == 'Y'){
printLibrary(library);
}
releaseLibrary(&library);
}
return 0;
}
观察打印顺序
//尾插法
#include <stdlib.h>
//建立节点
struct Book{
char title[128];
char author[40];
struct Book *next;
};
void getInput(struct Book *book){
printf("请输入书名:");
scanf("%s", book->title);
printf("请输入作者:");
scanf("%s", book->author);
}
//在单链表中插入元素
//形参字面上的意思:(*library)是头节点指针library进行一层解引用,然后对其指向的内容(地址)再进行一次解引用
void addBook(struct Book **library) {
struct Book *book, *temp;
//新建一个新的节点
book = (struct Book *)malloc(sizeof(struct Book));
if (book == NULL){
printf("内存分配失败了\n");
exit(1);
}
//填充内容
getInput(book);
if (*library != NULL){
temp = *library;
//定位单链表的尾部位置
while (temp->next != NULL){
temp = temp->next;
}
//插入数据
temp->next = book;
book->next = NULL;
}
else{
*library = book;
book->next = NULL;
}
}
void printLibrary(struct Book *library){
struct Book *book;
int count = 1;
book = library;
while (book != NULL){
printf("Book%d:", count);
printf("书名:%s:", book->title);
printf("作者:%s:", book_>author);
book = book->next;
count++;
}
}
void releaseLibrary(struct Book **library){
struct book *temp;
while (*library != NULL){
temp = *library;
*library = (*library) -> next;
free(temp);
}
}
int main(void){
//library作为头节点指针进行解引用,得到其存放的值,即下一个节点的地址指针
struct Book *library = NULL;
while(1){
printf("请问是否需要录入书籍信息(Y/N):");
do{
ch = getchar();
}while (ch != 'Y' && ch != 'N');
if (ch == 'Y'){
addBook(&library);
}
else{
break;
}
}
while(1){
printf("请问是否需要打印书籍信息(Y/N):");
do{
ch = getchar();
}while (ch != 'Y' && ch != 'N');
if (ch == 'Y'){
printLibrary(library);
}
releaseLibrary(&library);
}
return 0;
}
上述尾插法每次插入新元素都需要遍历一次链表,耗时多,是否可以记录下尾节点的地址呢
void addBook(struct Book **library){
struct Book *book;
//为防止每次进入函数,tail都会被初始化,我们将其变成静态变量:直到程序退出才释放,不然永久保存上一次的值
static struct Book *tail;
book = (struct Book *)malloc(sizeof(struct Book));
if (book == NULL){
</