实现功能:
- 双循环链表的创建
- 双循环链表的插入(头插法、尾插法)
- 双循环链表的删除
- 双循环链表的遍历
代码实现:
//双循环链表
#include <stdio.h>
#include <stdlib.h>
//定义链表节点的结构体
typedef struct node_st
{
int data; //数据域
struct node_st *prev; //前驱指针
struct node_st *next; //后继指针
}list;
/*函数声明部分*/
list *list_create(); //链表的创建
void list_insert_h(list *head,int data);//头插法
void list_insert_t(list *head,int data);//尾插法
int list_delete(list *head,int data); //链表的删除
void list_print(list *head); //链表的遍历
int main()
{
int i = 0;
list *head = list_create();
for(i=0;i<3;i++)
{
list_insert_h(head,i);
}
list_insert_t(head,3);
list_insert_t(head,4);
list_print(head);
for(i=0;i<5;i++)
{
list_delete(head,i);
}
list_print(head);
return 0;
}
/*函数实现部分*/
//链表的创建
list *list_create()
{
list *head = malloc(sizeof(*head));//头节点
head->data = 0;//记录有效节点个数
head->prev = head; //循环链表
head->next = head;
return head; //返回头指针
}
//链表的插入-头插法
void list_insert_h(list *head,int data)
{
list *new = malloc(sizeof(*new));//待插入的新节点
new->data = data; //新节点的数据
//1).链表为空
if(head->data == 0)
{
new->prev = head;//1.新节点的前驱指针指向头节点
new->next = head;//2.新节点的后继指针指向头节点
head->prev = new;//3.头节点的前驱指针指向新节点
head->next = new;//4.头节点的后继指针指向新节点
}
//2).链表不为空
else
{
new->prev = head;//1.新节点的前驱指针指向头节点
new->next = head->next;//2.新节点的后继指针指向第1个有效节点
head->next = new;//3.头节点的后继指针指向新节点
head->next->prev = new;//4.第1个有效节点的前驱指针指向新节点
}
head->data++; //有效节点数+1
}
//尾插法
void list_insert_t(list *head,int data)
{
list *new = malloc(sizeof(*new));
list *tail = head;
new->data = data; //新节点数据
while(tail->next != head)
{
tail = tail->next;
}
new->prev = tail;//1.新节点的前驱指针指向尾节点
new->next = head;//2.新节点的后继指针指向头节点
head->prev = new;//3.头节点的前驱指针指向新节点
tail->next = new;//4.尾节点的后继指针指向新节点
head->data++; //有效节点数+1
}
//链表的删除
int list_delete(list *head,int data)
{
list *node = head->next;
while(node != head)
{
if(node->data == data)
{
//待删节点的前1节点的后继指针指向待删节点的后1节点
node->prev->next = node->next;
//待删节点的后1节点的前驱指针指向待删节点的前1节点
node->next->prev = node->prev;
free(node); //释放内存
head->data--; //有效节点数-1
return 1;
}
//继续往下找
node = node->next;
}
return 0;//删除失败
}
//链表的遍历
void list_print(list *head)
{
list *node = head->next; //第1个有效节点
while(node != head)
{
printf("%d->",node->data);
node = node->next;
}
printf("NULL\n");
}
运行结果:
代码分析:
- 头插法
1). 链表为空时
new->prev = head;//1.新节点的前驱指针指向头节点
new->next = head;//2.新节点的后继指针指向头节点
head->prev = new;//3.头节点的前驱指针指向新节点
head->next = new;//4.头节点的后继指针指向新节点
2). 链表不为空时
new->prev = head; //1.新节点的前驱指针指向头节点
new->next = head->next;//2.新节点的后继指针指向第1个有效节点
head->next = new; //3.头节点的后继指针指向新节点
head->next->prev = new; //4.第1个有效节点的前驱指针指向新节点
- 尾插法
new->prev = tail;//1.新节点的前驱指针指向尾节点
new->next = head;//2.新节点的后继指针指向头节点
head->prev = new;//3.头节点的前驱指针指向新节点
tail->next = new;//4.尾节点的后继指针指向新节点
- 链表的删除
(待删节点是否为尾节点的情况一样)
//待删节点的前1节点的后继指针指向待删节点的后1节点
node->prev->next = node->next;
//待删节点的后1节点的前驱指针指向待删节点的前1节点
node->next->prev = node->prev;