數據結構 - C/C++ - 鏈表

目錄

結構特性

內存布局

結構樣式

結構拓展

單鏈表

結構定義

節點關聯

插入節點

刪除節點

常見操作????????

雙鏈表

環鏈表

結構容器

結構設計


結構特性

  • 線性結構的存儲方式

    • 順序存儲 - 數組

    • 鏈式存儲 - 鏈表

  • 線性結構的鏈式存儲是通過任意的存儲單元來存儲線性表當中的數據元素。

    • 存儲單元可以是連續的也可以是不連續的。

    • 線性結構的順序存儲中每個元素只需要存儲其元素數據即可。

    • 線性結構的鏈式存儲除了存儲元素數據外,還有存儲后繼元素的內存地址。

  • 結構概念

    • 節點(Node) - 鏈式存儲結構中的元素單位為節點,通常由數據域和指針域共同組成。

    • 數據域(Data) - 存儲節點值。

    • 指針域(Next) - 存儲節點指向的下一個節點的內存地址。

    • 頭節點(Head) - 鏈表頭部節點。

    • 尾節點(Tail) - 鏈表的結束位置節點,其指針域指向NULL,表示了鏈表結束。

內存布局

  • 鏈式存儲

  • 節點樣式

結構樣式

  • 單鏈表

    • 每個節點只有一個指針域,指向下一個節點。

  • 雙向鏈表

    • 每個節點存在兩個指針域,一個指向前節點,一個指向后節點。

  • 循環鏈表

    • 鏈表尾部節點指向頭節點。

結構拓展

單鏈表

結構定義
typedef struct ListNode
{//數據域int value;//指針域ListNode* Next;//賦值域ListNode(int num) : value(num), Next(nullptr){}
};
節點關聯
	ListNode* Node1 = new ListNode(1);ListNode* Node2 = new ListNode(2);ListNode* Node3 = new ListNode(3);ListNode* Node4 = new ListNode(4);ListNode* Node5 = new ListNode(5);Node1->Next = Node2;Node2->Next = Node3;Node3->Next = Node4;Node4->Next = Node5;Node5->Next = NULL;
插入節點
void Insert(ListNode* Cur, ListNode* Node)
{ListNode* Temp = Cur->Next;Cur->Next = Node;Node->Next = Temp;
}
刪除節點
void Remove(ListNode* Cur)
{//當前節點.Next = 當前節點.下一個節點.下一個節點ListNode* Node6 = Cur->Next;ListNode* Node3 = Node6->Next;Cur->Next = Node3;delete Node6;
}
常見操作????????
	//遍歷節點int nIndex = 0;ListNode* pTemp = Node1;while (pTemp != NULL){printf("Index -> [%d] -> Data -> [%d] \r\n", nIndex, pTemp->value);++nIndex;pTemp = pTemp->Next;}

雙鏈表

#include <iostream>class ListNode
{
public://數據域int value;//指針域ListNode* Prev;ListNode* Next;//賦值域ListNode(int Num): value(Num), Prev(nullptr), Next(nullptr) {}
};//追加節點
void Append(ListNode* Head , int val)
{ListNode* newNode = new ListNode(val);ListNode* tempNode = Head;while (tempNode->Next != NULL){tempNode = tempNode->Next;}tempNode->Next = newNode;newNode->Prev = tempNode;newNode->Next = NULL;}//添加節點
void Insert(ListNode* Head, int val)
{ListNode* newNode = new ListNode(val);ListNode* HeadNext = Head->Next;Head->Next = newNode;newNode->Prev = Head;newNode->Next = HeadNext;HeadNext->Prev = newNode;/*Node2.Next = NodeCC;NodeCC.Prev = Node2;NodeCC.Next = Node3;Node3.Prev = NodeCC;*/}//移除節點
void Remove(ListNode* Head)
{ListNode* tempNode = Head;while (tempNode->Next != NULL){tempNode = tempNode->Next;}tempNode->Prev->Next = NULL;delete tempNode;
}//刪除節點
void Erase(ListNode* Head)
{//當前節點.上一個.下一個 = 當前節點.下一個//當前節點.下一個.上一個 = 當前節點.上一個Head->Prev->Next = Head->Next;Head->Next->Prev = Head->Prev;
}int main()
{ListNode* Node1 = new ListNode(1);ListNode* Node2 = new ListNode(2);ListNode* Node3 = new ListNode(3);ListNode* Node4 = new ListNode(4);ListNode* Node5 = new ListNode(5);Node1->Prev = NULL;Node1->Next = Node2;Node2->Prev = Node1;Node2->Next = Node3;Node3->Prev = Node2;Node3->Next = Node4;Node4->Prev = Node3;Node4->Next = Node5;Node5->Prev = Node4;Node5->Next = NULL;Append(Node1 ,0xCC);Insert(Node2 ,0xDD);Remove(Node1);Erase(Node3);return 0;
}

