实现功能:
- 双链表的创建
- 双链表的插入(头插法、尾插法)
- 双链表的删除
- 双链表的遍历
代码实现:
//双链表
#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;
list *head = list_create();
list_insert_h(head,1);//头部插入
list_insert_h(head,2);
list_insert_h(head,3);
list_insert_t(head,4);//尾部插入
list_insert_t(head,5);
list_print(head);
for(i=1;i<6;i++) //循环删除所有有效节点
{
list_delete(head,i);
}
list_print(head);
return 0;
}
list *list_create()
{
list *head = malloc(sizeof(*head));
head->data = 0; //存放有效节点个数
head->prev = NULL;
head->next = NULL;
return head; //返回头指针
}
//头插法
void list_insert_h(list *head,int data)
{
list *new = malloc(sizeof(*new));//为新节点申请内存空间
new->data = data; //插入的数据
//1).链表不为空时
if(head->next!=NULL)
{
new->prev = head; //1.新节点的前驱指针指向头节点
new->next = head->next;//2.新节点的后继指针指向第1个有效节点
head->next = new; //3.头节点的后继指针指向新节点
head->next->prev = new;//4.第1个有效节点的前驱指针指向新节点
}
//2).链表为空时
else
{
new->prev = head; //1.新节点的前驱指针指向头节点
new->next = head->next;//2.新节点的后继指针指向NULL
head->next = new; //3.头节点的后继指针指向新节点
}
head->data++;//有效节点数+1
}
//尾插法
void list_insert_t(list *head,int data)
{
list *tail = head; //尾节点
list *new = malloc(sizeof(*new));//新节点
new->data = data; //新节点的数据
int i = 0;
//while(tail->next!=NULL)
for(i=0;i<head->data;i++)
{
tail = tail->next;
}
new->prev = tail; //1.新节点的前驱指针指向尾节点
new->next = tail->next;//2.新节点的后继指针指向NULL
tail->next = new; //3.尾节点的后继指针指向新节点
head->data++; //有效节点个数+1
}
int list_delete(list *head,int data)
{
list *node = head->next;
while(node) //节点不为空
{
if(node->data==data)
{
//1).待删节点不是尾节点时
if(node->next)
{
//1.待删节点的前1节点的后继指针指向待删节点的后1节点
node->prev->next = node->next;
//2.待删节点的后1节点的前驱指针指向待删节点的前1节点
node->next->prev = node->prev;
}
//2).待删节点为尾节点时
else
{
//1.待删节点的前1节点的后继指针指向NULL
node->prev->next = node->next;
}
free(node);
head->data--; //有效节点数-1
return 1;
}
//继续往下找
node = node->next;
}
return 0;
}
void list_print(list *head)
{
list *node = head->next;//第1个有效节点
while(node)
{
printf("%d->",node->data);
node = node->next;
}
printf("NULL\n");
}
运行结果:
代码分析:
5. 头插法
1). 链表不为空时
new->prev = head; //1.新节点的前驱指针指向头节点
new->next = head->next;//2.新节点的后继指针指向第1个有效节点
head->next = new; //3.头节点的后继指针指向新节点
head->next->prev = new;//4.第1个有效节点的前驱指针指向新节点
2). 链表为空时
new->prev = head; //1.新节点的前驱指针指向头节点
new->next = head->next;//2.新节点的后继指针指向NULL
head->next = new; //3.头节点的后继指针指向新节点
- 尾插法
new->prev = tail; //1. 新节点的前驱指针指向尾节点
new->next = tail->next;//2.新节点的后继指针指向NULL
tail->next = new; //3.尾节点的后继指针指向新节点
- 链表的删除
1). 待删节点不是尾节点时
//1.待删节点的前1个节点的后继指针指向待删除节点的后1个节点
node->prev->next = node->next;
//2.待删节点的后1个节点的前驱指针指向待删节点的前1个节点
node->next->prev = node->prev;
2). 待删节点为尾节点时:
//1. 待删节点的前1节点的后继指针指向NULL
node->prev->next = node->next;