《數據結構入門:順序表的結構設計與核心操作(C 語言版)》

目錄

一. 線性表

二. 順序表的概念與結構

2.1 核心概念

2.2 兩種常見結構

靜態順序表

動態順序表

2.3 核心區別對比

四. 順序表的實現

4.1 順序表的定義

4.2 順序表初始化

4.3 動態順序表容量檢查與擴容

4.4 動態順序表插入數據

4.4.1 頭插

4.4.2 尾插

4.4.3 指定位置插入

4.5 動態順序表的刪除數據

4.5.1 頭刪

4.5.2 尾刪

4.5.3 刪除指定位置的數據

4.5.4 刪除指定的數據

4.6 查找指定數據

4.6?動態順序表銷毀

五. 優缺點分析

六. 適用場景選擇

七. 總結


在學習順序表之前 我們需要有一定的基礎知識 首先我們需要了解線性表

一. 線性表

線性表是具有 “一對一” 邏輯關系的有限數據元素序列,是數據結構中最基礎、最常用的結構之一,廣泛應用于數組、鏈表等底層實現,也是棧、隊列等復雜結構的基礎。

核心定義與邏輯特征

線性表由?n(n≥0)?個相同數據類型的元素構成,記為?L = (a?, a?, ..., a?),其中:

  • a??是首元素(無前驅),a??是尾元素(無后繼);

  • 除?a??和?a??外,每個元素?a?(2≤i≤n-1)?有且僅有一個前驅a???)和一個后繼a???);

  • n=0?時稱為空表(無任何元素)。

兩種核心存儲結構( 暫時只做了解 )

線性表的存儲結構決定了其操作效率,核心分為 “順序存儲” 和 “鏈式存儲” 兩類,二者各有優劣:

