双向循环链表的使用
- 1.双向循环链表节点设计
- 2.初始化双向循环链表-->定义结构体变量 创建头节点
- (1)示例代码:
- (2)图示
- 3.双向循环链表节点头插
- (1)示例代码:
- (2)图示
- 4.双向循环链表节点尾插
- (1)示例代码:
- (2)图示
- 5.双向循环链表节点中间插入
- (1)示例代码:
- (2)图示
- 6.双向循环链表删除节点
- (1)示例代码:
- (2)图示
- 7.双向循环链表修改节点数据
- (1)示例代码:
- 8.双向循环链表遍历
- 9.完整示例代码
1.双向循环链表节点设计
typedef struct double_list{int data;struct double_list *next;struct double_list *prev;
}double_list_t;
2.初始化双向循环链表–>定义结构体变量 创建头节点
(1)示例代码:
double_list_t *double_list_init()
{double_list_t *head_node = malloc(sizeof(double_list_t));if (head_node != NULL){head_node->next = head_node;head_node->prev = head_node;}else{printf("[double_list_init]申请头节点失败\n");}return head_node;
}
(2)图示
3.双向循环链表节点头插
(1)示例代码:
int insert_list_head(int newdata, double_list_t *list)
{// 申请一个节点 -堆空间double_list_t *new_node = malloc(sizeof(double_list_t));if (new_node == NULL) {printf("[insert_list_head]申请新的节点失败\n");return -1; // 申请内存失败}// 初始化数据域new_node->data = newdata;new_node->next = NULL;new_node->prev = NULL;// 当链表为空时if (list->next == list){list->next = new_node;new_node->next = list;new_node->prev = list;list->prev = new_node;// printf("[insert_list_head]当链表为空时\n");}// 链表不为空时else{// 插入节点new_node->next = list->next;list->next = new_node;new_node->next->prev = new_node;new_node->prev = list;// printf("[insert_list_head]当链表不为空时\n");}return 0;
}
(2)图示
4.双向循环链表节点尾插
(1)示例代码:
int insert_list_tail(int newdata, double_list_t *list)
{// 申请一个节点 -堆空间double_list_t *new_node = malloc(sizeof(double_list_t));if (new_node == NULL) {printf("[insert_list_tail]申请新的节点失败\n");return -1; // 申请内存失败}// 初始化数据域new_node->data = newdata;new_node->next = NULL;new_node->prev = NULL;// 定义指针p去找到链表的尾部double_list_t *p = list;while (p->next != list){p = p->next;}// 此时p已经到最后一个节点的位置new_node->next = list;p->next = new_node;list->prev = new_node;new_node->prev = p;return 0;
}
(2)图示
5.双向循环链表节点中间插入
(1)示例代码:
int insert_list_mid(int olddata, int newdata, double_list_t *list)
{// 找到要插入的节点double_list_t *p = list;while (p->next != list){p = p->next;if (p->data == olddata){break;}}// 申请一个新的节点 -堆空间double_list_t *new_node = malloc(sizeof(double_list_t));// 初始化数据域new_node->data = newdata;new_node->next = NULL;new_node->prev = NULL;// p指向最后一个节点if (p->next == list){// 如果最后一个节点是要插入的数据if (p->data == olddata){new_node->next = p->next; p->next = new_node; new_node->prev = p;}else{printf("[insert_list_mid]要插入的数据不存在\n");return -1;}}else // 遍历到中间找到需要插入的节点{new_node->next = p->next; p->next = new_node; new_node->prev = p; new_node->next->prev = new_node;}return 0;
}
(2)图示
6.双向循环链表删除节点
(1)示例代码:
int list_delnode(int deldata, double_list_t *list)
{// p指向链表的头节点double_list_t *p = list;while (p->next != list){// 找到要删除的节点并进行删除if (p->data == deldata){p->prev->next = p->next; p->next->prev = p->prev;double_list_t *temp = p->next; // 将temp指针指向p的下一个节点 p->next = NULL;p->prev = NULL;free(p); // 释放p后此时p是野指针p = temp; // p往后移动}else{p = p->next;} }// 遍历到最后一个节点if (p->next == list){// 若最后一个节点是要删除的节点,则删除if (p->data == deldata){p->prev->next = list;p->next = NULL;list->prev = p->prev;p->prev = NULL;free(p);}else{printf("[list_delnode]最后一个节点不是要删除的节点\n");return 0;}}
}
(2)图示
7.双向循环链表修改节点数据
(1)示例代码:
int list_update_node(int old_data, int new_data, double_list_t *list)
{double_list_t *p = list;while (p->next != list){p = p->next; // p往后移动if (p->data == old_data){p->data = new_data;}}return 0;
}
8.双向循环链表遍历
int list_show(double_list_t *list)
{double_list_t *p = list; //p指向头结点while (p->next != list){p = p->next;printf("[list_show]当前p指向的节点数据:%d\n", p->data);}
}
9.完整示例代码
#include <stdio.h>
#include <stdlib.h>// 1.封装一个结构体来表示双向循环链表
typedef struct double_list{int data;struct double_list *next;struct double_list *prev;
}double_list_t;// 2.初始化双向循环链表-->定义结构体变量 创建头节点
double_list_t *double_list_init()
{double_list_t *head_node = malloc(sizeof(double_list_t));if (head_node != NULL){head_node->next = head_node;head_node->prev = head_node;}else{printf("[double_list_init]申请头节点失败\n");}return head_node;
}// 头插
int insert_list_head(int newdata, double_list_t *list)
{// 申请一个节点 -堆空间double_list_t *new_node = malloc(sizeof(double_list_t));if (new_node == NULL) {printf("[insert_list_head]申请新的节点失败\n");return -1; // 申请内存失败}// 初始化数据域new_node->data = newdata;new_node->next = NULL;new_node->prev = NULL;// 当链表为空时if (list->next == list){list->next = new_node;new_node->next = list;new_node->prev = list;list->prev = new_node;// printf("[insert_list_head]当链表为空时\n");}// 链表不为空时else{// 插入节点new_node->next = list->next;list->next = new_node;new_node->next->prev = new_node;new_node->prev = list;// printf("[insert_list_head]当链表不为空时\n");}return 0;
}
/*@brief:3.插入数据-->尾插(在最后一个有效成员的后面插入数据)*@param(in): newdata :待插入的数据 list:链表头节点*@param(out): *@retval:
*/
int insert_list_tail(int newdata, double_list_t *list)
{// 申请一个节点 -堆空间double_list_t *new_node = malloc(sizeof(double_list_t));if (new_node == NULL) {printf("[insert_list_tail]申请新的节点失败\n");return -1; // 申请内存失败}// 初始化数据域new_node->data = newdata;new_node->next = NULL;new_node->prev = NULL;// 定义指针p去找到链表的尾部double_list_t *p = list;while (p->next != list){p = p->next;}// 此时p已经到最后一个节点的位置new_node->next = list;p->next = new_node;list->prev = new_node;new_node->prev = p;return 0;
}// 节点中间插入链表
int insert_list_mid(int olddata, int newdata, double_list_t *list)
{// 找到要插入的节点double_list_t *p = list;while (p->next != list){p = p->next;if (p->data == olddata){break;}}// 申请一个新的节点 -堆空间double_list_t *new_node = malloc(sizeof(double_list_t));// 初始化数据域new_node->data = newdata;new_node->next = NULL;new_node->prev = NULL;// p指向最后一个节点if (p->next == list){// 如果最后一个节点是要插入的数据if (p->data == olddata){new_node->next = p->next; p->next = new_node; new_node->prev = p;}else{printf("[insert_list_mid]要插入的数据不存在\n");return -1;}}else // 遍历到中间找到需要插入的节点{new_node->next = p->next; p->next = new_node; new_node->prev = p; new_node->next->prev = new_node;}return 0;
}
// 删除节点
int list_delnode(int deldata, double_list_t *list)
{// p指向链表的头节点double_list_t *p = list;while (p->next != list){// 找到要删除的节点并进行删除if (p->data == deldata){p->prev->next = p->next; p->next->prev = p->prev;double_list_t *temp = p->next; // 将temp指针指向p的下一个节点 p->next = NULL;p->prev = NULL;free(p); // 释放p后此时p是野指针p = temp; // p往后移动}else{p = p->next;} }// 遍历到最后一个节点if (p->next == list){// 若最后一个节点是要删除的节点,则删除if (p->data == deldata){p->prev->next = list;p->next = NULL;list->prev = p->prev;p->prev = NULL;free(p);}else{printf("[list_delnode]最后一个节点不是要删除的节点\n");return 0;}}
}
// 修改节点
int list_update_node(int old_data, int new_data, double_list_t *list)
{double_list_t *p = list;while (p->next != list){p = p->next; // p往后移动if (p->data == old_data){p->data = new_data;}}return 0;
}// 4.遍历链表,打印节点数据
int list_show(double_list_t *list)
{double_list_t *p = list; //p指向头结点while (p->next != list){p = p->next;printf("[list_show]当前p指向的节点数据:%d\n", p->data);}
}int main(int argc, char const *argv[])
{// 初始化单链表 ,指向链表的头节点double_list_t *my_list_head = double_list_init();// 往链表插入数据insert_list_head(2, my_list_head);insert_list_head(3, my_list_head);insert_list_head(4, my_list_head);insert_list_tail(15, my_list_head);insert_list_tail(16, my_list_head);insert_list_tail(17, my_list_head);insert_list_head(2, my_list_head);insert_list_tail(15, my_list_head);insert_list_tail(15, my_list_head);insert_list_tail(15, my_list_head);insert_list_mid(5, 6, my_list_head);insert_list_mid(2, 88, my_list_head);insert_list_mid(17, 15, my_list_head);printf("============插入的节点============\n");list_show(my_list_head);printf("============插入的节点============\n");// 删除节点list_delnode(25, my_list_head);list_delnode(15, my_list_head);list_delnode(2, my_list_head);printf("============删除后的节点============\n");list_show(my_list_head); // 打印数据printf("============删除后的节点============\n");// 修改数据list_update_node(16, 116, my_list_head);printf("============修改后的节点============\n");list_show(my_list_head); // 打印数据printf("============修改后的节点============\n");return 0;
}
/*
执行结果:
[insert_list_mid]要插入的数据不存在
============插入的节点============
[list_show]当前p指向的节点数据:2
[list_show]当前p指向的节点数据:88
[list_show]当前p指向的节点数据:4
[list_show]当前p指向的节点数据:3
[list_show]当前p指向的节点数据:2
[list_show]当前p指向的节点数据:15
[list_show]当前p指向的节点数据:16
[list_show]当前p指向的节点数据:17
[list_show]当前p指向的节点数据:15
[list_show]当前p指向的节点数据:15
[list_show]当前p指向的节点数据:15
[list_show]当前p指向的节点数据:15
============插入的节点============
[list_delnode]最后一个节点不是要删除的节点
[list_delnode]最后一个节点不是要删除的节点
============删除后的节点============
[list_show]当前p指向的节点数据:88
[list_show]当前p指向的节点数据:4
[list_show]当前p指向的节点数据:3
[list_show]当前p指向的节点数据:16
[list_show]当前p指向的节点数据:17
============删除后的节点============
============修改后的节点============
[list_show]当前p指向的节点数据:88
[list_show]当前p指向的节点数据:4
[list_show]当前p指向的节点数据:3
[list_show]当前p指向的节点数据:116
[list_show]当前p指向的节点数据:17
============修改后的节点============
*/