在數據結構的學習中,線性表是最基礎、最核心的結構之一 —— 它是后續棧、隊列、鏈表等復雜結構的 “基石”。今天從 “是什么”(定義)到 “怎么用”(基本操作),徹底搞懂線性表的核心邏輯。
一、先明確:數據結構的三要素
在聊線性表之前,必須先記住數據結構的核心三要素,這是理解所有結構的前提:
邏輯結構:數據元素之間的 “關系”(比如線性表的 “前后順序”);
數據的運算:對數據元素能做的操作(比如增、刪、改、查);
存儲結構(物理結構):數據在內存中的 “存放方式”(比如數組、鏈表)。
關鍵提醒:存儲結構不同,運算的實現方式也不同(比如數組實現和鏈表實現的 “插入” 操作,底層邏輯完全不一樣),但今天我們先聚焦 “邏輯結構” 和 “運算”。
二、線性表的定義:到底什么是線性表?
線性表是具有相同數據類型的 n(n≥0)個數據元素的有限序列,用 L 命名時可表示為:
( L = (a_1, a_2, …, a_i, a_{i+1}, …, a_n) )
我們拆解這個定義里的關鍵信息,再結合例子理解會更透徹:
1. 定義的 3 個核心特性
-
同類型:所有元素的數據類型必須一致(比如全是整數、全是學生信息);
-
有限性:元素個數 n 是有限的(不存在無限個元素的線性表);
-
有序性:元素之間有明確的 “前后順序”(a? 在 a? 前面,a? 在 a? 前面,不能亂序)。
2. 幾個必須分清的術語
術語 | 含義 |
---|---|
表長 | 線性表中元素的個數 n(n=0 時為空表) |
表頭元素 | 第一個元素 a? |
表尾元素 | 最后一個元素 a? |
直接前驅 | 除 a? 外,每個元素 a? 前面的那個元素(即 a???) |
直接后繼 | 除 a? 外,每個元素 a? 后面的那個元素(即 a???) |
位序 | 元素在表中的 “位置編號”(從 1 開始!和數組下標從 0 開始形成區別) |
3. 舉個例子:哪些是線性表?
-
例 1:所有整數按遞增順序排列(1,2,3,4,…100)—— 同類型(整數)、有限(100 個)、有序(遞增),是線性表;
-
例 2:學生信息表(如下表)—— 同類型(學生信息)、有限(10 條記錄)、有序(按學號排序),是線性表;
學號 | 姓名 | 專業 |
---|---|---|
1120112100 | 張三 | 挖掘機 |
1120112101 | 李四 | 挖掘機 |
1120112102 | 王玉玉 | 數據挖掘 |
- 例 3:學習計劃列表(學習《C 語言》→ 學習《數據結構》→ 學習《架構師》)—— 同類型(學習任務)、有限、有序,也是線性表。
三、線性表的基本操作:從 “創” 到 “銷” 全流程
為什么要定義基本操作?核心原因有兩個:
-
團隊協作:封裝好的操作能讓其他人直接用,不用重復理解底層邏輯;
-
減少錯誤:常用操作寫成函數,避免重復編碼導致的 bug。
線性表的操作可以按 “生命周期” 和 “功能” 分為 4 類,我們逐個拆解(重點關注 “是否需要傳引用 &”):
1. 創銷類:線性表的 “出生” 與 “消亡”
這兩類操作是線性表的基礎 —— 從 “無” 到 “有”,再從 “有” 到 “無”。
- InitList (&L):初始化表
功能:構造一個空的線性表 L,并為其分配內存空間。
為什么傳 &L?因為要修改 L 本身(給它分配內存、設置表長為 0),需要把修改結果 “帶回來”。
- DestroyList (&L):銷毀表
功能:銷毀線性表 L,并釋放它占用的內存空間(避免內存泄漏)。
為什么傳 &L?因為要釋放 L 指向的內存,修改 L 的狀態(比如讓 L 指向 NULL),需要帶回報錯結果。
2. 增刪類:改變線性表的 “長度”
這兩類操作會修改線性表的元素個數,是高頻操作。
- ListInsert (&L, i, e):插入元素
功能:在表 L 的第 i 個位置,插入新元素 e(插入后表長 +1)。
傳參說明:&L(要修改表的結構)、i(插入位置,需滿足 1≤i≤表長 + 1)、e(要插入的元素)。
- ListDelete (&L, i, &e):刪除元素
功能:刪除表 L 第 i 個位置的元素,并用 e 保存被刪除元素的值(刪除后表長 -1)。
為什么 &e?因為要把 “被刪除的元素值” 帶回來(比如用戶需要知道刪了什么)。
3. 改查類:定位元素(“改” 的前提是 “查”)
“查” 是 “改” 的基礎 —— 要修改元素,必須先找到它的位置或值。
- GetElem (L, i):按位查找
功能:獲取表 L 第 i 個位置的元素值(i 需滿足 1≤i≤表長)。
為什么不傳 &L?因為只是 “讀取” 元素,沒有修改表的結構或內容,不需要帶回結果。
- LocateElem (L, e):按值查找
功能:在表 L 中查找 “值等于 e” 的元素,返回它的位序(若找不到返回 0 或 NULL)。
同理,僅讀取,不傳 &L。
4. 其他常用操作:輔助功能
這些操作是對線性表的 “補充查詢”,高頻且實用:
-
Length (L):求表長:返回表 L 中元素的個數 n;
-
PrintList (L):輸出表:按前后順序打印所有元素(比如打印學生信息表);
-
Empty (L):判空:若表 L 為空(n=0)返回 true,否則返回 false。
關鍵考點:什么時候傳引用 “&”?
當對參數的修改結果需要 “帶回來” 時,必須傳引用(或指針)。
比如:
-
不傳 & 的情況:調用 test(x) 后,x 的值在主函數中不變(修改只在 test 內部生效);
#include<stdio.h> void test(int x){x=1024;printf("test函數內部 x=%d\n",x); } int main(){int x=1;printf("調用test前 x=%d\n",x);test(x);printf("調用test后x=%d\n",x); }
-
傳 & 的情況:調用 test(&x) 后,x 的值在主函數中會被修改(修改結果帶回來了)。
#include<stdio.h> void test(int & x){x=1024;printf("test函數內部 x=%d\n",x); } int main(){int x=1;printf("調用test前 x=%d\n",x);test(x);printf("調用test后x=%d\n",x); }
對應到線性表操作:
需要傳 &L 的操作:InitList、DestroyList、ListInsert、ListDelete(都修改了 L 的結構或內容);
不需要傳 &L 的操作:GetElem、LocateElem、Length、PrintList、Empty(僅讀取,不修改)。
四、總結:線性表的核心要點
邏輯結構核心:同類型、有限、有序,每個元素(除首尾)有唯一前驅和后繼;
操作記憶思路:按 “創銷→增刪→改查” 的生命周期記憶,輔助 “判空、表長、打印”;
傳參關鍵:修改需 “帶回結果” 則傳 &,僅讀取則不傳;
注意細節:位序從 1 開始(和數組下標區分),函數命名要可讀(比如 InitList 比 fun1 更易理解)。