双向链表结点
单链表的链式储存只有一个指示后继的指针域,所以,从某个结点出发只能顺指针往后寻查其他结点。若要寻查结点的直接前端,则需要从表头指针出发。
为了克服单链表的单向性缺点,在双向链表的结点中有两个指针域,一个指向直接后继,一个指向直接前趋。
typedef struct double_list
{
int val; //结点的值
struct double_list* next; //后继结点的指针域
struct double_list* pre;//前趋结点的指针域
}double_list;

双向链表初始化
首先malloc一个结点的空间,刚刚初始化的头节点,其前指针与后指针都赋值为空。
void inite(double_list** head)
{
*head = (double_list*)malloc(sizeof(double_list));
(*head)->next = NULL;
(*head)->pre = NULL;
}
这里有一个坑,为什么参数是二级指针?
因为结点中还有前后的指针域,所以如果传递一级指针,则出了函数作用域,前后指针还是会返回默认的随机地址。
双向链表的插入
当新结点插入到链表当中时,与单链表操作相同,只不过多了一个前趋指针的指向,先将新结点的后指针指向后一个结点,前指针指向前一个结点,再将后结点的前指针指向新结点,前结点的后指针指向新结点,即可完成插入

头插法
头插法就是每当有新结点生成时,始终插入到头节点后,头插的实现相对简单,但是头插的顺序与链表的输出顺序是相反的。

void push_front(double_list* head,int val)
{
double_list* node = (double_list*)malloc(sizeof(double_list));
node->val = val;
head->next->pre = node;
node->next = head->next;
head->next = node;
node->pre = head;
}
尾插法
尾插法也就是先将指针遍历到链表尾部,再从尾部插入新结点

void push_back(double_list* head, int val)
{
double_list* phead = head;
double_list* node = (double_list*)malloc(sizeof(double_list));
while (phead->next!= NULL)
{
phead = phead->next;
}
node->val = val;
phead->next = node;
node->next = NULL;
node->pre = phead;
}
链表中删除结点
结点的删除相对简单,只需要将要删除的结点,前一个结点的后指针指向后一个结点,后一个结点的前指针指向前一个结点,再释放掉该结点的内存即可。

void erase(double_list* node)
{
node->next->pre = node->pre;
node->pre->next = node->next;
free(node);
node = NULL;
}
头删
头删也就是每次都从头节点的下一个结点删除,每次删除的都是链表中的第一个结点。
void pop_front(double_list* head)
{
double_list* temp = head->next;
head->next->next->pre = head;
head->next = head->next->next;
free(temp);
temp = NULL;
}
尾删
尾删也就是每次都遍历到链表结尾出,每次删除链表的最后一个结点。
void pop_back(double_list* head)
{
double_list* phead = head;
while (phead->next != NULL)
{
phead = phead->next;
}
phead->pre->next = NULL;
free(phead);
phead = NULL;
}
查找元素
double_list* find(double_list* head, int val)
{
double_list* phead = head;
while (phead != NULL)
{
if (phead->val == val)
return phead;
phead = phead->next;
}
return NULL;
}
遍历整个链表,当找到与值相同的结点时,返回该结点
打印链表
void print_list(double_list* head)
{
double_list* phead = head->next;
while (phead->next != NULL)
{
printf("%d->", phead->val);
phead = phead->next;
}
printf("%d", phead->val);
}
本文介绍了双向链表的数据结构,包括结点定义、初始化、插入(头插法与尾插法)、删除(头删与尾删)、查找元素及打印链表等基本操作。双向链表相对于单链表的优势在于可以从前后两个方向进行查找和操作。
1203

被折叠的 条评论
为什么被折叠?



