【第二節】C/C++數據結構之線性表

目錄

一、線性表基本說明

1.1 基本概念

1.2 抽象數據類型

1.3 存儲結構

1.4 插入與刪除的區別

1.5 順序存儲和鏈式存儲的優缺點

二、鏈表

2.1 基本概念

2.2 抽象數據類型

2.3 單鏈表的定義

2.4 單鏈表的基本操作

2.5 單鏈表模板形式的類定義與實現

三、單向循環鏈表

四、雙鏈表、雙向循環鏈表


一、線性表基本說明

1.1 基本概念

????????線性表,零個或多個數據元素的有限序列稱為線性表,例如一個字符串就是一個線性表比如一個結構體數組也是一個線性表。

1.2 抽象數據類型

ADT 線性表(List)
Data
除第一個元素外,每一個元素有且只有一個直接前驅元素,除了最后一個元素外,每個元素有且只有一個直接后繼元素,數據元素之間的關系是一對一的關系
Operation
初始化操作,建立一個空的線性表
若線性表為空,返回true,否則返回false
將線性表清空
將線性表中的第i個位置元素值返回給e在線性表中查找與給定值e相等的元素,成功返回序號,否則返回0在線性表中的第i個位置中插入新元素
在線性表中刪除第i個位置的元素,并用e返回其值
返回線性表L的元素個數
endADT

1.3 存儲結構

線性表的順序存儲

????????線性表的順序存儲結構,是指使用一段地址連續的存儲單元依次存儲線性表的數據元素。這種存儲方式通常通過數組(Array)來實現,其中數組的每個元素都對應線性表中的一個數據元素。

????????在數組中,數據元素按照其在線性表中的邏輯順序存儲,即第一個數據元素存儲在數組的第一個位置,第二個數據元素存儲在第二個位置,依此類推。這種存儲方式使得我們可以通過數組的索引直接訪問線性表中的任何數據元素,而不需要遍歷整個線性表。

????????需要注意的是,數組的總長度(即數據空間的總長度)并不一定等于線性表的長度。線性表的長度是指線性表中實際存儲的數據元素個數,而數組的長度是數組中可以存儲的最大數據元素個數。因此,數組的長度通常大于線性表的長度,以便在需要時可以動態擴展。

????????在實際編程中,我們通常會使用動態數組(Dynamic Array)來實現線性表的順序存儲結構,以便在需要時可以動態調整數組的大小。例如,當線性表的長度超過數組的長度時,可以創建一個新的更大的數組,并將原數組中的數據元素復制到新數組中。

線性表的鏈式存儲

????????線性表的鏈式存儲結構,是指使用鏈表(Linked List)來存儲線性表的數據元素。在鏈式存儲結構中,每個數據元素都包含一個數據項和一個指向下一個數據元素的指針。這種存儲方式可以靈活地進行插入和刪除操作,而不需要移動大量的數據。

????????鏈式存儲結構的優點在于,當需要插入或刪除元素時,只需要修改相關節點的指針,而不需要移動大量的數據。因此,鏈式存儲結構在執行插入和刪除操作時,通常比順序存儲結構更高效。

????????然而,鏈式存儲結構也有其缺點。由于每個數據元素都包含一個指針,因此存儲空間的利用率不如順序存儲結構高。此外,鏈式存儲結構在執行查找操作時,需要從頭開始遍歷鏈表,直到找到目標元素或到達鏈表的末尾。因此,如果需要頻繁地執行查找操作,順序存儲結構可能更適合。

????????總的來說,選擇使用順序存儲結構還是鏈式存儲結構,取決于具體的應用場景。如果需要頻繁地執行插入和刪除操作,并且數據量不大,那么鏈式存儲結構可能更適合。如果需要頻繁地執行查找操作,并且數據量較大,那么順序存儲結構可能更適合。

1.4 插入與刪除的區別

順序線性表的插入與刪除:
在順序存儲結構下,線性表在插入新數據前需要將其插入點后面的數據依次后移一個單位,以空出位置讓新數據插入
在順序存儲結構下,線性表在刪除數據后需要將其刪除點后面的數據依次前移一個單位,以補足刪除后空出位置

鏈式線性表的插入與刪除:
當我們想在鏈表中插入一個新數據的時候,只需要申請一段內存空間,然后將其前一個元素的指針指向自己,再將自己的指針指向下一個元素即可,無需操作其他元素
當我們想在鏈表中刪除一個節點時,只需要將前一個節點指向后一個節點,并釋放掉自己即可

