數據結構:鏈表(Linked List)

目錄

結構推導

回到最原始的問題 —— 我們如何存數據?

第二步:我們來看看數組的限制?

第三步:那我們該怎么做呢??

第四步:我們推導鏈表的數據結構?

結構講解

什么是鏈表?

什么是節點??

如何創建節點?

?如何訪問節點?


結構推導

🎯 目標:理解什么是鏈表(linked list),為什么我們需要它,以及它的結構從哪里來的。

回到最原始的問題 —— 我們如何存數據?

在 C 語言中,最基礎的存數據方式是:

int a[100];

也就是 數組(array)。它非常常見,我們從一開始就用。

那我們先從數組的“第一性”特征說起:

數組的本質是:

一塊連續的內存空間 + 索引訪問

舉個例子:

int a[5] = {10, 20, 30, 40, 50};

這個數組在內存里是這樣的(假設從地址 1000 開始):

地址
100010
100420
100830
101240
101650

它的特性:

  • 地址連續

  • a[i] 的位置是:a + i × sizeof(int)

  • 可以快速通過索引訪問:O(1)

詳細內容可以參考:數據結構:數組(Array)_array[1..50]-CSDN博客


第二步:我們來看看數組的限制?

情況1:大小固定

如果你定義了:

int a[100];

你就固定只能存最多 100 個元素。如果只用了前 5 個元素,空間也浪費。

如果你事先不知道需要多少個元素,就很難選大小。

情況2:插入麻煩

假設你已經有數組:

int a[5] = {10, 20, 30, 40, 50};

現在你想在 第 2 個位置插入 99,就得把后面的都搬一格:

for (int i = 5; i > 1; i--) {a[i] = a[i - 1];
}
a[1] = 99;

這會導致O(n) 的時間復雜度。

情況3:刪除也麻煩

類似的,如果你要刪掉 a[2],也得把后面的全往前搬一格。

總結數組的問題:

問題描述
空間不靈活空間必須一開始就定下來
插入慢中間插入要整體移動元素
刪除慢刪除某項也要移動后面的元素
空間浪費有時只用一部分數組,但仍然占內存

第三步:那我們該怎么做呢??

我們思考一下:

能不能只在用到數據時,才開辟空間?

能不能插入一個元素,而不影響其它元素的位置?

這就引出了一個新的思維模型:

? 使用“分散空間 + 指針連接”的模型

如果我們不強求內存連續,而是:

  • 每次添加一個節點時,就用 malloc 單獨開一塊空間

  • 每個節點都保存指向“下一個節點”的指針

我們就可以實現靈活的動態結構了。

這就是 鏈表(linked list) 的思想:

把所有的數據節點一個一個連起來,而不是排成連續數組


第四步:我們推導鏈表的數據結構?

我們要存一個元素,它需要什么?

  1. 數據本身,比如:一個整數

  2. 指向下一個節點的“線索”(指針)

所以我們設計一個節點結構:

struct Node {int data;           // 當前節點的數據struct Node* next;  // 指向下一個節點
};

那一個“鏈表”是什么?

一個鏈表是“若干個 Node 連起來”,只要有第一個節點(頭結點)的地址,就能找到整個鏈表。

所以我們定義:

struct Node* head;  // 指向鏈表的起點

? 所以鏈表的基本單位是:節點 + 指針

[10 | *] --> [20 | *] --> [30 | NULL]
  • 每個方塊是一個 Node

  • *next 指針

  • 最后一個節點的 next = NULL 表示鏈表結束

結論:為什么我們需要鏈表?

問題

鏈表怎么解決

數組大小固定

鏈表可以動態增加節點(malloc)

插入/刪除慢

鏈表插入刪除只需修改指針,不搬數據

空間浪費

用多少開多少,不多開


結構講解

什么是鏈表?

在數組中,所有元素都在一塊連續的內存空間中。你只能在一開始就分配好大小,插入/刪除不方便。那么:

有沒有一種數據結構,不要求數據連續存儲,但依然能一個接一個地串起來?

?這就是鏈表的本質:

鏈表是由若干個節點組成的線性結構,每個節點都知道下一個節點在哪里,只需要記住第一個節點就能訪問整個鏈表。

鏈表的核心思想是:

每個節點知道“誰在后面”,就像每一節車廂都知道后面那節車廂的位置。

整個鏈表就像是一列火車,每節車廂通過“掛鉤”(指針)串聯起來:

? 鏈表的特征:

  • 節點之間不要求連續內存

  • 每個節點都包含:

    • 本節點的數據

    • 指向下一個節點的指針

  • 通過“指針”把節點連接起來

?通常我們用一個指針 head 來指向第一個節點:

struct Node* head;

什么是節點??

一個節點(Node)是鏈表的最基本組成單位,就是一個結構體,它包含:

  1. 一份數據(例如 int 類型)

  2. 一個指針,指向下一個節點

這就好比:

  • 火車的每節車廂(節點)都有:

    • 貨物(數據)

    • 連接器(指針)去連下一節車廂

?用C語言表示:

struct Node {int data;           // 節點中存的數據struct Node* next;  // 指向下一個節點的指針
};
成員含義
int data存儲數據,比如整數 10
Node* next保存下一個節點的地址,如果是最后一個就為 NULL

如何創建節點?

為什么我們不能直接寫:

struct Node node1;

1. 這句代碼在 棧(stack)上 分配了一個 Node 類型的變量。它的特點是:

  • 分配在棧上(函數調用結束后會被自動釋放)

  • 內存大小在編譯時就已經確定

  • 生命周期由作用域決定,作用域結束就失效

🔍 2. 鏈表是動態結構,不能預知節點個數

鏈表的本質是:

  • 你不知道總共有多少個節點(比如根據用戶輸入構建)

  • 每一個節點都需要“現用現開”,而不是提前一次性分配

所以我們需要在“運行時”動態分配空間:?

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

這行代碼的含義是:

  1. malloc(sizeof(struct Node))堆(heap)上動態分配一塊內存,大小正好是一個 Node

  2. 返回值是 void*,強制類型轉換成 struct Node*

  3. newNode 是一個指針,指向新建的節點

再從鏈表的設計需求來倒推

  • 節點數是動態變化的(例如用戶輸入10個節點)

  • 節點之間是用指針連接的

  • 每個節點可能在任何時刻被插入或刪除

  • 節點需要長期存在,甚至跨越函數作用域

?所以:必須用動態內存分配,也就是 malloc()。struct Node node1; 是不能滿足上述需求的


?如何訪問節點?

假設我們已經創建了多個節點,并鏈接起來:

struct Node* head = (struct Node*) malloc(sizeof(struct Node));
head->data = 10;struct Node* second = (struct Node*) malloc(sizeof(struct Node));
second->data = 20;head->next = second;
second->next = NULL;

訪問鏈表節點的本質邏輯是沿著 next 指針走,這就叫做遍歷鏈表(traverse the linked list)。

舉個例子,假設你有一個鏈表,要訪問節點內容:

head → [10 | * ] → [20 | * ] → [30 | NULL]

你想訪問第二個節點的值 20:

你不能說 head[1],因為它不是數組。

你只能說:

head->next->data

這個表達式的意義是:

  1. head 是第一個節點的地址

  2. head->next 是第二個節點的地址

  3. head->next->data 就是第二個節點的值

訪問第二個節點的數據:?

printf("%d\n", head->next->data);  // 輸出 20

遍歷就是:

head 開始,沿著每個節點的 next 指針走,直到你走到 NULL(鏈表結尾)

struct Node* temp = head;
while (temp != NULL) {printf("%d ", temp->data);temp = temp->next;
}
printf("\n");

