什么是链表
链表:由分布在内存不同位置的结点(元素),通过成员指针所连接起来的表结构,结点间存在一对一关系。
链表的优缺点
优点:
对内存要求不高,可以使用小块内存。
插入、删除方便。
可以根据元素数量动态调整链表的长度,节约内存,还可以无限的添加数据。
缺点:
频繁的释放和创建结点可能会产生内存碎片。
访问速度慢,不能随机访问,只能从头结点逐个遍历。
单链表
首先是单链表节点定义:
typedef struct Node
{
int data;
struct Node* next;
}Node;
单链表插入结点
//头插入
void add_head_list(Node* head, TYPE data)
{
Node* node = create_node(data);
//更改node指向链表第一个结点
node->next = head->next;
//更新头结点指向
head->next = node;
}
//尾插入
void add_tail_list(Node* head, TYPE data)
{
while(NULL != head)
head = head->next;
head = create_node(data);
}
//结点p后插入
void add_list(Node* p, TYPE data)
{
Node* node = create_node(data);
Node* q = p->next;
p->next = node;
node->next = q;
}
单链表删除结点
//头删除
bool del_head_list(Node* head)
{
if(NULL==head->next)
return false;
Node* tmp = head->next;
head->next = tmp->next;
free(tmp);
return true;
}
//尾删除
bool del_tail_list(Node* head)
{
//循环到倒数第二个结点
while(NULL!=head->next->next)
head = head->next;
return del_head_list(head);
}
//删除结点p的后一个结点
bool del_list(Node* p)
{
Node* q = p->next;
p->next = q->next;
free(q);
}
双向循环链表
//定义结点
typedef struct Node
{
int data;
//有两个指针域,分别代表前驱和后继
struct Node* next;
struct Node* prev;
}Node;
添加结点
//在prev和next两个结点间插入一个节点
void _add_node(Node* next, Node* prev, TYPE data)
{
Node* node = create_node(data);
//你指哪儿我指哪儿
node->next = prev->next;
node->prev = next->prev;
prev->next = node;
next->prev = node;
}
//头添加
void add_head_list(Node* head, TYPE data)
{
//在头结点和第一个结点之间添加结点
Node* prev = head;
Node* next = head->next;
_add_node(next, prev, data);
}
//尾添加
void add_tail_list(Node* head, TYPE data)
{
//在尾结点和头结点之间添加结点
Node* prev = head->prev;
Node* next = head;
_add_node(next, prev, data);
}
删除节点
void _del_node(Node* node)
{
node->prev->next = node->next;
node->next->prev = node->prev;
free(node);
}
//头删除
bool del_head_list(Node* head)
{
//只有头结点
if(head->next == head)
return false;
_del_node(head->next);
return true;
}
//尾删除
bool del_tail_list(Node* head)
{
if(head->next == head)
return false;
_del_node(head->prev);
return true;
}