本文将介绍双向循环链表的基本概念,并通过具体的C语言代码实现,展示其创建、插入、删除、遍历和销毁等操作。
什么是双向循环链表?
双向循环链表是一种特殊的数据结构,它结合了双向链表和循环链表的特点。每个节点都有两个指针,一个指向下一个节点,另一个指向上一个节点。同时,整个链表形成一个环,即最后一个节点的下一个节点是指向第一个节点的。
基本操作实现
节点的创建
首先,我们需要定义一个结构体来表示双向循环链表的节点。每个节点包含一个数据域和两个指针域,分别指向下一个节点和上一个节点。
typedef struct Node {
int data;
struct Node* prev;
struct Node* next;
} *node_ptr;
创建节点的函数`creat_node`接受一个整数参数`data`,并返回一个新的节点指针。
node_ptr creat_node(int data) {
node_ptr s = (node_ptr)malloc(sizeof(Node));
if (s == NULL) {
printf("内存分配失败\n");
return NULL;
}
s->data = data;
s->next = NULL;
s->prev = NULL;
return s;
}
插入操作
插入操作通过`insert_at_end`函数实现,该函数接受链表的头指针和要插入的数据。新节点将被插入到链表的末尾。
void insert_at_end(node_ptr& head, int data) {
node_ptr s = creat_node(data);
if (head == NULL) {
head = s;
head->next = head;
head->prev = head;
} else {
node_ptr last = head->prev;
last->next = s;
s->prev = last;
s->next = head;
head->prev = s;
}
printf("已插入:%d\n", data);
}
删除操作
删除操作通过`delete_node`函数实现,该函数接受链表的头指针和要删除的值。如果找到匹配的节点,则将其从链表中移除。
void delete_node(node_ptr& head, int value) {
if (head == NULL) {
printf("头指针为空\n");
return;
}
node_ptr p = head;
do {
if (p->data == value) {
if (p->prev != p) {
p->prev->next = p->next;
p->next->prev = p->prev;
free(p);
return;
} else {
free(head);
head = NULL;
return;
}
printf("已删除:%d\n", value);
}
p = p->next;
} while (p != head);
printf("没有找到匹配的值\n");
}
遍历操作
遍历操作通过`traversal`函数实现,该函数接受链表的头指针,依次打印出每个节点的数据。
void traversal(node_ptr& head) {
if (head == NULL) {
printf("头指针为空\n");
return;
}
node_ptr s = head;
do {
printf("%d\n", s->data);
s = s->next;
} while (s != head);
printf("遍历结束\n");
}
销毁操作
销毁操作通过`destroy`函数实现,该函数接受链表的头指针,依次释放每个节点的内存。
void destroy(node_ptr& head) {
node_ptr p;
node_ptr flag = head;
do {
p = head;
head = head->next;
printf("正在摧毁:%d\n", p->data);
free(p);
} while (head != flag);
printf("销毁完毕\n");
}
应用场景
双向循环链表在实际应用中有多种用途,例如:
1. **音乐播放器播放列表**:可以方便地实现歌曲的前后切换和循环播放。
2. **浏览器历史记录**:可以方便地实现页面的前进和后退功能。
3. **缓存管理**:可以实现最近最少使用(LRU)算法,快速找到最旧的缓存进行替换。
总结
本文介绍了双向循环链表的基本概念和实现方法,包括节点的创建、插入、删除、遍历和销毁等操作。通过这些基本操作,我们可以灵活地应用双向循环链表解决实际问题。
Lk.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
typedef struct Node {
int data;
struct Node* prev;
struct Node* next;
}*node_ptr;
node_ptr creat_node(int data);
void insert_at_end(node_ptr &head, int data);
void delete_node(node_ptr& head, int value);
void traversal(node_ptr& head);
void destroy(node_ptr& head);
Lk.cpp
#include "Lk.h"
node_ptr creat_node(int data)
{
node_ptr s = (node_ptr)malloc(sizeof(Node));
if (s == NULL)
{
printf("内存分配失败\n");
return NULL;
}
s->data = data;
s->next = NULL;
s->prev = NULL;
return s;
}
void insert_at_end(node_ptr& head, int data)
{
node_ptr s = creat_node(data);
if (head == NULL)
{
head = s;
head->next = head;
head->prev = head;
}
else {
node_ptr last = head->prev;
last->next = s;
s->prev = last;
s->next = head;
head->prev = s;
}
printf("已插入:%d\n", data);
return ;
}
void delete_node(node_ptr& head, int value)
{
if (head == NULL) {
printf("头指针为空\n");
return;
}
node_ptr p = head;
do {
if (p->data == value)
{
if (p->prev != p)
{
p->prev->next = p->next;
p->next->prev = p->prev;
free(p);
return;
}
else {
free(head);
head = NULL;
return;
}
printf("已删除:%d\n", value);
}
p = p->next;
} while (p != head);
printf("没有找到匹配的值\n");
}
void traversal(node_ptr& head)
{
if (head == NULL)
{
printf("头指针为空\n");
return;
}
node_ptr s = head;
do {
printf("%d\n", s->data);
s = s->next;
} while (s != head);
printf("遍历结束\n");
}
void destroy(node_ptr& head)
{
node_ptr p;
node_ptr flag = head;
do{
p = head;
head = head->next;
printf("正在摧毁:%d\n", p->data);
free(p);
} while (head != flag);
printf("销毁完毕\n");
return;
}
main函数
#include"Lk.h"
int main() {
/*typedef struct Node {
int data;
struct Node* prev;
struct Node* next;
}*node_ptr;
node_ptr creat_node(int data);
void insert_at_end(node_ptr & head, int data);
void delete_node(node_ptr & head, int value);
void traversal(node_ptr & head);
void destroy(node_ptr & head);*/
node_ptr head = (node_ptr)malloc(sizeof(Node));
head = NULL;
for(int i=0;i<10;i++)
insert_at_end(head,i);
delete_node(head,5);
traversal(head);
destroy(head);
head = NULL;
return 0;
}
运行结果