【入门级-数据结构-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缓存淘汰算法,需要双向遍历的场景

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

相关推荐
不穿鞋的懒羊羊10 分钟前
dfs深度优先搜索
算法
OYYHXPJR31 分钟前
【算法】区间重叠模板和矩形重叠模板
算法
shehuiyuelaiyuehao33 分钟前
算法46,分治快排,排序数组
java·算法·排序算法·排序
careathers44 分钟前
【数据结构】栈
java·数据结构
远航计算机1 小时前
GEO 选题从哪来?用一份 Query 词库把一年内容排出来
大数据·人工智能·算法·aigc
宣宣猪的小花园.1 小时前
【机器学习】神经网络与表征:为什么深度学习能自动提取特征
人工智能·嵌入式硬件·算法·机器学习
mmmmath_31 小时前
LeetCode.018.四数之和
数据结构·算法·leetcode
AIGCmagic社区1 小时前
腾讯混元 AuK 技术报告拆读:1.5B 统一语音生成与编辑,蒸馏后 4 步无 CFG 提速 4.5 倍
人工智能·算法·aigc·ai多模态
大熊背1 小时前
基于照明色度表征的颜色恒常性的白平衡算法实现
算法·白平衡·色温·色度坐标·普朗克曲线
高亦真1 小时前
今天是学习嵌入式的第38天
linux·学习·算法