双向循环链表的实现与应用

本文将介绍双向循环链表的基本概念,并通过具体的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;
}

运行结果

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值