C语言类的双向链表详解

C语言类的双向链表详解

基本概念

什么是双向链表?

双向链表是链表的一种,它有两个指针域:一个指向前一个结点,一个指向后一个结点。每个结点包含两个部分:数据和指针域,指针域分别指向前一个结点和后一个结点,所以每个结点都是由数据和两个指针域构成的。

双向链表的作用?

双向链表可以支持O(1)时间复杂度的在任何一个结点前或后插入一个结点。

双向链表的实现方式?

在C语言中,双向链表可以通过结构体和指针来实现,我们使用struct定义每个链表结点,包含数据和两个指针域。通过指针来连接每个结点形成链表,指针可以动态的指向前后结点,实现双向遍历。

创建双向链表

初始化一个双向链表

struct Node {
    int data;
    struct Node* next;
    struct Node* prev;
};

// 初始化一个空的双向链表
struct Node* linkedlist_init() {
    struct Node* head = (struct Node*) malloc(sizeof(struct Node));
    head->data = 0;
    head->next = NULL;
    head->prev = NULL;
    return head;
}

向双向链表中插入一个结点

// 在双向链表的pos位置增加一个节点node
void linkedlist_insert(struct Node* pos, struct Node* node) {
    node->next = pos->next;
    pos->next->prev = node;
    node->prev = pos;
    pos->next = node;
}

从双向链表中删除一个结点

// 从双向链表中删除一个节点
void linkedlist_delete(struct Node* node) {
    node->prev->next = node->next;
    node->next->prev = node->prev;
    free(node);
}

示例

示例1

以下示例展示了如何创建一个双向链表,并在其中插入3个结点,再删除第2个结点。

int main(void) {
    struct Node* head = linkedlist_init();
    struct Node* node1 = (struct Node*) malloc(sizeof(struct Node));
    struct Node* node2 = (struct Node*) malloc(sizeof(struct Node));
    struct Node* node3 = (struct Node*) malloc(sizeof(struct Node));

    node1->data = 1;
    node2->data = 2;
    node3->data = 3;

    linkedlist_insert(head, node1); // head->node1
    linkedlist_insert(node1, node2); // head->node1->node2
    linkedlist_insert(node2, node3); // head->node1->node2->node3

    linkedlist_delete(node2); // head->node1->node3

    return 0;
}

示例2

以下示例展示了如何遍历一个双向链表,分别从头、尾、中间向前、向后遍历链表。

int main(void) {
    // 创建一个双向链表并初始化
    struct Node* head = linkedlist_init();
    struct Node* node1 = (struct Node*) malloc(sizeof(struct Node));
    struct Node* node2 = (struct Node*) malloc(sizeof(struct Node));
    struct Node* node3 = (struct Node*) malloc(sizeof(struct Node));
    struct Node* node4 = (struct Node*) malloc(sizeof(struct Node));
    struct Node* node5 = (struct Node*) malloc(sizeof(struct Node));

    node1->data = 1;
    node2->data = 2;
    node3->data = 3;
    node4->data = 4;
    node5->data = 5;

    linkedlist_insert(head, node1); // head->node1
    linkedlist_insert(node1, node2); // head->node1->node2
    linkedlist_insert(node2, node3); // head->node1->node2->node3
    linkedlist_insert(node3, node4); // head->node1->node2->node3->node4
    linkedlist_insert(node4, node5); // head->node1->node2->node3->node4->node5


    // 从头开始向后遍历
    for (struct Node* p = head->next; p != NULL; p = p->next) {
        printf("%d ", p->data); // 1 2 3 4 5
    }
    printf("\n");

    // 从尾开始向前遍历
    for (struct Node* p = node5; p != NULL; p = p->prev) {
        printf("%d ", p->data); // 5 4 3 2 1
    }
    printf("\n");

    // 从中间开始向前遍历
    for (struct Node* p = node2->prev; p != NULL; p = p->prev) {
        printf("%d ", p->data); // 1
    }
    printf("\n");

    // 从中间开始向后遍历
    for (struct Node* p = node2; p != NULL; p = p->next) {
        printf("%d ", p->data); // 2 3 4 5
    }
    printf("\n");

    return 0;
}

总结

双向链表是一种非常实用的数据结构,在很多场景中都能够发挥巨大的作用。上述介绍的初始化、插入、删除等常用操作都是非常基础的操作,通过合理应用这些操作可以实现更加复杂、高效的数据处理。

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

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