1.5 順序存儲和鏈式存儲的優缺點

順序存儲和鏈式存儲是兩種基本的數據結構,它們在存儲和訪問數據元素時各有優缺點。

順序存儲(順序結構)

  • 優點:順序存儲的優點在于存儲效率高,存取速度快。由于數據元素存儲在連續的內存空間中,因此可以通過下標直接訪問任何元素,無需遍歷整個數據結構。

  • 缺點:順序存儲的缺點在于空間大小固定,不易擴充。一旦定義了存儲空間的大小,就無法改變。此外,在插入或刪除元素時,需要移動大量元素,這會降低效率。

鏈式存儲(鏈式結構)

  • 優點:鏈式存儲的優點在于空間利用率高,可以動態分配和釋放存儲空間。此外,在插入和刪除元素時,只需要修改鏈接指針,而不需要移動數據元素,因此效率較高。

  • 缺點:鏈式存儲的缺點在于存取元素時需要順序查找,因此存取效率不高。此外,由于每個元素都包含一個指針,因此存儲空間的利用率不如順序存儲高。

在實際應用中,選擇順序存儲還是鏈式存儲取決于具體的應用需求。如果需要頻繁地插入和刪除元素,并且數據量不大,那么鏈式存儲可能更適合。如果需要頻繁地查找元素,并且數據量較大,那么順序存儲可能更適合。

二、鏈表

2.1 基本概念

????????鏈表是一種物理存儲單元上非連續、非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。鏈表由一系列結點(鏈表中每一個元素稱為結點)組成,結點可以在運行時動態生成。
????????每個結點包括兩個部分:一個是存儲數據元素的數據域,另一個是存儲下一個結點地址
的指針域循環鏈表是另一種形式的鏈式存貯結構。它的特點是表中最后一個結點的指針域指向頭結點,整個鏈表形成一個環。

2.2 抽象數據類型

ADT 鏈表(List)
Data
除第一個元素外,每一個元素有且只有一個直接前驅元素,除了最后一個元素外,每個元素有且只有一個直接后繼元素,數據元素之間的關系是一對一的關系
Operation
初始化操作,建立一個空的鏈表
若鏈表為空,返回true,否則返回false
將鏈表清空
將鏈表中的第i個位置元素值返回給e
在鏈表中查找與給定值e相等的元素,成功返回序號,否則返回0
在鏈表中的第i個位置中插入新元素
在鏈表中刪除第i個位置的元素,并用e返回其值
返回鏈表的元素個數
endADT

2.3 單鏈表的定義

????????鏈表中最簡單的一種是單向鏈表,它包含兩個域,一個數據域和一個指針域。這個鏈接指向列表中的下一個節點,而最后一個節點則指向一個空值。
????????單向鏈表通常由一個頭指針(head),用于指向鏈表頭。單向鏈表有一個尾結點,該結點的指針部分指向一個空結點(NULL)。

2.4 單鏈表的基本操作

對鏈表的基本操作有:
創建鏈表是指,從無到有地建立起一個鏈表,即往空鏈表中依次插入若干結點,并保持結點之間的前驅和后繼關系。
檢索操作是指,按給定的結點索引號或檢索條件,查找某個結點。如果找到指定的結點則稱為檢索成功;否則,稱為檢索失敗。
插入操作是指,在結點之間插入一個新的結點,使線性表的長度增1。
刪除操作是指,刪除結點ki,使線性表的長度減1
打印輸出。

2.5 單鏈表模板形式的類定義與實現

代碼示例:

#include <iostream>// 定義鏈表節點結構體
template <typename T>
struct Node {T data;Node* next;Node(const T& value) : data(value), next(nullptr) {}
};// 單鏈表類模板
template <typename T>
class SingleLinkedList {
private:Node<T>* head;int size;public:SingleLinkedList() : head(nullptr), size(0) {}~SingleLinkedList() {while (head != nullptr) {Node<T>* temp = head;head = head->next;delete temp;}}// 插入元素到鏈表頭部void push_front(const T& value) {Node<T>* newNode = new Node<T>(value);newNode->next = head;head = newNode;size++;}// 刪除鏈表頭部元素void pop_front() {if (head != nullptr) {Node<T>* temp = head;head = head->next;delete temp;size--;}}// 查找元素Node<T>* find(const T& value) {Node<T>* current = head;while (current != nullptr) {if (current->data == value) {return current;}current = current->next;}return nullptr; // 未找到返回nullptr}// 刪除指定元素void remove(const T& value) {if (head == nullptr) return;if (head->data == value) {pop_front();return;}Node<T>* current = head;while (current->next != nullptr) {if (current->next->data == value) {Node<T>* temp = current->next;current->next = current->next->next;delete temp;size--;return;}current = current->next;}}// 獲取鏈表大小int getSize() const {return size;}// 顯示鏈表元素void display() const {Node<T>* current = head;while (current != nullptr) {std::cout << current->data << " ";current = current->next;}std::cout << std::endl;}
};// 示例使用
int main() {SingleLinkedList<int> list;// 插入元素list.push_front(10);list.push_front(20);list.push_front(30);list.display(); // 輸出: 30 20 10// 刪除元素list.pop_front();list.display(); // 輸出: 20 10// 查找元素Node<int>* foundNode = list.find(20);if (foundNode != nullptr) {std::cout << "Found: " << foundNode->data << std::endl;} else {std::cout << "Not found" << std::endl;}// 刪除指定元素list.remove(10);list.display(); // 輸出: 20// 獲取鏈表大小std::cout << "Size: " << list.getSize() << std::endl; // 輸出: Size: 1return 0;
}

????????在這個代碼中,我們定義了一個Node結構體模板來表示鏈表中的節點,每個節點包含一個數據項和一個指向下一個節點的指針。SingleLinkedList類模板定義了單鏈表的主要操作,包括構造函數、析構函數、push_front(在鏈表前端插入元素)、pop_front(從鏈表前端刪除元素)、find(查找元素)、remove(刪除指定元素)、getSize(獲取鏈表大小)和display(顯示鏈表中的所有元素)。

????????在main函數中,我們創建了一個SingleLinkedList<int>對象,并進行了一些操作,以展示如何使用這個模板類。這些操作包括插入元素、刪除元素、查找元素、顯示鏈表和獲取鏈表大小。

三、單向循環鏈表

四、雙鏈表、雙向循環鏈表

????????單向鏈表、單向循環鏈表、雙向鏈表和雙向循環鏈表都是鏈表數據結構的不同類型,它們在結構和操作上有所不同。以下是這些鏈表類型之間的主要區別:

  1. 單向鏈表:

    • 每個節點包含一個數據項和一個指向下一個節點的指針。

    • 鏈表的末尾節點的指針通常設置為NULL,表示鏈表的結束。

    • 單向鏈表不是循環的,它只能從頭到尾遍歷。

  2. 單向循環鏈表:

    • 與單向鏈表類似,但鏈表的最后一個節點的指針指向鏈表的第一個節點,形成一個循環。

    • 這種類型的鏈表可以從任何節點開始遍歷,并且可以無限期地繼續。

  3. 雙向鏈表:

    • 每個節點包含一個數據項、一個指向下一個節點的指針和一個指向前一個節點的指針。

    • 鏈表的第一個節點的前向指針通常設置為NULL,表示鏈表的開始。

    • 鏈表的最后一個節點的后向指針通常設置為NULL,表示鏈表的結束。

    • 雙向鏈表可以從任意節點開始向前或向后遍歷。

  4. 雙向循環鏈表:

    • 與雙向鏈表類似,但鏈表的第一個節點的后向指針指向鏈表的最后一個節點,形成一個循環。

    • 鏈表的最后一個節點的前向指針指向鏈表的第一個節點,形成另一個循環。

    • 雙向循環鏈表可以從任意節點開始向前或向后遍歷,并且可以無限期地繼續。

????????選擇哪種鏈表類型取決于你的具體需求。例如,如果你需要頻繁地在鏈表的兩端插入和刪除元素,雙向鏈表可能是一個好的選擇。如果你需要在鏈表中進行循環遍歷,那么單向循環鏈表或雙向循環鏈表可能更適合。

關于它們的更具體實現和應用后面再詳細講解。

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

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

相關文章

項目迭代中新老邏輯切換入口

前言 ? 日常我們在項目開發中經常會進行項目迭代&#xff0c;比如說開發初期設定的代碼邏輯根據功能需求迭代逐漸發現越來越難用&#xff0c;或者改動是對整體較大時&#xff0c;往往會進行專項處理&#xff0c;對這個邏輯進行改造。 ? 那么就會涉及到原先被調用方切換接口…