這段代碼會訪問每個節點的 data,直到遇到 NULL。?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/91511.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/91511.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/91511.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[RK3566-Android11] U盤頻繁快速插拔識別問題

問題描述 做老化測試時,在使用U盤頻繁快速插拔的情況下,SDCard目錄會突然被Kill掉,然后又重新掛載上,這會導致系統及APP的數據因為讀寫異常,從而界面卡死正常U盤插拔不應該導致內部存儲卸載解決方案: SDK根…

【Golang】Go語言Map數據類型

Go語言Map數據類型 文章目錄Go語言Map數據類型一、Map1.1.1、map定義1.1.2、map的基本使用1.1.3、判斷某個鍵是否存在1.1.4、map的遍歷1.1.5、使用delete()函數刪除鍵值對1.1.6、按照指定順序遍歷map1.1.7、元素為map類型的切片1.1.8、值為切片類型的map一、Map map是一種無序…

Orange的運維學習日記--23.Linux計劃任務詳解

Orange的運維學習日記–23.Linux計劃任務詳解 文章目錄Orange的運維學習日記--23.Linux計劃任務詳解一次性計劃任務atd 服務at 命令基本語法交互式示例腳本文件示例timespec 格式示例查看與管理任務查看當前隊列查看任務詳細內容刪除任務用戶權限控制用戶周期性計劃任務查看任務…

Ubuntu 24.04.2 LTS 安裝mysql8.0.36保姆級教程(從安裝到遠程連接)

目錄 前言 一、系統準備 二、安裝 MySQL 8.0.36 1. 查看可用版本 2.如果沒有對應版本則需要手動下載mysql-apt-config(有則跳過) 2.1下圖是mysql-apt-config各版本對應的mysql版本 2.2下載mysql apt repository 2.3安裝 MySQL APT Repository 包 …

【LLM】講清楚MLA原理

需要你對MHA、MQA、GQA有足夠了解,相信本文能幫助你對MLA有新的認識。 本文內容都來自https://www.youtube.com/watch?v0VLAoVGf_74,如果閱讀本文出現問題,建議直接去看一遍。 按照Deepseek設定一些參數值:輸入token長度n10&…

谷歌采用 Ligero 構建其 ZK 技術棧