對比維度順序存儲結構(順序表)鏈式存儲結構(鏈表)
存儲方式連續的存儲單元依次存儲元素任意存儲單元存儲元素,通過指針 / 引用鏈接邏輯關系
邏輯與物理關系邏輯順序 ≡ 物理順序邏輯順序 ≠ 物理順序(靠指針維護)
訪問效率支持隨機訪問(通過索引?O(1)?定位)僅支持順序訪問(需從表頭遍歷,O(n)
插入 / 刪除效率中間 / 頭部操作需移動元素(O(n)),尾部插入?O(1)僅需修改指針(O(1),前提是找到目標位置)
空間利用率可能存在 “內存碎片”(預分配空間未用完)無碎片,但需額外存儲指針(空間開銷略大)
典型實現數組(如 C 語言數組、Java ArrayList)單鏈表、雙向鏈表、循環鏈表(如 Java LinkedList)

二. 順序表的概念與結構

順序表是線性表的順序存儲結構,核心是用一段地址連續的物理存儲單元依次存儲線性表中的元素,使得元素的 “邏輯順序” 與 “物理存儲順序完全一致”(即第 1 個元素存在第 1 個物理位置,第 2 個元素存在第 2 個物理位置,以此類推)。

2.1 核心概念

順序表本質是 “基于數組的線性表實現”,但相比普通數組,它會額外記錄當前元素個數(避免越界)和數組容量(方便擴容),是對數組的 “結構化封裝”,確保符合線性表的邏輯特征(一對一前驅 / 后繼關系)。

例如:存儲?[1,3,5,7]?的順序表,物理存儲上元素在內存中連續排列,邏輯上?1?的后繼是?33?的后繼是?5,與物理位置順序完全匹配。

2.2 兩種常見結構

根據數組空間的分配方式,順序表分為 “靜態順序表” 和 “動態順序表”,實際開發中動態順序表更常用(避免空間浪費或不足)。

靜態順序表

  • 特點:使用固定大小的數組存儲元素,容量在定義時確定,無法動態調整。
  • 結構定義
    #define MAX_SIZE 100  // 固定容量
    typedef int SLDataType;  // 元素類型(可替換為其他類型)// 靜態順序表結構
    typedef struct SeqList {SLDataType arr[MAX_SIZE];  // 固定大小的數組,存儲元素int size;                  // 當前元素個數(關鍵:記錄有效元素數量)
    } SeqList;
    
  • 缺點:容量固定,若元素個數超過?MAX_SIZE?會溢出;若元素少則浪費內存。

動態順序表

  • 特點:使用動態內存分配的數組(如?malloc/realloc?分配),容量可根據元素個數動態擴容 / 縮容,靈活性更高。
  • 結構定義
    typedef int SLDataType;// 動態順序表結構
    typedef struct SeqList {SLDataType* arr;  // 指向動態分配數組的指針(存儲元素)int size;         // 當前元素個數(有效元素數)int capacity;     // 當前數組的容量(最大可存儲元素數)
    } SeqList;
    
  • 核心優勢:容量按需調整,避免靜態順序表的空間浪費或溢出問題,是實際開發中的主流選擇。

2.3 核心區別對比

對比維度靜態順序表動態順序表
存儲空間分配編譯時固定分配(棧上或全局區)運行時動態分配(堆內存)
容量特性容量固定,不可改變容量可變,可動態擴容 / 縮容
空間利用率可能浪費(容量大于實際需求)利用率高(按需分配)
溢出風險有(元素數超過最大容量時)無(可動態擴容避免溢出)
內存管理復雜度簡單(自動分配和釋放)復雜(需手動分配、擴容和釋放)
實現難度簡單稍復雜(需實現擴容邏輯)

四. 順序表的實現

4.1 順序表的定義

靜態順序表:

#define MAX_SIZE 100  // 固定容量
typedef int SLDataType;  // 元素類型(可替換為其他類型)// 靜態順序表結構
typedef struct SeqList {SLDataType arr[MAX_SIZE];  // 固定大小的數組,存儲元素int size;                  // 當前元素個數(關鍵:記錄有效元素數量)
} SeqList;

動態順序表:

typedef int SLDataType;// 動態順序表結構
typedef struct SeqList {SLDataType* arr;  // 指向動態分配數組的指針(存儲元素)int size;         // 當前元素個數(有效元素數)int capacity;     // 當前數組的容量(最大可存儲元素數)
} SeqList;

4.2 順序表初始化

靜態順序表初始化

void StaticSeqListInit(StaticSeqList* ssl) {ssl->size = 0;  // 只需初始化元素個數為0,數組空間已固定分配
}

動態順序表初始化

void DynamicSeqListInit(DynamicSeqList* dsl) {dsl->data = NULL;dsl->size = 0;dsl->capacity = 0;  // 初始容量為0,或可分配默認初始容量

4.3 動態順序表容量檢查與擴容

// 檢查容量,不足則擴容
void CheckCapacity(DynamicSeqList* dsl) {if (dsl->size == dsl->capacity) {// 計算新容量,初始容量為0則設為4,否則翻倍int newCapacity = dsl->capacity == 0 ? 4 : dsl->capacity * 2;// 重新分配內存SLDataType* newData = (SLDataType*)realloc(dsl->data, newCapacity * sizeof(SLDataType));if (newData == NULL) {perror("realloc failed");exit(EXIT_FAILURE);}dsl->data = newData;dsl->capacity = newCapacity;}
}

4.4 動態順序表插入數據

4.4.1 頭插

//頭插
void SLPushFront(SL* ps, SLdatatype x)
{assert(ps);//ps!=NULL//檢查空間是否足夠SLCheckCapacity(ps);//空間足夠for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];}ps->arr[0] = x;ps->size++;
}

4.4.2 尾插

//尾插
void SLPushBack(SL* ps, SLTDataType x)
{//空間不夠if (ps->size == ps->capacity){//增容int newCapacity = ps->capacity ==0 ? 4 : 2 * ps->capacity;SLTDataType* tmp = (SLTDataType*)realloc(ps->arr, newCapacity*sizeof(SLTDataType));if (tmp = NULL){perror("realloc");exit(1);}ps->arr = tmp;ps->capacity = newCapacity;}//空間足夠ps->arr[ps->size++] = x;//插入完后,size往后走
}

4.4.3 指定位置插入

// 在pos位置插入元素value
int DynamicSeqListInsert(DynamicSeqList* dsl, int pos, SLDataType value) {if (pos < 0 || pos > dsl->size) return -1;CheckCapacity(dsl);  // 自動檢查并擴容// 移動元素for (int i = dsl->size; i > pos; i--) {dsl->data[i] = dsl->data[i-1];}// 插入新元素dsl->data[pos] = value;dsl->size++;return 0;
}

4.5 動態順序表的刪除數據

4.5.1 頭刪

//尾刪
void SLPopBack(SL* ps)
{assert(ps && ps->size);ps->size--;
}

4.5.2 尾刪

//尾刪
void SLPopBack(SL* ps)
{assert(ps && ps->size);ps->size--;
}

4.5.3 刪除指定位置的數據

void  SQdelete(SL* ps, int pos) //刪除第x個數據 這個x是數組的下標
{assert(ps->size > 0 && ps->size > pos);while (ps->size-pos>0){ps->arr[pos] = ps->arr[pos + 1];pos++;}ps->size--;
}

4.5.4 刪除指定的數據

void SQLdex(SL* ps, int x) //刪除查找到的所有x
{int i = 0;while (i < ps->size){if (ps->arr[i] == x){// 元素前移覆蓋要刪除的元素for (int j = i; j < ps->size - 1; j++){ps->arr[j] = ps->arr[j + 1];}ps->size--; // 元素數量減1// 不執行i++,因為下一個元素移動到了當前位置}else{i++; // 只有當沒有刪除元素時,才移動到下一個位置}}
}

4.6 查找指定數據


void SLFind(SL* ps, SLdate x)
{for (int i = 0;i < ps->size;i++){if (ps->arr[i] == x){printf("找到了 順序表第%d個",i+1);printf("\n");}}
}

4.6?動態順序表銷毀

// 必須手動釋放動態分配的內存,避免內存泄漏
void DynamicSeqListDestroy(DynamicSeqList* dsl) {free(dsl->data);dsl->data = NULL;dsl->size = 0;dsl->capacity = 0;
}

示例運行結果如下:

五. 優缺點分析

靜態順序表

  • 優點

    • 實現簡單,無需處理復雜的內存分配邏輯

    • 訪問速度快,無需額外的指針操作

    • 棧上分配內存,自動釋放,不會造成內存泄漏

  • 缺點

    • 容量固定,無法適應數據量動態變化的場景

    • 可能造成內存空間浪費(當實際元素遠少于最大容量時)

    • 存在溢出風險(當元素數量超過最大容量時)

動態順序表

  • 優點

    • 容量可動態調整,能靈活適應數據量變化

    • 內存利用率高,按需分配空間

    • 不存在固定容量導致的溢出問題

  • 缺點

    • 實現相對復雜,需要處理擴容、內存分配等問題

    • 擴容時可能產生內存碎片

    • 需手動管理內存,若操作不當易造成內存泄漏

    • 擴容過程中需要拷貝數據,可能影響性能

六. 適用場景選擇

  1. 靜態順序表適用場景

    • 數據量已知且固定不變的情況

    • 對內存管理要求簡單,不希望手動處理內存分配的場景

    • 嵌入式系統、單片機等內存資源受限且數據量固定的環境

  2. 動態順序表適用場景

    • 數據量不確定,需要動態增減的情況

    • 對內存利用率要求較高的場景

    • 大部分通用編程場景,如實現動態數組、列表等數據結構

七. 總結

靜態順序表和動態順序表都是基于數組的線性表實現,核心區別在于存儲空間是否可動態調整。靜態順序表簡單直接但缺乏靈活性,動態順序表靈活高效但實現稍復雜。

在實際開發中,動態順序表應用更為廣泛,因為它能更好地適應數據量動態變化的需求。了解兩者的特點和差異,有助于根據具體場景選擇合適的實現方式,從而優化程序性能和內存使用。

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

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

相關文章

[Maven 基礎課程]Maven 是什么

Maven 的官方網站&#xff1a;https://maven.apache.org/ 來自 Maven 官網的對于 Maven 是什么的描述&#xff1a; Apache Maven is a build tool for Java projects. Using a project object model (POM), Maven manages a project’s compilation, testing, and documentat…

【MATLAB例程】三維組合導航,濾波使用EKF,帶嚴格的慣導推算、雅克比求解函數,圖像對比濾波前后的速度、位置、姿態

文章目錄程序介紹系統建模濾波框架仿真設置性能對比代碼優點運行結果MATLAB源代碼程序介紹 本程序實現了 三維狀態量的擴展卡爾曼濾波&#xff08;EKF&#xff09;組合導航仿真&#xff0c;采用嚴格的15維誤差狀態模型&#xff0c;狀態向量包括&#xff1a; x[pxpypzvxvyvz?θ…

港資企業在大陸,如何靠 SD-WAN 專線暢連香港?

在當前市場形勢下&#xff0c;港資企業在大陸的業務布局不斷拓展&#xff0c;企業間訪問香港總部系統以及香港員工到內陸出差時訪問相關系統&#xff0c;成為日常運營的高頻需求。然而&#xff0c;網絡問題卻常常阻礙業務的順暢開展&#xff0c;基于 SD-WAN 專線的到香港加速網…

并發編程——08 Semaphore源碼分析

1 概述Semaphore 是基于 AQS CAS 實現的&#xff0c;可根據構造參數的布爾值&#xff0c;選擇使用公平鎖&#xff0c;還是非公平鎖。Semaphore 默認使用非公平鎖&#xff1b;2 構造函數 // AQS的實現 private final Sync sync;// 默認使用非公平鎖 public Semaphore(int permi…

Java全棧開發面試實戰:從基礎到微服務的深度解析

Java全棧開發面試實戰&#xff1a;從基礎到微服務的深度解析 一、面試開場 面試官&#xff08;中年工程師&#xff0c;穿著休閑但專業&#xff09;&#xff1a;你好&#xff0c;我是李工&#xff0c;今天來聊一下你的技術背景。你之前在XX科技做全棧開發&#xff0c;對吧&#…

CVPR深度學習論文創新合集拆解:模型訓練速度算提升

關注gongzhonghao【CVPR頂會精選】大語言模型擴散Transformer的深度融合&#xff0c;讓文本到圖像生成更精準、細節更豐富&#xff1b;同時&#xff0c;專家軌跡正則化深度強化學習在自動對焦中的穩定加速表現&#xff0c;也展示了深度學習與軌跡建模結合的潛力。這樣的組合正在…

【智能體】零代碼學習 Coze 智能體(2)創建智能體的完整步驟

歡迎關注【AGI使用教程】 專欄 【智能體】零代碼學習 Coze 智能體&#xff08;1&#xff09; 【智能體】零代碼學習 Coze 智能體&#xff08;2&#xff09; 【智能體】零代碼學習 Coze 智能體&#xff08;1&#xff09;1、登錄 Coze 平臺2、創建智能體3、智能體編排頁面4、編寫…

WPF和WinFrom區別

WPF 總結Windows Presentation Foundation (WPF) 是微軟開發的一個用于構建 Windows 桌面應用程序的用戶界面框架。它基于 .NET Framework&#xff0c;提供豐富的圖形、動畫和數據綁定功能&#xff0c;幫助開發者創建現代化、高性能的應用程序。以下是其核心要點總結&#xff1…

數據庫原理及應用_數據庫基礎_第3章數據庫編程_常用系統函數

前言 "<數據庫原理及應用>(MySQL版)".以下稱為"本書"中3.1.2節內容 引入 數據庫常用系統函數的分析.上一篇帖子分析了,數據庫函數需要看看能否被C語言函數替代 1.字符串函數 1)計算字符串字符數的函數和字符串長度的函數 語法: CHAR_LENGTH(str)…

回歸問題的損失函數

簡單來說&#xff0c;?在回歸問題中&#xff0c;最常用的損失函數是均方誤差&#xff08;MSE, Mean Squared Error&#xff09;和平均絕對誤差&#xff08;MAE, Mean Absolute Error&#xff09;?。它們衡量的都是模型預測值&#xff08;?&#xff09;與真實值&#xff08;y…

吳恩達機器學習(四)

一、神經網絡神經元模擬邏輯單元&#xff1a;神經網絡簡單模型&#xff1a;神經網絡中的前向傳播過程&#xff1a;依次計算激活項&#xff0c;從輸入層到隱藏層再到輸出層的過程。樣例&#xff1a;多元分類&#xff1a;

【重學 MySQL】九十三、MySQL的字符集的修改與底層原理詳解

【重學 MySQL】九十三、MySQL的字符集的修改與底層原理詳解一、字符集修改方法1. **配置文件修改**2. **SQL命令修改**3. **數據遷移方案**二、底層原理與注意事項1. **字符集與排序規則**2. **存儲與性能影響**3. **數據一致性風險**三、常見問題解決1. **亂碼問題**2. **性能…

pdf 轉圖片工具實現

一、安裝 sudo yum install poppler-utils pdftoppm -v pdftoppm -png -r 300 a.pdf /tmp/page 運行效果&#xff1a; PDF轉圖片工具 - 在線PDF轉PNG/JPG/TIFF轉換器 | 免費在線工具 后臺實現&#xff1a; using System.Diagnostics; using System.IO.Compression;namespac…

Zynq開發實踐(FPGA之輸入、輸出整合)

【 聲明&#xff1a;版權所有&#xff0c;歡迎轉載&#xff0c;請勿用于商業用途。 聯系信箱&#xff1a;feixiaoxing 163.com】fpga開發的時候習慣上先把功能拆分成若干個模塊。針對這些模塊&#xff0c;一個一、個實現好之后&#xff0c;再用wire連接即可。這一點有點像軟件編…

【Linux基礎】深入理解計算機啟動原理:MBR主引導記錄詳解

目錄 引言 1 硬盤分區初始化概述 1.1 為什么需要硬盤分區 1.2 硬盤分區格式的發展 1.3 分區初始化的基本流程 2 MBR詳解 2.1 MBR的定義與位置 2.2 MBR的結構詳解 2.3 分區表結構詳解 2.4 MBR的工作原理 2.5 MBR的引導程序 3 MBR的局限性 3.1 硬盤容量限制 3.2 分…

Linux 線程同步

線程同步 由于線程共享內存&#xff0c;訪問共享數據&#xff08;全局變量、堆內存&#xff09;必須進行同步&#xff0c;以防止競態條件&#xff08;Race Conditions&#xff09;導致數據不一致或程序崩潰。 子線程沒有獨立的地址空間&#xff0c;數據通常是共享的&#xff1b…

世界模型的典型框架與分類

1.概述 人類和動物智能的一個重要方面是我們對世界的內部模型。我們使用這個模型來預測我們的行為將如何影響我們的環境&#xff0c;預測未來的事件&#xff0c;并計劃復雜的行動序列以實現目標。當前大多數機器學習研究都集中在被動理解數據的模型上&#xff0c;例如圖像分類…

【Day 35】Linux-Mysql錯誤總結

&#xff08;一&#xff09;MySQL 基礎操作與服務故障類 連接層錯誤&#xff08;客戶端與服務器的連接建立失敗&#xff09; 解決 socket 路徑、文件存在性及服務可用性問題。 1、MySQL 客戶端連接失敗&#xff08;報錯 “Cant connect to local MySQL server throgh socket…

MYSQL速通(2/5)

六、多表查詢1、多表關系①、一對多&#xff08;多對一&#xff09;舉例&#xff1a;一個部門對多個員工實現&#xff1a;多的那邊建立外鍵&#xff0c;指向一的那邊的主鍵②、多對多舉例&#xff1a;一個學生可選多門課&#xff0c;一門課可被多個學生選實現&#xff1a;建立中…

CRM、ERP、HRP系統有啥區別?

要理解CRM、ERP、HRP系統&#xff0c;需先明確三者的核心定位&#xff08;聚焦客戶、企業全資源、特定領域資源&#xff09;&#xff0c;再從管理范圍、目標、用戶等維度區分。以下是詳細解析&#xff1a; 一、各系統核心定義與核心模塊 1. CRM系統&#xff1a;客戶關系管理系統…