链表=信息域+指针域
链表中的信息域通过指针连接在一起
head null
信息域存放链表中某个结点的内容,这里的结点相当于数组里的元素
指针域用来指向下一个跟它一模一样的结点
结点之间用指针串联
直到最后一个结点的指针域指向null结束
链表中各个元素不是紧密相连的,它们之间通过指针相连
所以对于之前的book结构来说,要把它变成链表中的一个结点,需要为它添加一个指向自身的成员
-------------------------------------------------------------------------------------------------------------------------
插入元素
首先在堆里申请一个新的内存空间,用来存放这个新的结点,然后填充这个新结点的信息域,然后把head指针原来的指向擦除,然后指向新结点,新结点的指针域指向原来head指向的那个信息域 头插法
-------------------------------------------------------------------------------------------------------------------------
书籍插入单链表的代码解释
声明一个addBook函数,因为该函数需要一个参数,所以在main函数里申请一个struct Book *library(这里实际指的就是头指针head)=null,刚开始指向null,说明这是一个空的单链表,通过调用addBook把新的结点插入,要插入新的结点,就需要修改head的值,因为head存放的是它原来所指向的那个信息域的地址,所以需要把head里存的内容改成将要添加的那个结点的信息域的地址,让新插入的那个结点的指针域指向head原来指向的那个信息域-------------------------------------------------------------------------------------------------------------------------
代码部分
修改library部分,对它进行两层解引用。此时addBook函数的参数是一个指向book结构的指针的指针 主函数里调用addBook函数,里面的参数应该是&library,不能是library,因为如果是library的话,此时传入的是原来head指向的那个信息域,但是我们要修改的是head,所以应该给head的地址,修改head的值 重新看addBook函数,动态的在内存里调用malloc函数来申请一个book结构sizeof(struct Book),因为返回的是void函数类型,所以把它强制转化为book的结构体类型 (struct Book*) 强制转化
内存分配完以后要填充信息域,即让用户输入信息。这个用自定义的getInput函数实现,函数传递的参数就是book的地址
传给这个函数的是一个book结构的指针,直接传个指针,然后通过指针修改结合体的内容就可以了 输入书名时,因为传过来的是指针,所以直接用箭头的这个操作符指向title
再返回去看addBook函数,接下来有两种情况,就是要么library传过来的head是一个空的单链表即,library这个指针指向null,此时就把library这个指针指向新生成的这个book结点,把book->next指向null;反之,先把head原来存储的地址的值用一个临时变量tmp存放起来,然后让head指向新的结点的信息域,再把tmp的值给这个新结点的指针域
两个星号的原因:我们要修改的这个head存放的内容的值,即library指针自身的值,所以我们需要把指针的地址传进去,而这个指针是一个指向book结构体的指针,把指针的地址传进去,所以需要一个指向book结构体指针的指针
-------------------------------------------------------------------------------------------------------------------------
如何打印单链表里的成员
声明一个printLibrary函数 book=book->next的意思是指向下一个结点
最后记得用releaseLibrary函数释放掉malloc申请的空间
看向主函数 提高用户体验 (while循环内即下面的东西)
-------------------------------------------------------------------------------------------------------------------------
头插法 比较慢录入的内容在前面 ,尾插法在单链表的后面
-------------------------------------------------------------------------------------------------------------------------
在写释放单链表的代码时犯的错误
先调用free函数将library指向的内存空间释放掉,然后将library指向下一个结点,这里存在一个问题,把library的空间释放掉以后,就无法过去这个空间的next成员了,所以理论上library=library->next这个语句是没有意义的。之前的错误代码:
修改方法:
增加一个临时变量,在释放之前把这个结点的地址先保存下来。 声明部分也进行了修改
releaseLibrary函数调用时也改为library的地址
->的优先级比*高
#include#include struct Book { char title[128];//信息域 char author[40];//信息域 struct Book *next;//指针域 };//完成了单链表结点的声明 void getInput(struct Book *book); void addBook(struct Book **library); void printLibrary(struct Book *library); void releaseLibrary(struct Book **library) ; void getInput(struct Book *book) { printf("请输入书名:"); scanf("%s", book->title); printf("请输入作者"); scanf("%s", book->author); } void addBook(struct Book **library) { struct Book *book, *temp; book = (struct Book *)malloc(sizeof(struct Book)); if (book == NULL) { printf("内存分配失败n");//通常不会 exit(1);//用于强制退出,需要头文件stdlib.h } 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) { struct Book *library = NULL; int ch; while (1) { printf("请问是否需要录入书籍信息(Y/N):"); do { ch = getchar(); } while (ch != 'Y' && ch != 'N'); if (ch == 'Y') { addBook(&library); } else { break; } } printf("请问是否需要打印图书信息(Y/N):"); do { ch = getchar(); } while (ch != 'Y' && ch != 'N'); if (ch == 'Y') { printLibrary(library); } releaseLibrary(&library); return 0; }
如果出现问题,欢迎批评指正啊



