开发者学堂课程【你的第一门 C 语言课:单链表】学习笔记,与课程紧密联系,让用户快速学习知识
课程地址:https://developer.aliyun.com/learning/course/444/detail/5494
单链表
目录:
一、结构体书写
二、链表定义
三、单链表
一、结构体书写
结构体是允许嵌套的,即结构体的成员可以为另外一个结构体。故将结构体书写成如下模式,则其为错误结构体。
struct Test
{
int x;
int y;
struct Test test ;
};
当如此书写代码时,将会被编译期进行报错提示。
例:
include
int main(void)
{
struct Test
{
int
x;
int
y;
struct Test test;
//包含结构体自身
}
return 0 ;
}
fishc@bogon s1e45]$ vi test1.c
[fishc@bogon sle45]$ gcc testl.c
test1.c: In function 'main':
test1.c:9: error: field 'test' has incomplete type
[fishc@bogon s1e45 ]$
//即出现错误
由于上述的书写将会造成代码的无限循环。
此为 test 结构体成员,需要自身,但自身并不完整导致陷入有去无回的递归。
更改:
int main(void)
{
struct Test
{
int x;
int y;
struct Test
*
test;
//更改为4个字节的第三方指针变量,即特殊地指向 test 结构体自身。
}
return 0 ;
}
[
fishc@bogon s1e45]$ vi test1.c
[fishc@bogon sle45]$ gcc testl.c
test1.c: In function 'main':
test1.c:9: error: field 'test' has incomplete type
[
fishc@bogon s1e45]$ vi test1.c
[fishc@bogon sle45]$ gcc testl.c
[fishc@bogon sle45]$ gcc testl.c
//此时运行正常
二、链表定义
需要一个指向自身的结构,即为链表。
链表是一种常见的基础数据结构。根据需求,可构造出单链表、双链表、循环链表和块状链表等。链表的出现很大程度上弥补了数组的先天不足。
三、单链表
包含信息域、指针域,信息域存放链表节点的内容,而指针域指向下一个完全相同的节点。两者因指针而串联到一起。直到最后指针域指向的节点为 null,则此单链表就此结束。其中,需要一个头指针指向最初节点。
链表的各个元素在链表中并非紧密相连,而是通过指针连接。
此种存储方式使得链表和数组形成了鲜明对比。
1.单链表节点的声明
将 book 结构改写为链表节点,只需要对其添加一个指向自身的成员。
include
struct Book
{
char title[128];
//信息域
char author[40];
struct Book *next ;
};
int main(void )
{
return0;
}
2.在单链表中插入文字
头插法
(1)定义:
首先申请新的内存空间以存放节点,填充其信息域:书名、作者等
将 Head 指针原本的指向擦除,并使其指向新节点,将 Head 指针存放的地址-即第一个元素的地址指向新节点。即将信息域插入了单链表的首部。
(2)示例
include
include
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
)
;
}
void addBook(struct Book **library)
//此处的两层指针是由于指针自身的值,即 head 指针的值需要进行修改,将指针的地址传输进去。
head 指针是指向 book 结构体的指针,故其需要指向 book 结构体指针的指针。
{
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;
//当旧信息域中含有数据时,将信息与本身存放地址的值以一个临时值存放起来,使 head 能够指向新信息域
}
}
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(strct Book *Library)
{
while (Library != NULL)
{
free(Library);
addBook(&library);
return0;
}
}
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')
}
else
{
break;
}
}
printf“请问是否需要打印图书信息
录入信息
?(Y/N)”
do
{
ch = getchar();
}while (ch != 'y' && ch != 'N'};
if (ch == 'y')
{
printLiobrary
(library);
}
release(Library);
return0;
{
break;
}
}
addBook(&library)
return0;
}
请问是否需要打印图书信息录入信息(Y/N):Y
请输入书名:《零基础入门Python》
请输入作者:小甲鱼
请问是否需要录入书籍信息(Y/N):Y
请输入书名:《带你学C带你飞》
请输入作者:小甲鱼
请问是否需要打印录入书籍信息(Y/N):Y
Book1:书名:《带你学C带你飞》 作者:小甲鱼 Book2:书名:《零基础入门Python》 作者:小甲鱼[fishc@bogon s1e45]s