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日

相关文章

  • Java数据结构之优先级队列(PriorityQueue)用法详解

    Java数据结构之优先级队列(PriorityQueue)用法详解 什么是优先级队列? 优先级队列(Priority Queue)是一种特殊的队列,它能够保证每次取出的元素都是优先级最高(或者最低)的元素。在实际应用中,优先级队列经常用来实现任务调度,负载均衡等。 Java中的优先级队列 在Java中,优先级队列实现了Queue接口,所以它也具有队列的基本特…

    数据结构 2023年5月17日
    00
  • 深入理解Objective-C中类的数据结构

    深入理解Objective-C中类的数据结构 在Objective-C中,类作为面向对象编程的基础,是必不可少的概念。理解Objective-C中类的数据结构,对于开发者理解iOS应用程序的底层原理,以及编写高质量代码具有重要的意义。 类的数据结构 一个Objective-C类由以下几部分组成: isa指针:指向该类对象的元类,元类是描述一个类的对象。isa…

    数据结构 2023年5月17日
    00
  • C语言深入讲解链表的使用

    C语言深入讲解链表的使用 什么是链表? 链表是一种常用的数据结构,它的存储方式是通过指针相互连接实现的。链表是由若干个节点(node)构成的,每个节点都存储着一些信息和指向下一个节点的指针。 链表实现的基本操作 链表的基本操作包括插入节点、删除节点以及遍历链表。我们下面将通过代码示例详细介绍这些操作。 插入节点 链表的插入节点操作是指在链表的某一位置插入一个…

    数据结构 2023年5月17日
    00
  • JavaScript 数据结构之散列表的创建(2)

    下面是详细讲解“JavaScript 数据结构之散列表的创建(2)”的完整攻略。 散列表(哈希表) 散列表是一种数据结构,使用哈希函数将键映射到索引。散列表可以在常量时间 O(1) 中进行插入、删除和查找操作,但也具有碰撞冲突问题。 碰撞冲突问题 在散列表中,当两个不同的键通过哈希函数映射到了同一个索引位置时,就会发生碰撞冲突问题。解决碰撞冲突问题的方法有很…

    数据结构 2023年5月17日
    00
  • C语言数据结构之堆排序的优化算法

    C语言数据结构之堆排序的优化算法攻略 堆排序简介 堆排序(HeapSort)是一种树形选择排序,在排序过程中始终保持一个最大堆,每次将堆顶元素与最后一个元素交换位置,并进行一次最大堆调整操作,直到整个序列有序为止。 堆排序的时间复杂度为O(nlogn),具有不需额外存储空间的特点,因此广泛应用于内存受限的场景。 堆排序的优化算法 1. 建堆操作的优化 将序列…

    数据结构 2023年5月17日
    00
  • Java数据结构及算法实例:快速计算二进制数中1的个数(Fast Bit Counting)

    Java数据结构及算法实例:快速计算二进制数中1的个数 简介 本文将介绍在Java中快速计算二进制数中1的个数的算法。本算法是一种基于位运算的算法,其核心思想是利用位运算的快捷性,将原问题转化为每次计算一位是否为1的问题,使得计算速度大大提升。 背景知识 在理解本算法之前,需要了解Java中的一些背景知识: 1. 位运算 Java中的位运算符有如下几个: &…

    数据结构 2023年5月17日
    00
  • C语言数据结构实现字符串分割的实例

    C语言中数据结构实现字符串分割可以用到两种常见数据结构:指针和数组。 方法一:指针 步骤一:创建指针 首先声明一个指针类型的变量,用来存储字符串中单个字符所在的地址: char *ptr; 步骤二:遍历字符串 通过对字符串进行遍历,在每个分隔符位置上获取单词,并通过指针记录下每个单词的地址: char str[] = "C语言-数据结构-字符串分割…

    数据结构 2023年5月17日
    00
  • Java数据结构之LinkedList的用法详解

    Java数据结构之LinkedList的用法详解 LinkedList简介 LinkedList是Java中的一个数据结构,它是一个双向链表,可以提供快速的插入和删除操作。LinkedList中的元素分别保存在每个节点中,每个节点包含了指向前一个节点和后一个节点的引用。 使用LinkedList的好处是,其可以快速的进行插入和删除操作,但是如果需要随机存取中…

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