環鏈表

#include <iostream>class ListNode
{
public://數據域int value;//指針域ListNode* Next;//賦值域ListNode(int Num) : value(Num), Next(nullptr){}
};int main()
{ListNode* Node1 = new ListNode(1);ListNode* Node2 = new ListNode(2);ListNode* Node3 = new ListNode(3);ListNode* Node4 = new ListNode(4);ListNode* Node5 = new ListNode(5);Node1->Next = Node2;Node2->Next = Node3;Node3->Next = Node4;Node4->Next = Node5;Node5->Next = Node1;ListNode* tempNode = Node1;do{printf("%d \r\n", tempNode->value);tempNode = tempNode->Next;} while (tempNode != Node1);return 0;
}

結構容器

  • std:list

  • 構造函數

    • 默認構造函數

    • 有參構造函數

    • 拷貝構造函數

    • 列表構造函數

    • 默認析構函數

  • 大小函數

    • 節點數量

    • 是否為空

    • 清空數據

  • 功能函數

    • 插入元素

    • 頭部插入

    • 尾部插入

    • 指定插入

    • 刪除元素

    • 修改元素

    • 訪問元素

結構設計

#include <iostream>class Node
{
public://數據域int value;//指針域Node* Prev;Node* Next;//賦值域Node(int Num, Node* p = nullptr, Node* n = nullptr) : value(Num), Prev(p), Next(n) {}
};class List
{
public://頭部節點Node* Head;//尾部節點Node* Tail;//節點數量size_t size;public://默認構造List();//有參構造List(int Count, int value);//拷貝構造List(const List& ref);//列表構造List(std::initializer_list<int> initList);//默認析構~List();public://是否為空bool IsEmpty();//節點數量size_t GetSize();//清空容器void Clear();public://尾部插入void Push_Back(int value);//頭部插入void Push_Front(int value);//指定插入void Insert(int InsertValue, int value);//尾部移除void Pop_Back();//頭部移除void Pop_Front();//按值匹配void Remove(int value);//查找節點bool Find(int value);public://賦值運算符List& operator=(const List & other);//下標運算符int& operator[](int Index);};std::ostream& operator<<(std::ostream& output, const List& obj);List::List()
{this->Head = nullptr;this->Tail = nullptr;this->size = 0;
}List::List(int Count, int value) : Head(nullptr), Tail(nullptr), size(0)
{while (Count--){Push_Back(value);}
}List::List(const List& ref) : Head(nullptr), Tail(nullptr), size(0)
{Node* node = ref.Head;while (node){Push_Back(node->value);node = node->Next;}
}List::List(std::initializer_list<int> initList) : Head(nullptr), Tail(nullptr), size(0)
{for (auto value : initList){Push_Back(value);}
}List::~List()
{Clear();
}bool List::IsEmpty()
{return this->size == 0 ? true : false;
}size_t List::GetSize()
{return this->size;
}void List::Clear()
{if (IsEmpty()) return;Node* node = this->Head;while (node){Node* Temp = node->Next;delete node;node = Temp;}Head = Tail = nullptr;size = 0;
}void List::Push_Back(int value)
{//創建對象時關聯前后節點對象Node* node = new Node(value, Tail, nullptr);//當前容器是否存在尾節點if (Tail != nullptr){Tail->Next = node;}//修正尾部節點Tail = node;//判斷頭部節點if (Head == nullptr){Head = node;}++this->size;
}void List::Push_Front(int value)
{Node* node = new Node(value, nullptr, Head);if (Head != nullptr){Head->Prev = node;}Head = node;if (Tail == nullptr){Tail = node;}++this->size;
}void List::Insert(int InsertValue, int value)
{Node* node = Head;while (node != nullptr && node->value != InsertValue){node = node->Next;}if (node != nullptr){Node* InsertNode = new Node(value, node, node->Next);if (node->Next != nullptr){node->Next->Prev = InsertNode;}else{Tail = InsertNode;}node->Next = InsertNode;++this->size;}}void List::Pop_Back()
{if (Tail == nullptr){return;}//保存尾節點Node* temp = Tail;//修正尾節點Tail = Tail->Prev;if (Tail == nullptr){Head = nullptr;}else{Tail->Next = nullptr;}delete temp;--this->size;
}void List::Pop_Front()
{if (Head == nullptr){return;}Node* temp = Head;Head = Head->Next;if (Head == nullptr){Tail = nullptr;}else{Head->Prev = nullptr;}delete temp;--this->size;
}void List::Remove(int value)
{Node* node = Head;while (node != nullptr && node->value != value){node = node->Next;}if (node != nullptr){if (node == Head) Pop_Front();else if (node == Tail) Pop_Back();else{node->Prev->Next = node->Next;node->Next->Prev = node->Prev;delete node;--this->size;}}}bool List::Find(int value)
{Node* node = Head;while (node != nullptr){if (node->value == value) return true;node = node->Next;}return false;
}List& List::operator=(const List& other)
{if (this != &other){//刪除默認數據Clear();Node* node = other.Head;while (node){Push_Back(node->value);node = node->Next;}}return *this;
}int& List::operator[](int Index)
{Node* node = Head;int Count = 0;while (node != nullptr && Count < Index){node = node->Next;++Count;}if (node != nullptr){return node->value;}
}std::ostream& operator<<(std::ostream& output, const List& obj)
{Node* node = obj.Head;while (node != nullptr){output << node->value;if (node->Next != nullptr){output << " | ";}node = node->Next;}return output;
}int main()
{//默認構造函數List myList1;//有參構造函數List myList3(3, 0xCC);//列表構造函數List myList4 = { 1,2,3,4,5 };//拷貝構造函數List myList5 = myList4;//賦值運算符List myList6;myList6 = myList5;std::cout << myList6 << std::endl;return 0;
}

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

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

相關文章

技術分享:分布式數據庫DNS服務器的架構思路

DNS是企業數字化轉型的基石。伴隨微服務或單元化部署的推廣&#xff0c;許多用戶也開始采用分布式數據庫將原來的單體數據庫集群服務架構拆分為大量分布式子服務集群&#xff0c;對應不同的微服務或服務單元。本文將從分布式數據庫DNS服務器的架構需求、架構分析兩方面入手&…

1_插入排序_循環不變式

01_插入排序 #include<stdio.h>void insert_sort(int arr[], int n); void printArray(int arr[], size);int main() {int arr[] {1, 2, 3, 22, 5, 9};int n sizeof(arr) / sizeof(arr[0]);printf("打印原始數組:\n");prinfArray(arr, n);insert_sort(arr, …

湖北大學2024年成人高考函授報名專升本市場營銷專業介紹

在璀璨的學術殿堂中&#xff0c;湖北大學如同一顆璀璨的明珠&#xff0c;熠熠生輝。為了滿足廣大社會人士對于繼續深造、提升自我、實現職業夢想的渴望&#xff0c;湖北大學特別開設了成人高等繼續教育項目&#xff0c;為廣大有志之士敞開了一扇通往知識殿堂的大門。 而今&…

【FFmpeg】av_write_frame函數

目錄 1.av_write_frame1.1 寫入pkt&#xff08;write_packets_common&#xff09;1.1.1 檢查pkt的信息&#xff08;check_packet&#xff09;1.1.2 準備輸入的pkt&#xff08;prepare_input_packet&#xff09;1.1.3 檢查碼流&#xff08;check_bitstream&#xff09;1.1.4 寫入…

【創建者模式-建造者模式】

概要 將一個復雜對象的構建與表示分離&#xff0c;使得同樣的構建過程可以創建不同的表示。 建造者模式包含以下角色 抽象建造者類&#xff08;Builder&#xff09;&#xff1a;這個接口規定要實現復雜對象的那些部分的創建&#xff0c;并不涉及具體的部件對象的創建。具體建…

什么是ISR?

ISR&#xff08;Interrupt Service Routine&#xff0c;中斷服務程序&#xff09;是一個用于處理硬件中斷的特定程序。中斷是硬件或軟件引起的事件&#xff0c;會暫時打斷當前正在運行的任務&#xff0c;以便緊急處理某個事件。ISR的目的是快速響應中斷信號&#xff0c;執行所需…

在WSL Ubuntu中啟用root用戶的SSH服務

在 Ubuntu 中&#xff0c;默認情況下 root 用戶是禁用 SSH 登錄的&#xff0c;這是為了增加系統安全性。 一、修改配置 找到 PermitRootLogin 行&#xff1a;在文件中找到 PermitRootLogin 配置項。默認情況下&#xff0c;它通常被設置為 PermitRootLogin prohibit-password 或…

一篇文章學會【node.js安裝以及Vue-Cli腳手架搭建】

一.為什么搭建Vue-Cli (1).傳統的前端項目結構&#xff1a; 一個項目中有許多html文件&#xff0c;每一個html文件都是相互獨立的&#xff0c; 如果需要在頁面中導入一些外部依賴的組件&#xff0c;就需要在每一個html文件中都需要導入&#xff0c;非常麻煩 (2).現在的前端…

A股低開高走,近3000點,行情要啟動了嗎?

A股低開高走&#xff0c;近3000點&#xff0c;行情要啟動了嗎&#xff1f; 今天的A股&#xff0c;讓人瞪目結舌了&#xff0c;你們知道是為什么嗎&#xff1f;盤面上出現2個重要信號&#xff0c;一起來看看&#xff1a; 1、今天兩市低開高走&#xff0c;銀行板塊護盤指數&…

Windows 下后臺啟動java項目的 jar 包

java -jar swagger.jar 的dos窗口 后臺啟動 jar 包&#xff1a; 使用 javaw.exe 啟動 jar 包&#xff0c;并不會在窗口打印日志&#xff0c;而且會直接在后臺運行進程&#xff0c;關掉窗口&#xff0c;進程繼續跑 javaw -jar swagger.jar 關閉進程&#xff1a; 后臺啟動的 …

大數據面試題之Spark(7)

Spark實現wordcount Spark Streaming怎么實現數據持久化保存? Spark SQL讀取文件&#xff0c;內存不夠使用&#xff0c;如何處理? Spark的lazy體現在哪里? Spark中的并行度等于什么 Spark運行時并行度的設署 Spark SQL的數據傾斜 Spark的exactly-once Spark的RDD和p…

大話C語言:第26篇 靜態庫

1 靜態庫概述 C語言靜態庫&#xff08;Static Library&#xff09;是一種包含一組目標文件的歸檔文件&#xff0c;這些目標文件通常是由多個C語言源文件編譯而成的。靜態庫在程序編譯時被鏈接到目標程序中&#xff0c;成為程序的一部分&#xff0c;因此在運行時不再需要額外的…

java Lambda表達式介紹

Lambda 表達式是 Java 8 中引入的一種語法糖,用于簡化使用函數式接口的代碼編寫。它使得 Java 編程更加簡潔和靈活,特別是在處理集合數據、事件監聽器等方面提供了便利。 Lambda 表達式的語法 Lambda 表達式的基本語法如下: (parameters) -> expression或者是一個代碼…

盤古5.0,靠什么去解最難的題?

文&#xff5c;周效敬 編&#xff5c;王一粟 當大模型的競爭開始拼落地&#xff0c;商業化在B端和C端都展開了自由生長。 在B端&#xff0c;借助云計算向千行萬業扎根&#xff1b;在C端&#xff0c;通過軟件App和智能終端快速迭代。 在華為&#xff0c;這家曾經以通信行業起…

Error: A JNl error has occurred, please check your installation and try again.

Eclipse 運行main方法的時候報錯&#xff1a;Error: A JNl error has occurred, please check your installation and try again. 一、問題分析 導致這個問題&#xff0c;主要原因&#xff0c;我認為是在新版本中&#xff0c;默認的JDK編譯版本與我們配置的JDK版本不一致導致的…

公網環境使用Potplayer遠程訪問家中群暉NAS搭建的WebDAV聽歌看電影

文章目錄 前言1 使用環境要求&#xff1a;2 配置webdav3 測試局域網使用potplayer訪問webdav4 內網穿透&#xff0c;映射至公網5 使用固定地址在potplayer訪問webdav 前言 本文主要介紹如何在Windows設備使用potplayer播放器遠程訪問本地局域網的群暉NAS中的影視資源&#xff…

告別流失,擁抱增長!Xinstall智能邀請系統,讓你的App拉新更高效

在移動互聯網時代&#xff0c;App的推廣和運營面臨著諸多挑戰。其中&#xff0c;如何有效地進行邀請拉新活動&#xff0c;吸引更多新用戶&#xff0c;成為了每個運營者都需要面對的問題。今天&#xff0c;我們將為大家介紹一款能夠幫助你輕松解決這一難題的神器——Xinstall。 …

C語言從頭學28——數組(一)

一、基本概念 數組是一組相同類型的值被順序地儲存在一起。數組表示方法為變量名加方括號&#xff0c;方括號里是數組的成員數量。例如&#xff1a; int arr[20]; //聲明了一個 int 類型的名為 arr 包含20個成員的數組 數組的成員是從0開始編號的&#x…

深入理解Symfony框架的環境配置策略

引言 Symfony是一個高度靈活的PHP框架&#xff0c;它允許開發者通過配置文件來定制應用程序的行為&#xff0c;以適應不同的運行環境。環境配置是Symfony中一個重要的概念&#xff0c;它允許開發者為開發、測試和生產環境設置不同的配置參數。本文將詳細探討Symfony的環境配置…

7-491 3名同學5門課程成績,輸出最好成績及所在的行和列(二維數組作為函數的參數)

編程:數組存儲3名同學5門課程成績 輸出最好成績及所在的行和列 要求&#xff1a;將輸入、查找和打印的功能編寫成函數 并將二維數組通過指針參數傳遞的方式由主函數傳遞到子函數中 輸入格式: 每行輸入一個同學的5門課的成績&#xff0c;每個成績之間空一格&#xff0c;見輸入…