【入门级-数据结构-1、线性结构:链 表(单链表、双向链表、循环链表 )】

一、链表的基本概念

链表是一种物理存储单元上非连续、非顺序的线性结构,数据元素之间的逻辑关系通过指针链接来实现。

优点:

动态内存分配,不需要预先分配连续空间

插入删除操作方便,时间复杂度O(1)

缺点:

不支持随机访问,查找需要O(n)

需要额外的指针存储空间

二、单链表

单链表是最基本的链表结构,由一系列节点组成,每个节点包含:

数据域:存储数据元素

指针域:存储指向下一个节点的指针

核心特点:节点之间是单向连接的,只能从头到尾依次访问,不能反向访问。

  1. 结构定义

    typedef struct Node {

    int data; // 数据域

    struct Node* next; // 指针域

    } Node, *LinkedList;

  2. 基本操作

    初始化

    LinkedList initList() {

    LinkedList head = (Node*)malloc(sizeof(Node));

    if (head == NULL) return NULL;

    head->next = NULL;

    return head;

    }

    头插法

    void insertAtHead(LinkedList head, int value) {

    Node* newNode = (Node*)malloc(sizeof(Node));

    newNode->data = value;

    newNode->next = head->next;

    head->next = newNode;

    }

    尾插法

    void insertAtTail(LinkedList head, int value) {

    Node* newNode = (Node*)malloc(sizeof(Node));

    newNode->data = value;

    newNode->next = NULL;

    Node* p = head;

    while (p->next != NULL) {

    p = p->next;

    }

    p->next = newNode;

    }

    删除节点

    int deleteNode(LinkedList head, int value) {

    Node* p = head;

    while (p->next != NULL && p->next->data != value) {

    p = p->next;

    }

    if (p->next == NULL) return -1; // 未找到

    Node* temp = p->next;

    p->next = temp->next;

    free(temp);

    return 0;

    }

三、双向链表

双向链表是在单链表的基础上,每个节点增加一个指向前驱节点的指针,形成双向连接的结构。

核心特点:

每个节点有两个指针:prev(指向前一个节点)和next(指向后一个节点)

可以从两个方向遍历链表

支持双向查找,提高某些操作的效率

  1. 结构定义

    typedef struct DoubleNode {

    int data;

    struct DoubleNode* prev; // 前驱指针

    struct DoubleNode* next; // 后继指针

    } DoubleNode, *DoubleList;

  2. 基本操作

    初始化

    DoubleList initDoubleList() {

    DoubleList head = (DoubleNode*)malloc(sizeof(DoubleNode));

    if (head == NULL) return NULL;

    head->prev = NULL;

    head->next = NULL;

    return head;

    }

    插入(指定位置后)

    void insertAfter(DoubleNode* pos, int value) {

    if (pos == NULL) return;

    DoubleNode* newNode = (DoubleNode*)malloc(sizeof(DoubleNode));

    newNode->data = value;

    newNode->next = pos->next;

    newNode->prev = pos;

    if (pos->next != NULL) {

    pos->next->prev = newNode;

    }

    pos->next = newNode;

    }

    删除节点

    void deleteNode(DoubleList head, DoubleNode* target) {

    if (target == NULL) return;

    target->prev->next = target->next;

    if (target->next != NULL) {

    target->next->prev = target->prev;

    }

    free(target);

    }

四、循环链表

循环链表是链表的另一种形式,其最后一个节点的指针指向头结点(或第一个节点),形成一个环状结构。

核心特点:

没有NULL指针,链表中所有节点都首尾相连

从任意节点出发都可以访问到所有节点

可以无限遍历,需要设置终止条件

  1. 单循环链表

    结构定义

    typedef struct CircularNode {

    int data;

    struct CircularNode* next;

    } CircularNode, CircularList;
    初始化
    CircularList initCircularList() {
    CircularList head = (CircularNode
    )malloc(sizeof(CircularNode));

    if (head == NULL) return NULL;

    head->next = head; // 指向自身,形成循环

    return head;

    }

    插入

    void insertCircular(CircularList head, int value) {

    CircularNode* newNode = (CircularNode*)malloc(sizeof(CircularNode));

    newNode->data = value;

    newNode->next = head->next;

    head->next = newNode;

    }

    遍历(需判断循环结束)

    void printCircular(CircularList head) {

    if (head->next == head) {

    printf("空链表\n");

    return;

    }

    CircularNode* p = head->next;

    do {

    printf("%d -> ", p->data);

    p = p->next;

    } while (p != head->next);

    printf("(循环)\n");

    }

  2. 双向循环链表

    结构定义

    typedef struct DCNode {

    int data;

    struct DCNode* prev;

    struct DCNode* next;

    } DCNode, DCList;
    初始化
    DCList initDCList() {
    DCList head = (DCNode
    )malloc(sizeof(DCNode));

    if (head == NULL) return NULL;

    head->prev = head;

    head->next = head;

    return head;

    }

    插入

    void insertDC(DCList head, int value) {

    DCNode* newNode = (DCNode*)malloc(sizeof(DCNode));

    newNode->data = value;

    newNode->next = head->next;

    newNode->prev = head;

    head->next->prev = newNode;

    head->next = newNode;

    }

五、常见应用场景

链表类型 适用场景

单链表 栈、队列的底层实现,邻接表

双向链表 LRU缓存淘汰算法,需要双向遍历的场景

循环链表 约瑟夫环问题,操作系统进程调度(时间片轮转)

相关推荐
Omics Pro1 小时前
P4医学4大支柱需绑定4大数字技术才可落地
人工智能·python·算法·机器学习·plotly
csdn_aspnet1 小时前
C++ 霍尔分区算法(Hoare‘s Partition Algorithm)
数据结构·c++·算法
不知名的老吴1 小时前
熟练掌握Python,可数据结构和算法还是很难?
数据结构
无限进步_1 小时前
【Linux】进度条:行缓冲区、\r 与 fflush 的实战
linux·服务器·开发语言·数据结构·后端
郝学胜-神的一滴1 小时前
力扣 144:二叉树前序遍历的优雅实现
java·数据结构·c++·python·算法·leetcode·职场和发展
MegaDataFlowers1 小时前
543.二叉树的直径
算法
Kurisu5751 小时前
深度拆解:从 CPU 乱序执行到内存屏障,无锁编程的底层防线
算法
GIOTTO情1 小时前
智能舆情处置系统技术方案:基于NLP语义算法的全链路风险处置落地
人工智能·算法·自然语言处理