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

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

相关推荐
Re.不晚3 小时前
挑战做100道力扣算法- DAY1
算法·leetcode·职场和发展
蓝悦无人机4 小时前
《Planning algorithms》读书笔记——第1章 引言
算法·读书笔记·规划算法·lavalle
Sagittarius_A*4 小时前
分组密码基础(二):Feistel 结构与 DES 的设计思想
算法·信息安全·密码学·des·数论
青山木4 小时前
Hot 100 --- 搜索插入位置
java·数据结构·算法·leetcode
alexwang2115 小时前
HDU 4348 详细题解
c++·算法·题解·hdu·主席树·可持久化数据结构·可持久化线段树
可编程芯片开发6 小时前
基于分段变步长搜索RMDCFT算法的天基雷达空间机动目标检测方法MATLAB仿真,对比RMDCFT算法
算法
2501_946736166 小时前
在线考试平台如何选型?从功能、优势与应用场景角度详解
大数据·人工智能·算法
天辛大师6 小时前
天心大师:不确定中锚定自我,AI生活的哲学命题
人工智能·算法·决策树·机器学习·生活·启发式算法
皓月斯语6 小时前
B2132 素数对
c++·算法·题解
星轨初途7 小时前
LeetCode 热题 100——day2 字母异位词分组
c++·算法·leetcode