C语言超详细讲解双向带头循环链表

C语言双向带头循环链表

基本概念

带头双向循环链表是指在双向循环链表的基础上,在头节点前面添加一个头结点。这个头结点不存储任何数据,只是为了方便对链表进行操作。循环链表则是在单向或双向链表的基础上,使链表的头节点与尾节点相连,形成一个环。

综合这两种链表,就构成了“双向带头循环链表”这种数据结构。双向带头循环链表是一种灵活性较高的数据结构,支持前插、后插、前删、后删等多种操作。

链表节点结构

在本文实现的双向带头循环链表中,链表节点包含了数据和指向前驱节点和后继节点的指针。

typedef int datatype;                          // 假设链表储存的数据类型为int
typedef struct node {
    datatype data;                             // 数据域
    struct node *prior, *next;                  // 指向前驱节点和后继节点的指针
} ListNode, *PListNode;                        // 将ListNode定义为结构体类型,PListNode定义为指向结构体ListNode的指针类型

初始化链表

初始化操作初始化链表,创建头节点,让头节点的前驱节点和后继节点都指向自身。

PListNode initList() {
    PListNode head = (PListNode)malloc(sizeof(ListNode));    // 分配一个头节点,并使head指向它
    head->prior = head->next = head;
    return head;
}

插入节点

链表的插入操作一般分为前插和后插,分别表示将节点插入到当前位置的前面或后面。

后插

后插操作是指在当前节点后面插入一个新节点。具体步骤如下:

  1. 创建一个新的节点,将新节点的前驱节点指向当前节点,将新节点的后继节点指向当前节点的后继节点。
  2. 将当前节点的后继节点的前驱节点指向新节点,将当前节点的后继节点指向新节点。
void insertAfter(PListNode pos, datatype value) {
    PListNode new_node = (PListNode)malloc(sizeof(ListNode));    // 创建新节点
    new_node->data = value;
    new_node->next = pos->next;
    new_node->prior = pos;
    pos->next->prior = new_node;
    pos->next = new_node;
}

前插

前插操作是指在当前节点前面插入一个新节点。具体步骤如下:

  1. 创建一个新的节点,将新节点的前驱节点指向当前节点的前驱节点,将新节点的后继节点指向当前节点。
  2. 将当前节点的前驱节点的后继节点指向新节点,将当前节点的前驱节点指向新节点。
void insertBefore(PListNode pos, datatype value) {
    PListNode new_node = (PListNode)malloc(sizeof(ListNode));    // 创建新节点
    new_node->data = value;
    new_node->next = pos;
    new_node->prior = pos->prior;
    pos->prior->next = new_node;
    pos->prior = new_node;
}

删除节点

链表的删除操作一般分为前删和后删,分别表示将当前位置的前驱节点或后继节点删除。

后删

后删操作是指删除当前节点的后继节点。具体步骤如下:

  1. 将当前节点的后继节点的后继节点的前驱节点指向当前节点。
  2. 将当前节点的后继节点的前驱节点指向空,将当前节点的后继指针指向后继节点的后继节点。
  3. 释放后继节点。
void deleteAfter(PListNode pos) {
    PListNode to_delete = pos->next;
    pos->next = to_delete->next;
    to_delete->next->prior = pos;
    to_delete->prior = NULL;
    to_delete->next = NULL;
    free(to_delete);
}

前删

前删操作是指删除当前节点的前驱节点。具体步骤如下:

  1. 将当前节点的前驱节点的前驱节点的后继节点指向当前节点。
  2. 将当前节点的前驱节点的后继节点指向空,将当前节点的前驱指针指向前驱节点的前驱节点。
  3. 释放前驱节点。
void deleteBefore(PListNode pos) {
    PListNode to_delete = pos->prior;
    pos->prior = to_delete->prior;
    to_delete->prior->next = pos;
    to_delete->prior = NULL;
    to_delete->next = NULL;
    free(to_delete);
}

示例说明

示例1

以下是一个将数列 {1, 2, 3, 4} 存入链表中的例子

int main() {
    PListNode head = initList();
    for (int i = 1; i <= 4; i++) {
        insertAfter(head, i);
    }

    PListNode ptr = head->next;

    while (ptr != head) {
        printf("%d ", ptr->data);
        ptr = ptr->next;
    }
    printf("\n");

    return 0;
}

输出结果为:

1 2 3 4

示例2

以下是一个在指定位置插入一个节点的例子

int main() {
    PListNode head = initList();
    for (int i = 1; i <= 4; i++) {
        insertAfter(head, i);
    }

    insertBefore(head->next->next, 5);

    PListNode ptr = head->next;

    while (ptr != head) {
        printf("%d ", ptr->data);
        ptr = ptr->next;
    }
    printf("\n");

    return 0;
}

