C语言数据结构 双向链表的建立与基本操作

C语言数据结构 双向链表的建立与基本操作

双向链表的定义

双向链表是一种常见的线性数据结构,它由多个结点组成,每个结点有两个指针,一个指向前一个结点,一个指向后一个结点。对于一个双向链表,我们可以获得其第一个结点和最后一个结点的指针,也可以沿着链表从前往后或从后往前遍历链表的每个结点。

双向链表的建立

我们首先需要定义一个双向链表的结点类型,包括两个指针,一个表示前一个结点,一个表示后一个结点。如下所示:

typedef struct node {
    int data;
    struct node *prev;  // 指向前一个结点
    struct node *next;  // 指向后一个结点
} Node;

然后,我们可以声明一个头结点,作为链表的头部,方便插入和删除操作。头结点不存储数据,只是一个指针类型的变量,其 prev 指针和 next 指针都指向 NULL,如下所示:

Node *head = (Node *)malloc(sizeof(Node));
head->prev = NULL;
head->next = NULL;

上述操作会创建一个空的双向链表,头结点为 head。

接下来,我们可以通过插入操作,逐个将结点插入到链表中,从而创建出一个完整的双向链表。在插入操作中,需要注意后继结点的指针应该指向新插入的结点,前驱结点的指针应该指向新插入的结点,新插入的结点的前驱结点指针应该指向前驱结点。

双向链表的基本操作

插入操作

双向链表的插入操作与单链表的插入操作类似,需要指定插入的位置和插入的值。如果插入的位置是链表的头部,则需要修改头结点的 next 指针,如果插入的位置是链表的中间或尾部,则需要修改插入结点前驱结点和后继结点的指针。代码示例如下:

void insert(Node *head, int pos, int value) {
    Node *newNode = (Node *)malloc(sizeof(Node));
    newNode->data = value;
    Node *p = head;

    for (int i = 0; i < pos && p != NULL; i++) {
        p = p->next;
    }

    if (p == NULL) {
        return;  // 位置错误,不插入结点
    }

    newNode->prev = p->prev;
    newNode->next = p;
    p->prev->next = newNode;
    p->prev = newNode;
}

删除操作

双向链表的删除操作与插入操作类似,同样需要指定删除的位置。删除操作需要修改删除结点前驱结点和后继结点的指针,代码示例如下:

void delete(Node *head, int pos) {
    Node *p = head;

    for (int i = 0; i < pos && p != NULL; i++) {
        p = p->next;
    }

    if (p == NULL) {
        return;  // 位置错误,不删除结点
    }

    p->prev->next = p->next;
    p->next->prev = p->prev;
    free(p);
}

遍历操作

双向链表的遍历操作可以从头结点开始遍历,依次访问每一个结点,并将其数据打印出来。代码示例如下:

void traverse(Node *head) {
    Node *p = head->next;

    while (p != NULL) {
        printf("%d ", p->data);
        p = p->next;
    }
}

示例说明

示例一

以下代码演示如何构建一个双向链表,插入若干数据并从头到尾输出链表:

#include <stdio.h>
#include <stdlib.h>

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

void insert(Node *head, int pos, int value) {
    Node *newNode = (Node *)malloc(sizeof(Node));
    newNode->data = value;
    Node *p = head;

    for (int i = 0; i < pos && p != NULL; i++) {
        p = p->next;
    }

    if (p == NULL) {
        return;  // 位置错误,不插入结点
    }

    newNode->prev = p->prev;
    newNode->next = p;
    p->prev->next = newNode;
    p->prev = newNode;
}

void traverse(Node *head) {
    Node *p = head->next;

    while (p != NULL) {
        printf("%d ", p->data);
        p = p->next;
    }
}

int main() {
    Node *head = (Node *)malloc(sizeof(Node));
    head->prev = NULL;
    head->next = NULL;

    insert(head, 0, 1);
    insert(head, 1, 2);
    insert(head, 2, 3);
    insert(head, 3, 4);

    traverse(head);
    return 0;
}

上述代码将输出:1 2 3 4

示例二

以下代码演示如何构建一个双向链表,删除链表中的某个结点并从头到尾输出链表:

#include <stdio.h>
#include <stdlib.h>

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

void delete(Node *head, int pos) {
    Node *p = head;

    for (int i = 0; i < pos && p != NULL; i++) {
        p = p->next;
    }

    if (p == NULL) {
        return;  // 位置错误,不删除结点
    }

    p->prev->next = p->next;
    p->next->prev = p->prev;
    free(p);
}

