目录
1.链表的概念及结构
物理结构图:
2 链表的分类
实际中链表的结构非常多样,一下情况组合起来就有8种链表结构:
2.1 单向或者双向
2.2带头或者不带头
2.3 循环或者非循环
虽然有这么多的链表的结构,但是我们实际中最常用还是两种结构:
注:
1. 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结 构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。
2. 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向 循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而 简单了。
3 单链表的实现
部分代码示例:
// 无头单向
typedef int Sltdatatype;
typedef struct Slistnode
{
Sltdatatype data;
struct Slistnode* next;
}Sltnode;
// 构造新节点函数
Sltnode* Buylistnode(Sltdatatype x)
{
Sltnode* newnode = (Sltnode*)malloc(sizeof(Sltnode));
if (newnode == NULL)
{
printf("malloc fail\n");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
return newnode;
}
// 打印函数
void Slistprint(Sltnode** phead)
{
Sltnode* cur = *phead;
while (cur != NULL)
{
printf("%d->", cur->data);
cur = cur->next;
}
}
//头插数据
void Slistpushfront(Sltnode** pphead, Sltdatatype x)
{
Sltnode* newnode = Buylistnode(x);
newnode->next = *pphead;
*pphead = newnode;
}
// 尾插数据
void Slistpushback(Sltnode** pphead, Sltdatatype x)
{
// 新节点
Sltnode* newnode = (Sltnode*)malloc(sizeof(Sltnode));
newnode->data = x;
newnode->next = NULL;
if (*pphead == NULL)
{
*pphead = newnode;
}
// 找尾节点
Sltnode* tail = *pphead;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newnode;
}
// 尾删除数据
void SlistPopback(Sltnode** pphead)
{
// 温柔的方法
if (*pphead = NULL)
{
return;
}
// 粗暴的方法
// assert(*pphead != NULL);
// 一个节点或则 两个及以上节点
if ((*pphead)->next == NULL)
{
free(*pphead);
*pphead = NULL;
}
else
{
Sltnode* tail = *pphead;
Sltnode* prev = NULL;
//while (tail->next != NULL)
while (tail->next)
{
prev = tail;
tail = tail->next;
}
free(tail);
tail->next = NULL;
prev->next = NULL;
}
}
注:在写代码中要特别注意,函数传参,形参是实参的拷贝,形参的改变不会影响实参。如果传入的是一级指针,形参phead的改变不会影响实参,所以这里采用了二级指针。
最后,这是我在学习C语言数据结构之单链表时的笔记。如果有不正确的地方,或者遗漏的重点希望大家指正。大家一起加油!