输出结果为:

1 2 5 3 4

总结

双向带头循环链表是一种优秀的数据结构,通过正确的应用,可以使程序更简洁、易于理解和效率更高。在实际编程中,应根据需求选择合适的数据结构进行使用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言超详细讲解双向带头循环链表 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • C语言数据结构之单链表存储详解

    C语言数据结构之单链表存储详解 什么是单链表 链表是一种非顺序存储的数据结构,其每个节点都保存下一个节点的地址。单链表是最简单的链表,每个节点只包含下一个节点的地址。 单链表节点的定义 单链表的节点定义一般包括两个部分:数据域和指针域。数据域存放节点的数据,指针域存放下一个节点的地址。 以下是单链表节点的定义: typedef struct node { i…

    数据结构 2023年5月17日
    00
  • 一文吃透JS树状结构的数据处理(增删改查)

    一文吃透JS树状结构的数据处理(增删改查) 什么是树状结构 树状结构是一种经典的数据结构,在计算机领域中被广泛应用。树状结构由连通的节点组成,节点之间形成父子关系。一根树状结构的“根节点”没有父节点,每个子节点可以有多个“子节点”,但一个“子节点”只能有一个“父节点”。常见的应用包括文件系统、HTML DOM 和 JSON 数据格式等。 数据结构设计 我们以…

    数据结构 2023年5月17日
    00
  • 稀疏数组

    引入 当在网页上下棋类游戏时,玩到中途想要离开,但是我们需要保存进度,方便下次继续 我们应该怎么实现 ? 以围棋举例 使用二维数组将棋盘记下 ,如 0 为 没有棋子 ,1 为 黑子 , 2为白子 但是没有棋子的地方都为 0 ,整个二维数组充斥着大量的无效数据 0 我们需要想一个办法来 优化存储的方式 基本介绍 当一个数组中大部分元素是同一个值时,我们可以使用…

    算法与数据结构 2023年4月25日
    00
  • Java数据结构之加权无向图的设计实现

    Java数据结构之加权无向图的设计实现 前言 在计算机科学中,图(Graph)作为一种基本数据结构,被广泛应用于各种领域,如网络流、图像处理、计算机视觉等。本文将介绍加权无向图(Weighted Undirected Graph)的设计实现,涉及图的存储、添加边、获取特定节点的相邻节点、计算最短路径等。 设计实现 存储结构 加权无向图可以用一个邻接表数组存储…

    数据结构 2023年5月17日
    00
  • C++实现LeetCode(211.添加和查找单词-数据结构设计)

    首先,我们需要先了解一下题目的要求和限制,以及具体的解题思路。 题目描述 设计一个支持添加、删除、查找单词的数据结构。添加和删除单词的操作需要支持普通词和通配符’.’。查找单词只支持普通词,不支持通配符’.’。所有单词都是非空的。 解题思路 这道题可以使用前缀树(Trie树)来实现。 首先,我们需要定义一个单词类,它包含两个字段:单词字符串和单词长度。然后,…

    数据结构 2023年5月17日
    00
  • C++数据结构之搜索二叉树的实现

    C++数据结构之搜索二叉树的实现 搜索二叉树(Binary Search Tree, BST)是一种常见的数据结构,它支持快速地查找、插入和删除元素。本文将详细讲述如何用C++实现搜索二叉树。 一、搜索二叉树的定义 搜索二叉树是一种二叉树,它满足以下性质: 对于任意一个节点,其左子树中的所有节点都小于它,其右子树中的所有节点都大于它; 每个节点的左右子树也都…

    数据结构 2023年5月17日
    00
  • C#模拟链表数据结构的实例解析

    C#模拟链表数据结构的实例解析 简介 链表是一种常见的数据结构,它由一系列节点组成,每个节点包含一个数据元素和指向下一个节点的指针。本篇文章将介绍如何使用 C# 来模拟链表数据结构,并通过两个示例展示如何实现链表的操作。 链表的基本结构 链表是由一系列节点组成的,每个节点包含一个数据元素和指向下一个节点的指针。我们可以通过以下代码定义一个链表节点的类: pu…

    数据结构 2023年5月17日
    00
  • JavaScript中数据结构与算法(四):串(BF)

    JavaScript中数据结构与算法(四):串(BF) 一、串的定义 在计算机科学中,串(string)是由零个或多个字符组成的有限序列。零个字符的串称为空串(empty string),也叫做空格串(null string)。串中的字符数称为串的长度(length)。 二、串BF算法的定义 串的BF算法,也称为朴素算法(Brute-Force Algori…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部