成功解決“ModuleNotFoundError: No module named ‘tensorflow_datasets‘”錯誤的全面指南

成功解決“ModuleNotFoundError: No module named ‘tensorflow_datasets’”錯誤的全面指南 在Python編程和深度學習項目中&#xff0c;tensorflow_datasets&#xff08;通常簡稱為tfds&#xff09;是一個非常重要的庫&#xff0c;它提供了大量現成的數據集&#xff0c;方便…

終于來啦!Stable Diffusion 3將在6月12日正式開源

6月3日晚&#xff0c;著名開源大模型平臺Stability AI的聯合首席執行官Christian Laforte&#xff0c;在AMD的產品發布會上宣布&#xff0c;文生圖模型 Stable Diffusion 3將于6月12日在Hugging Face開源權重。 本次開源的是Stable Diffusion 3的Medium模型&#xff0c;有20億…

武漢盛勢啟創科技攜手三品軟件 EDM系統助力企業圖文檔數字化

客戶簡介 武漢盛勢啟創科技有限公司&#xff08;以下簡稱“盛世啟創”&#xff09;是一家專注于新能源汽車零部件領域的科技型企業&#xff0c;其主要業務涵蓋新能源汽車三電系統智能傳感器、智能座艙及線控底盤控制器的芯片開發、硬件設計、嵌入式系統開發。以及相關產品的生產…

C++第二十三彈---深入理解STL中list的使用

?個人主頁&#xff1a; 熬夜學編程的小林 &#x1f497;系列專欄&#xff1a; 【C語言詳解】 【數據結構詳解】【C詳解】 目錄 1、list的介紹 2、list的使用 2.1、構造函數 2.2、賦值操作符重載 2.3、迭代器使用 2.4、容量操作 2.5、元素訪問 2.6、修改操作 2.7、其…

從0開始學人工智能測試節選:Spark -- 結構化數據領域中測試人員的萬金油技術(三)

分布式計算原理 分布式計算的原理總結一句話就是&#xff1a;分而治之。 把數據分片&#xff0c;存在不同的機器中&#xff0c;解決數據存儲的壓力。客戶端和服務端之間通過相關協議來自動的完成在不同的機器之間進行數據的存取&#xff0c;用戶并不感知數據的物理存儲結構。 用…

UIKit之App界面Demo

需求 實現簡單的APP界面 功能&#xff1a; 實現滾動實現上層、下層橫欄滾動時穿透效果&#xff08;永遠浮在表面&#xff0c;不跟著滾動&#xff09;。暫用UIView代替&#xff0c;還沒學Bar。 分析&#xff1a; 知識點&#xff1a; 實現鼠標拖動的上下滾動&#xff1a;當…

小紅書前端2輪面試期望22K,全程問低代碼設計

一面&#xff08;通過&#xff09; 1、好&#xff0c;那我們開始把&#xff0c;先簡單介紹一下自己的一個經歷&#xff0c;以及自己有亮點的項目&#xff1f;balabala 2、你可以這樣介紹&#xff1a;在這里邊主要負責哪幾個項目&#xff0c;哪些項目是比較有亮點的&#xff0…

python用PyPDF2函數庫方法對pdf文件切割

煩透了那些軟件動不動就要收費&#xff0c;于是自己嘗試碼程序處理pdf分割。 由于PyPDF2更新到了3.0之后&#xff0c;之前網上的舊代碼無法使用&#xff0c;查了半天沒出準譜&#xff0c;結果百度AI生成了代碼&#xff0c;一試&#xff0c;成了&#xff01; 果然&#xff0c;…

代碼隨想錄-算法訓練營day60【單調棧03:柱狀圖中最大的矩形】

代碼隨想錄-035期-算法訓練營【博客筆記匯總表】-CSDN博客 第十章 單調棧part03有了之前單調棧的鋪墊,這道題目就不難了。 ● 84.柱狀圖中最大的矩形https://programmercarl.com/0084.%E6%9F%B1%E7%8A%B6%E5%9B%BE%E4%B8%AD%E6%9C%80%E5%A4%A7%E7%9A%84%E7%9F%A9%E5%BD%A2.htm…

智享直播(三代)2024年:打造24/7實景無人直播,引領年輕資產創業新紀元!

