双链表的介绍
看到这里,我相信你们都已经对单向链表有一定的了解,与数组相比较,链表在处理插入和删除的时候非常好用,缺点是消耗的空间较大,而且还不能通过下标进行访问。
链表有单向和双向,单向查询困难,要找到某个元素需要将这个元素之前的位置都遍历一遍。除此之外,单向的链表想要访问上一级特别困难。在此基础上,出现了双链表。
这就是双链表,双链表的头节点prev可以为NULL,也可以与链表末端链接形成双向循环链表。
双链表的创建
首先要创建一个头节点,并且让这个头节点的prev为NULL(初始化)。假使我们要创建n个节点,那么我们需要创建(尾节点)end,和中间节点node。循环n-1遍,每次使用node接收malloc分配空间后的地址,再将end->next指向node,node->prev指向end。最后循环出来不要忘记将end->next=NULL,要不它的指向是未知的,也就是我们说的野指针,这会引起程序的崩溃。
List* ListCreat(int n)
{
if (n <= 0)
{
printf("错误!\n");
return;
}
List* head = (List*)malloc(sizeof(List)), * end = head;
head->prev = NULL;
List* node = NULL;
int i = 0;
printf("请输入值\n");
scanf("%d", &head->data);
for (i = 1; i < n; i++)
{
node = (List*)malloc(sizeof(List));
scanf("%d", &node->data);
end->next = node;
node->prev = end;
end = node;
}
end->next = NULL;
return head;
}
双链表的长度
在创建完双链表之后,我们想知道它的长度,可以创建整形变量count,这需要将链表的位置传进来,可以想到,每次链表走一步,count自加1,直至链表走到NULL。
int ListLen(List* list)
{
int count = 0;
while (list)
{
count++;
list = list->next;
}
return count;
}
双链表的插入
对于双链表的插入,其实与单链表相差无几,只不过多了俩个需要处理的指针,在插入的时候,需要考虑头插和尾插的情况,
List* ListInsert(List* list, int n)
{
if (n < 0)
return;
List* node = list;
for (int i = 0; i < n&&node->next; i++)//当超出链表长度时,当成尾插处理
{
node = node->next;
}
List* new = (List*)malloc(sizeof(List));
printf("请输入要插入的值\n");
scanf("%d", &new->data);
if (!node->prev)//头插
{
new->next = list;
list->prev = node;
node->prev = NULL;
return new;
}
if (!node->next)//尾插
{
node->next = new;
new->prev = node;
new->next = NULL;
}
else
{
node->prev->next = new;
new->prev = node->prev;
node->prev = new;
new->next = node;
}
return list;
}
双链表的删除
删除双链表的某个元素时,需要处理俩个指针,即要删除节点的上一节点的next,和要删除的下一节点的prev,这里也要考虑到头删和尾删。
(这里博主对于链表的访问类似数组,从零开始)。
List* ListDel(List* list, int n)
{
List* node = list;
if (n < 0)
{
printf("错误!\n");
}
for (int i = 0; i < n&&node->next; i++)//当超出链表长度当成尾删处理
{
node = node->next;
}
if (!node->next)//尾删
{
node->prev->next = NULL;
free(node);
}
else if (!node->prev)//头删
{
list = list->next;
list->prev = NULL;
free(node);
}
else
{
node->prev->next = node->next;
node->next->prev = node->prev;
free(node);
}
return list;
}
到了这里,双链表的基本操作已经完成,剩下的销毁和打印可以自己去实现下。