相关文章

  • 柏林噪声算法(Perlin Noise)

    概述 引述维基百科的介绍: Perlin噪声(Perlin noise,又称为柏林噪声)指由Ken Perlin发明的自然噪声生成算法,具有在函数上的连续性,并可在多次调用时给出一致的数值。 在电子游戏领域中可以透过使用Perlin噪声生成具连续性的地形;或是在艺术领域中使用Perlin噪声生成图样。 维基百科的介绍相当的官方,其实可以理解为一个随机函数,不…

    算法与数据结构 2023年4月17日
    00
  • 数据结构之数组Array实例详解

    数据结构之数组Array实例详解 什么是数组? 数组是一种由相同类型元素组成的集合,它们在内存中是连续存储的。通过下标可以访问数组中的元素,下标从0开始,到length-1结束。 定义数组 使用Array构造函数 可以使用Array构造函数来创建数组。以下是一些数组的创建方式。 var array1 = new Array(); // 创建空数组 var a…

    数据结构 2023年5月17日
    00
  • C++数据结构关于栈迷宫求解示例

    C++数据结构关于栈迷宫求解示例攻略 在本篇攻略中,我们将使用C++数据结构中的栈来解决迷宫问题,具体将通过两个示例来详细讲解该方法。首先介绍一下栈的概念。 栈的概念 栈是一种“后入先出”的数据结构,即最后压入栈中的元素会首先被弹出,而最早压入栈中的元素会最后被弹出。栈的基本操作有入栈(push)、出栈(pop)、判断是否为空以及读取栈顶元素等。 迷宫问题 …

    数据结构 2023年5月17日
    00
  • 「枚举」组合的输出

    本题为3月23日23上半学期集训每日一题中B题的题解 题面 (写题解的时候学校oj已不可查看此题,下面的题面来自洛谷第1157题) 题目描述 排列与组合是常用的数学方法,其中组合就是从 \(n\) 个元素中抽出 \(r\) 个元素(不分顺序且 \(r \le n\)),我们可以简单地将 \(n\) 个元素理解为自然数 \(1,2,\dots,n\),从中任取…

    算法与数据结构 2023年4月18日
    00
  • Java数据结构之常见排序算法(下)

    Java数据结构之常见排序算法(下) 前言 这是 Java 数据结构之常见排序算法的第二篇,本篇文章将继续介绍常见的排序算法。对于尚未了解基本排序算法的读者,可以先阅读 Java 数据结构之常见排序算法(上)。 快速排序 快速排序是一种使用分治思想的排序算法,其思路是将一个数组分为两个子数组,再对子数组进行排序,这个过程不断递归执行。在具体实现时,选择一个元…

    数据结构 2023年5月17日
    00
  • C语言实现单链表的基本操作分享

    C语言实现单链表的基本操作分享 什么是单链表 单链表是一种常见的数据结构,它由许多节点按照线性的方式组成。每个节点都包含一个值和一个指向下一个节点的指针。链表最后一个节点的指针通常指向NULL,表示链表的结束。 单链表的基本操作 单链表的基本操作包括插入、删除、查找、遍历等。 插入 当需要在单链表中插入一个节点时,需要先找到它的位置,然后将它插入到链表中。插…

    数据结构 2023年5月17日
    00
  • C语言全面讲解顺序表使用操作

    C语言全面讲解顺序表使用操作 什么是顺序表 顺序表(Sequential List)是一种常见的数据结构,它由一组连续的存储单元组成,并且支持随机访问。通常我们使用数组来实现顺序表。 顺序表的基本操作 初始化 在使用顺序表之前,需要先进行初始化。顺序表的初始化包括两个步骤:指定顺序表的大小,申请内存空间。具体代码如下: #define MAXSIZE 100…

    数据结构 2023年5月17日
    00
  • F – 产生冠军(不使用拓扑排序)

    题目描述 有一群人,打乒乓球比赛,两两捉对撕杀,每两个人之间最多打一场比赛。球赛的规则如下:如果A打败了B,B又打败了C,而A与C之间没有进行过比赛,那么就认定,A一定能打败C。如果A打败了B,B又打败了C,而且,C又打败了A,那么A、B、C三者都不可能成为冠军。根据这个规则,无需循环较量,或许就能确定冠军。你的任务就是面对一群比赛选手,在经过了若干场撕杀之…

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