在21世紀的數字化浪潮中&#xff0c;直播行業以其獨特的魅力和無限的可能性&#xff0c;正在全球范圍內掀起一場前所未有的( keJ0277 )創業革命。而在這場革命中&#xff0c;智享直播&#xff08;三代&#xff09;以其創新的技術理念和前瞻的戰略布局&#xff0c;立志于2024年打…

怎么用電腦錄制視頻?小白也能快速上手

隨著網絡技術的發展&#xff0c;電腦錄制視頻已經成為了許多人的日常需求&#xff0c;無論是游戲玩家想錄制自己的精彩操作&#xff0c;還是上班族需要錄制屏幕演示&#xff0c;一款好用的錄屏軟件變得尤為重要。可是你知道怎么用電腦錄制視頻嗎&#xff1f;本文將介紹兩種電腦…

I2C通信協議

I2C通信協議 項目要求是&#xff0c;通過通信線&#xff0c;是實現單片機讀寫外掛模塊寄存器的功能&#xff0c;至少實現&#xff0c;在指定位置寫寄存器和在指定位置讀寄存器&#xff0c;實現了讀寫寄存器&#xff0c;就實現對模塊的控制。 MPU6050&#xff0c;OLED&#xf…

【ARM】Fusa Compiler 6.16 LTS的安全認證報告獲取

【更多軟件使用問題請點擊億道電子官方網站】 1、 文檔目標 了解ARM的Arm Compiler for Embedded FuSa 6.16 LTS的安全認證證書和報告的獲取 2、 問題場景 對于使用了ARM DS Gold/Platinum、MDK pro或者Arm Compiler for Embedded FuSa 6.16 LTS產品的客戶。在對于最終的產品…

生產問題排查:springboot項目啟動時注冊nacos失敗或運行時從nacos閃退

文章目錄 一、引出問題二、解決方案1、使用actuator健康檢查2、項目啟動時判斷nacos是否正常連接3、k8s設置探針 一、引出問題 生產項目是用k8s部署的&#xff0c;最近經常遇到啟動時注冊不到nacos&#xff08;查找nacos的host地址找不到&#xff09;&#xff0c;或者運行的好…

有文字轉語音真人發聲嗎?這5個配音工具堪比真人配音

青春是一首永不老去的歌&#xff0c;它鐫刻在生命的唱片上&#xff0c;永不退色。 每當我們聽到那些熟悉的旋律&#xff0c;心中總會涌起一股暖流&#xff0c;仿佛回到了那個充滿活力和夢想的年代。借助現代科技的力量&#xff0c;我們可以通過文字轉語音軟件&#xff0c;讓這…

.NET集成DeveloperSharp實現圖片的裁剪、縮放、與加水印

&#x1f3c6;作者&#xff1a;科技、互聯網行業優質創作者 &#x1f3c6;專注領域&#xff1a;.Net技術、軟件架構、人工智能、數字化轉型、DeveloperSharp、微服務、工業互聯網、智能制造 &#x1f3c6;歡迎關注我&#xff08;Net數字智慧化基地&#xff09;&#xff0c;里面…

Apache Doris 基礎 -- 數據表設計(表索引)

1、索引概述 索引用于幫助快速過濾或搜索數據。目前&#xff0c;Doris支持兩種類型的索引:內置智能索引和用戶創建的二級索引。 內置智能索引 排序鍵和前綴索引:Apache Doris基于排序鍵以有序的方式存儲數據。它為每1024行數據創建一個前綴索引。索引中的鍵是當前1024行組的…

github搭建個人博客

準備工作 windows安裝nodejs windows安裝git windows安裝hexo 擁有gitee個人賬戶 配置信息 通過gitee創建博客倉庫 登錄gitee平臺&#xff0c;進入主界面&#xff0c;右側加號&#xff0c;新建倉庫&#xff0c;注意&#xff1a;倉庫名稱和gitee用戶名稱一致 生成/添加 SSH 公…

初級網絡工程師之入門到入獄(一)

本文是我在學習過程中記錄學習的點點滴滴&#xff0c;目的是為了學完之后鞏固一下順便也和大家分享一下&#xff0c;日后忘記了也可以方便快速的復習。 網絡工程師從入門到入獄 前言一、交換機二、路由器三、DHCP&#xff08;動態主機配置協議&#xff09;四、路由器配置 DHCP自…