1. 引言 前序博客有: Ligero 和 Ligetron 中的 MPC 和 ZKLigetron:Nim Network開發的針對AI的zkVMLigetron:基于MPC-In-The-Head范式的zkVM簡介 在隱私保護身份驗證領域邁出重要一步,谷歌最近宣布 將零知識證明(ZKP…

Flutter渲染引擎:Impeller和Skia

一、Impeller 渲染引擎的發布時間Impeller 是 Flutter 團隊為解決 Skia 引擎在移動端(尤其是 iOS 平臺)的性能問題而開發的全新渲染引擎,其發展歷程如下:首次公開:2021 年 Google I/O 大會上首次提及,作為 …

網絡編程-加密算法

目錄 一.網絡編程基礎 1. 概述 2. IP地址 3. 域名 4. 網絡模型 5. 常用協議 6. 小結 二.TCP編程 1. 什么是Socket? 2. 服務器端 3. 客戶端 4. Socket流 5. 小結 三.UDP編程 1. 概述 2. 服務器端 3. 客戶端 4. 小結 案例: 四.加密算法 …

【網絡工程師軟考版】網絡安全

任何形式的網絡服務都會導致安全方面的風險,問題是如何將風險降到最低程度,目前的網絡安全措施有數據加密、數字簽名、身份認證、防火墻、特征過濾等。所涉內容:1、網絡安全基礎2、加密技術與哈希算法3、數字簽名4、數字證書5、VPN技術6、防火…

深入淺出設計模式——創建型模式之建造者模式 Builder

文章目錄建造者模式簡介建造者模式結構建造者模式代碼實例定義產品類House定義建造者定義抽象建造者AbstractBuilder定義具體建造者定義指揮者客戶端代碼示例運行結果建造者模式總結代碼倉庫建一棟房子總共分幾步?建造者模式告訴你答案!“把大象裝冰箱&a…

OpenVLA: 論文閱讀 -- 開源視覺-語言-行動模型

更多內容:XiaoJ的知識星球 目錄OpenVLA:開源視覺-語言-行動模型1. 介紹2. 相關工作1)視覺條件語言模型(Visually-Conditioned Language Models)2)通用型機器人策略(Generalist Robot Policies&a…

JavaWeb(蒼穹外賣)--學習筆記15(分頁查詢PageHelper)

前言 終于開始學習做項目了,本篇文章是學習B站黑馬程序員蒼穹外賣的學習筆記📑。我的學習路線是Java基礎語法-JavaWeb-做項目,管理端的功能學習完之后,就進入到了用戶端微信小程序的開發,這篇文章來看看分頁查詢&#…

金融專題|某跨境支付機構:以榫卯企業云平臺 VPC 功能保障業務主體安全

作者:SmartX 金融團隊 金融機構在信息化建設時面臨諸多數據合規要求,例如:不同業務區域之間互相隔離、數據庫僅能由關聯的應用服務器訪問、僅有特定的服務器允許被外網訪問等。對此,某跨境支付機構以 SmartX 榫卯企業云平臺構建私…

Win10下python環境變量呼出微軟應用商店

以下是三種徹底解決 Windows 10 的 CMD 中運行 python 命令彈出應用商店問題的方法??方法一:調整環境變量優先級?-或者直接刪除微軟應用商店的環境變量%USERPROFILE%\AppData\Local\Microsoft\WindowsApp???操作步驟??打開系統環境變量設置(右鍵…

字節跳動“扣子”(Coze)開源:AI智能體生態的技術革命

(以下借助 DeepSeek-R1 輔助整理) 在2025年7月26日的深夜,GitHub上悄然出現的兩個倉庫——Coze Studio和Coze Loop,在48小時內狂攬超過9,000顆Star。字節跳動以Apache 2.0許可證將自家AI智能體平臺的核心技術徹底開源。 “當所有人…

Camx-usecase ID和pipeline的匹配源碼解讀

組件關系整體流程:camxhal3.cpp:704 open()camxhal3.cpp:1423 configure_streams()chxextensionmodule.cpp:2810 InitializeOverrideSessionchxusecaseutils.cpp:850 GetMatchingUsecase()chxadvancedcamerausecase.cpp:4729 Initialize()chxadvancedcamerausecase.…

日志管理進入「對話式」時代:日志易MCP Server落地實錄

01 背景:MCP協議介紹在AI蓬勃發展的當下,大型語言模型(LLM)雖展現出強大潛力,卻受困于與外部資源連接的難題。數據分散、接口繁雜,致使AI模型難以靈活對接本地資源與遠程服務,極大限制了其響應質…

django-3模型操作

from django.db import modelsclass Book(models.Model):title models.CharField(max_length200) # 書名author models.CharField(max_length100) # 作者publish_date models.DateField() # 出版日期price models.DecimalField(max_digits10, decimal_places2) # 價格s…

【繪制圖像輪廓】——圖像預處理(OpenCV)

目錄 1 什么是輪廓 2 尋找輪廓 2.1 mode參數 2.2 method參數 3 繪制輪廓 1 什么是輪廓 輪廓是一系列相連的點組成的曲線,代表了物體的基本外形。輪廓是連續的,邊緣不一定連續。輪廓是一個閉合的、封閉的形狀。 輪廓的作用: 形狀分析 目…

嵌入式 Linux 深度解析:架構、原理與工程實踐(增強版)

嵌入式 Linux 深度解析:架構、原理與工程實踐(增強版) 目錄嵌入式 Linux 深度解析:架構、原理與工程實踐(增強版)第一章 嵌入式 Linux 基礎概念1.1 定義與核心特征1.2 典型架構棧深度解析第二章 Linux 文件…