void traverse(Node *head) {
    Node *p = head->next;

    while (p != NULL) {
        printf("%d ", p->data);
        p = p->next;
    }
}

int main() {
    Node *head = (Node *)malloc(sizeof(Node));
    head->prev = NULL;
    head->next = NULL;

    Node *node1 = (Node *)malloc(sizeof(Node));
    node1->data = 1;
    head->next = node1;
    node1->prev = head;
    node1->next = NULL;

    Node *node2 = (Node *)malloc(sizeof(Node));
    node2->data = 2;
    node1->next = node2;
    node2->prev = node1;
    node2->next = NULL;

    Node *node3 = (Node *)malloc(sizeof(Node));
    node3->data = 3;
    node2->next = node3;
    node3->prev = node2;
    node3->next = NULL;

    delete(head, 2);

    traverse(head);
    return 0;
}

上述代码将输出:1 2

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言数据结构 双向链表的建立与基本操作 - Python技术站

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

相关文章

  • 数据结构串的操作实例详解

    数据结构串的操作实例详解 什么是数据结构串? 数据结构串是由若干个字符按照一定的顺序排列而成的线性结构。可以对串进行许多操作,如子串的截取、串的连接、串的替换等等。 数据结构串的基本操作 串的初始化 为了操作一个串,我们需要先定义一个串并初始化,可以通过以下代码实现: #include <stdio.h> #define MAXSIZE 100 …

    数据结构 2023年5月17日
    00
  • Java数据结构之链表相关知识总结

    Java数据结构之链表相关知识总结 链表是一种非常常用的数据结构,它有许多实际应用,比如链表可以用来实现栈、队列、散列表和图等数据结构。在Java语言中,链表的实现方式主要有单向链表、双向链表和循环链表。 单向链表 单向链表是一种链表结构,每个节点包含两个元素:节点值和一个指向下一个节点的引用。链表的头结点(第一个节点)不包含值,仅包含指向链表中第一个实际节…

    数据结构 2023年5月17日
    00
  • C++数据结构之双向链表

    C++数据结构之双向链表完整攻略 1. 什么是双向链表 双向链表是一种特殊的链表结构,每个节点拥有两个指针域,分别指向前继和后继节点。 双向链表不需要像单向链表那样从头到尾遍历整个链表,可以通过前后指针直接访问前后节点,提高了查找、删除、插入等操作的效率。 双向链表有一些常用的操作,如插入节点、删除节点、查找节点等。 2. 双向链表的实现 2.1 节点定义 …

    数据结构 2023年5月17日
    00
  • 一文带你走进js数据类型与数据结构的世界

    一文带你走进JS数据类型与数据结构的世界 一、JS数据类型 1. 原始类型 JS中原始类型包括:Undefined、Null、Boolean、Number、String、Symbol(ES6新增)。 其中Undefined和Null分别代表未定义和空值,Boolean表示布尔值,Number表示数字,String表示字符串,Symbol是ES6新增的一种基础…

    数据结构 2023年5月17日
    00
  • 数据结构与算法之手撕排序算法

    数据结构与算法之手撕排序算法 本篇攻略介绍如何手撕常见的排序算法。 冒泡排序 冒泡排序是一种通过不断交换相邻元素来排序的方法。它的时间复杂度为$O(n^2)$。 def bubble_sort(nums): for i in range(len(nums)): for j in range(len(nums)-i-1): if nums[j] > nu…

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

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

    数据结构 2023年5月17日
    00
  • 滑动窗口总结

    前言 滑动窗口是双指针的一种特例,可以称为左右指针,在任意时刻,只有一个指针运动,而另一个保持静止。滑动窗口路一般用于解决特定的序列中符合条件的连续的子序列的问题。 好处:时间复杂度 O(n^2) —> O(n) 一、算法应用场景 关键词: 1.满足XXX条件(计算结果、出现次数、同时包含) 2.最长/最短/或最值 3.子串/子数组/子序列 最最最…

    算法与数据结构 2023年4月17日
    00
  • Java数据结构之哈夫曼树概述及实现

    Java数据结构之哈夫曼树概述及实现 哈夫曼树概述 哈夫曼树(Huffman Tree),也称为最优树(Optimal Binary Tree),是一种带权路径长度最短的二叉树,也就是最小权重的前缀编码树。其基本思想是采用频率作为节点的权值,将频率较小的节点放在左子树上,频率较大的节点放在右子树上,从而形成一棵权值最小的二叉树。 实现过程 实现哈夫曼树需要以…

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