C语言数据结构之双向循环链表的实例

yizhihongxing

C语言数据结构之双向循环链表的实例

什么是双向循环链表?

双向循环链表是一种链式存储结构。每个节点都包含两个指针域,分别指向前一个节点和后一个节点,形成一个环形结构。双向循环链表可以实现正向和反向遍历,插入和删除节点的时间复杂度为$O(1)$。

双向循环链表的结构体定义

typedef struct Node
{
    ElemType data;
    struct Node *prev;
    struct Node *next;
} Node, *ListNode;

Node表示链表中的一个节点,ElemType为节点中存储的元素的类型。prev和next分别表示指向前一个节点和后一个节点的指针。

双向循环链表的初始化

ListNode initList()
{
    ListNode head = (ListNode)malloc(sizeof(Node));
    head->prev = head->next = head;
    return head;
}

initList()函数用于初始化双向循环链表,在头节点位置分配一个节点空间后,将前驱指针和后继指针都指向头节点,表示链表为空。

双向循环链表的插入

插入在链表头部

void insertHead(ListNode head, ElemType elem)
{
    ListNode node = (ListNode)malloc(sizeof(Node));
    node->data = elem;
    node->next = head->next;
    node->prev = head;
    head->next->prev = node;
    head->next = node;
}

insertHead()函数用于在链表头部插入一个元素。新建一个节点,将节点值赋为elem,将节点的next指向头节点的next,节点的prev指向头节点,然后将头节点的next和头节点的next的prev都指向新节点。

插入在链表尾部

void insertTail(ListNode head, ElemType elem)
{
    ListNode node = (ListNode)malloc(sizeof(Node));
    node->data = elem;
    node->prev = head->prev;
    node->next = head;
    head->prev->next = node;
    head->prev = node;
}

insertTail()函数用于在链表尾部插入一个元素。新建一个节点,将节点值赋为elem,将节点的prev指向头节点的prev,节点的next指向头节点,然后将头节点的prev和头节点的prev的next都指向新节点。

双向循环链表的删除

void deleteNode(ListNode head, ElemType elem)
{
    ListNode cur = head->next;
    while (cur != head)
    {
        if (cur->data == elem)
        {
            cur->prev->next = cur->next;
            cur->next->prev = cur->prev;
            free(cur);
            return;
        }
        cur = cur->next;
    }
}

deleteNode()函数用于删除数据域为elem的节点,遍历链表找到要删除的节点,将这个节点的前一个节点的next指针指向这个节点的后一个节点,同时将这个节点的后一个节点的prev指针指向这个节点的前一个节点。最后释放这个节点的空间。

示例说明

示例一

初始化一个双向循环链表,插入5个元素,分别为1,2,3,4,5。然后从头节点开始遍历链表,输出每个节点的值。

int main()
{
    ListNode list = initList();
    for (int i = 1; i <= 5; i++)
    {
        insertTail(list, i);
    }
    ListNode cur = list->next;
    while (cur != list)
    {
        printf("%d ", cur->data);
        cur = cur->next;
    }
    printf("\n");
    return 0;
}

输出结果为:1 2 3 4 5

示例二

初始化一个双向循环链表,插入5个元素,分别为1,2,3,4,5。然后删除数据域为3的节点之后,从头节点开始遍历链表,输出每个节点的值。

int main()
{
    ListNode list = initList();
    for (int i = 1; i <= 5; i++)
    {
        insertTail(list, i);
    }
    deleteNode(list, 3);
    ListNode cur = list->next;
    while (cur != list)
    {
        printf("%d ", cur->data);
        cur = cur->next;
    }
    printf("\n");
    return 0;
}

输出结果为:1 2 4 5

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言数据结构之双向循环链表的实例 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • 非常详细的/etc/passwd解释

    非常详细的 /etc/passwd 解释 在类UNIX操作系统中,/etc/passwd是存储本地用户信息的文件。在本篇文章中,将会详细解释/etc/passwd文件的各个字段以及它们是如何被用来控制用户的访问。 文件格式 /etc/passwd 文件由一行一行的文本记录构成,每一行都表示一个本地系统用户。每一行由冒号(::)分隔成了七个字段。以下是一些范例…

    其他 2023年3月28日
    00
  • 基于Vue实现封装一个虚拟列表组件

    下面是基于Vue实现封装一个虚拟列表组件的完整攻略: 1.了解需求和原理 在实现一个虚拟列表组件之前,我们首先需要了解这个组件的需求和原理。虚拟列表是指,当页面需要展示大量数据时,为了避免DOM元素的频繁创建和渲染,可以只渲染浏览器视窗范围内的一部分数据,随着用户的滚动,再动态地改变渲染的数据范围。常见的例子就是百度搜索结果、淘宝商品列表等。 实现虚拟列表的…

    other 2023年6月25日
    00
  • 关于java:找不到maven依赖项

    关于Java:找不到Maven依赖项的解决方案 在Java开发中,使用Maven管理依赖项是一种常见的方式。但有时候,我们可能遇到“找不到Maven依赖项”的问题。本攻略将介绍如何解决这个问题,并提供两个示例。 问题描述 当我们在使用Maven构建Java项目时,会遇到以下错误: Could not resolve dependencies for proj…

    other 2023年5月9日
    00
  • BAT批处理中的字符串处理详解(字符串截取)

    BAT批处理中的字符串处理详解(字符串截取) 在BAT批处理中,字符串处理是经常用到的技巧之一。本文详细讲解了在BAT批处理中的字符串截取方法。 字符串的长度 在BAT批处理中,获取字符串的长度可以使用“!变量名:~n,m!”的方式。其中,n是起始位置,m是截取长度,如果不设置m,表示一直截到字符串结尾。如下所示: @echo off set str=hel…

    other 2023年6月20日
    00
  • Win10右键菜单怎么添加删除复制路径选项?

    添加、删除和修改Win10右键菜单的步骤如下: 添加右键菜单选项 打开注册表编辑器(Registry Editor),使用快捷键“Win + R”,输入 “regedit” 然后按Enter键进入。 转到以下路径 HKEY_CLASSES_ROOT\*\shell 右键“shell”文件夹,选择“新建” -> “键值(key)”。 为新键值取一个名字,…

    other 2023年6月27日
    00
  • 不允许有重复的“row.names”

    当我们在R语言中使用read.table()或read.csv()等函数读取数据时,如果数据中有重复的行名(row.names),则会出现“不允许有重复的row.names”错误。以下是解决这个问题的完整攻略: 1. 查看数据中有重复的行名 首先,我们需要查看数据中是否有重复的行名。可以使用以下代码: data <- read.table("…

    other 2023年5月7日
    00
  • Springboot项目Aop与拦截器与过滤器横向对比

    当然!下面是关于\”Spring Boot项目AOP与拦截器与过滤器横向对比\”的完整攻略,包含两个示例说明。 … … … … 示例1:AOP的使用 @Aspect @Component public class LoggingAspect { @Before(\"execution(* com.example.demo.servi…

    other 2023年8月20日
    00
  • Java编程Socket实现多个客户端连接同一个服务端代码

    需要实现Java编程Socket实现多个客户端连接同一个服务端的功能,通常需要遵循以下步骤: 1. 创建服务端Socket在服务端,我们需要创建一个ServerSocket对象。这个对象可以监听客户端连接请求,并为每个新的连接创建一个Socket对象。以下是示例代码: ServerSocket serverSocket = new ServerSocket(…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部