双向链表
一、什么是双向链表
双向链表又称双链表,是链表的一种,和单链表一样,也是把多个结构体节点用结构体指针连接起来,只不过单链表只有一个指向下一个节点的结构体指针,而双链表有两个结构体指针分别指向上一个节点和下一个节点。
二、双向链表的特点
1、双链表和单链表一样,没有固定的长度,可以自由增加节点
2、双链表有两个指针域,一个用于指向前一个节点,另一个用于指向下一个节点
3、由于有指向前一个节点的指针域,双链表可以很好的支持逆序输出
三、双向链表和单向链表的区别
单链表只有一个指针域,用于指向下一个节点的首地址,而双链表有两个指针域,可以分别指向前一个节点和下一个节点,链表的遍历更加方便
四、双链表的结构示意图
五、双链表的设计与功能实现
1、创建双链表节点
2、链接双链表节点
3、双链表的打印输出
4、双链表节点的删除
5、双链表的销毁
6、双链表的连接
定义一个结构体,存放数据和指针
struct Node
{
int x;
int y;
Node* prev; //定义一个结构体指针, 保存该节点上一个节点在内存中的地址
Node* next; //定义一个结构体指针, 保存该节点下一个节点在内存中的地址
};
创建链表结构体
struct Linklist
{
Node* head; //保存头节点的地址
Node* tail; //保存尾接点地址
int size; //保存节点个数
};
创建链表中存放数据的节点
Node* createNode(int x, int y)
{
Node*temp= (Node*)malloc(sizeof(Node));//申请一个节点的内存 , 并且指向这段内存
temp->x = x;
temp->y = y;
temp->next = NULL;
temp->prev = NULL;
return temp;
}
定义一个函数,传入两个节点
void node_link(Node* n1, Node* n2)
{
n1->next = n2;
n2->prev = n1;
}
初始化双链表
void Linklist_init(Linklist*list)
{
list->head = NULL; //头尾指针置空,大小为0
list->tail = NULL;
list->size = 0;
}
头插法
void push_head(Linklist* list, int x, int y)
{
if (list->head == NULL)
{
//创建节点,因为是第一个节点,所以头节点等于尾接点
list->head = createNode(x,y);
list->tail = list->head;
list->size = 1; //有一个节点
}
else
{
Node* temp = createNode(x, y); //定义临时指针变量接收新节点的地址
node_link(temp, list->head); //头插
list->head = temp;
list->size++;
}
}
尾插法
void push_tail(Linklist* list, int x, int y)
{
if (list->head == NULL)
{
list->head = createNode(x, y);
list->tail = list->head;
list->size = 1;
}
else
{
Node* temp = createNode(x, y);
node_link(list->tail, temp);
list->tail = temp;
list->size++;
}
}
顺序输出
void printhead_list(Linklist*p)
{
if (p->head == NULL)
{
printf("该双链表为空!");
return;
}
else
{
Node* temp = p->head;
printf("头输出为:\n");
//定义一个临时指针指向链表头节点
while (temp!= NULL)
{
printf("x=%d y=%d\n", temp->x, temp->y);
temp = temp->next;
}
}
}
逆序输出
void printend_list(Linklist* p)
{
if (p->head == NULL)
{
printf("该双链表为空!");
return;
}
else
{
printf("尾输出为:\n");
Node* temp = p->tail;
while (temp != NULL)
{
printf("x=%d y=%d\n", temp->x, temp->y);
temp = temp->prev;
}
}
}
删除符合条件的节点
void deleteNode(Linklist*p, int x)
{
assert(list);//断言 , 判断list是否为空 ,如果为空, 程序结束
if (p== NULL)
return;
Node* temp = p->head;
while (p != NULL)
{
if (temp->x == x)
{
Node* tt = temp;
node_link(tt->prev, tt->next);
temp = temp->next;
free(tt);
}
else
temp = temp->next;
}
}
删除指定节点
void deletelink(Linklist* p)
{
if (p != NULL)
{
Node* temp = p->head;
while (temp != NULL)
{
Node* tt = temp;
temp = temp->next;
free(tt);
}
Linklist_init(p);
}
}
删除头节点
void deletelisthead(Linklist* list, Node* node)
{
assert(list->head);//判断链表是否为空
if (node == list->head)//如果删除的是头节点
{
Node* temp = list->head;
list->head = list->head->next;
if (list->head == NULL)
list->tail = NULL;
else
list->head->prev = NULL;
free(temp);
}
else if (node == list->tail)
{
Node* temp = list->tail;
list->tail = list->tail->prev;
if (list->tail == NULL)
{
list->head == NULL;
}
else
list->tail->next = NULL;
free(temp);
}
else
{
node_link(node->prev, node->next);
free(node);
}
list->size--;
}
销毁链表
void destory(Linklist* list)
{
for (Node* temp = list->head; temp != NULL;)
{
Node* tt = temp;
temp = temp->next;
free(tt);
}
Linklist_init(list);
}
链表节点数
void Looklistsize(Linklist* list)
{
printf("双链表的大小为%d\n", list->size);
}
连接两个双链表
Linklist* linklists(Linklist* list1, Linklist* list2)
{
Linklist *list3= (Linklist*)malloc(sizeof(Linklist));
Linklist_init(list3);
Node* temp = list1->tail;
Node* tt = list2->head;
node_link(temp, tt);
list3->head = list1->head;
list3->tail = list2->tail;
list3->size = list1->size + list2->size;
return list3;
}
测试
int main()
{
Linklist* list1 = (Linklist*)malloc(sizeof(Linklist));
Linklist_init(list1);
Linklist* list2 = (Linklist*)malloc(sizeof(Linklist));
Linklist_init(list2);
Linklist* list3 = (Linklist*)malloc(sizeof(Linklist));
Linklist_init(list3);
for (int i = 0; i < 10; i++)
{
push_head(list1, i * 1, i * 1);
//push_head(list2, i * 2, i * 2);
}
for (int i = 0; i < 10; i++)
{
//push_head(list1, i * 1, i * 1);
push_head(list2, i * 2, i * 2);
}
list3 = linklists(list1, list2);
//deleteNode(list, 2);
//printend_list(list);
//printhead_list(list);
//destory(list);
//for (Node*temp=list->head;temp!=NULL;temp=temp->next)
//{
// Node* tt = temp;
// if (temp->x == 3 || temp->y == 5)
// {
// deletelisthead(list,tt);
// }
//}
printf("list1和list2双链表连接成功后的数据为:\n");
printend_list(list3);
Looklistsize(list3);
system("pause");
return 0;
}