日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构 链表(一)

發布時間:2025/3/20 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构 链表(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

鏈表

  • 鏈表的時間復雜度
  • 單向鏈表與雙向鏈表
    • 單向鏈表與雙向鏈表的比較
    • 鏈表與數組的比較
  • 單向鏈表的C++實現
    • 反轉單向鏈表圖解

鏈表是通過 分布在內存各個位置上不同節點相互連接成的一種線性表的數據結構,其特性突出表現為 內存分布零散,因此在數據存儲對內存要求相較于數組而言較低。

鏈表的時間復雜度

  • 數據插入:鏈表的數據的內存由于是分散的,因此在插入過程中只需要考慮前后數據指針的改變即可,不用考慮插入節點后的數據遷移工作,因此鏈表單純的插入操作的時間復雜度是O(1),但是因為數據的查找訪問需要遍歷整個鏈表,因此在鏈表中任意位置插入節點數據時,僅僅是遍歷占用的時間復雜度為O(n),僅僅在頭節點插入時不需要遍歷此時的時間復雜度才為O(1)
  • 數據刪除:與數據插入一樣,數據節點的刪除只要考慮刪除節點前后兩節點指針的變化,因此鏈表節點單純刪除的時間復雜度是O(1),與插入的情況基本一致,刪除頭部首個數據節點時時間復雜度才為O(1),其余均為O(n)。
  • 數據訪問:由于鏈表的特性是非連續內存分布的數據結構,因此不具備隨機訪問的特性,在查找、數據訪問時需要進行遍歷鏈表的操作,因此鏈表的數據訪問操作的時間復雜度為O(n)
  • 單向鏈表與雙向鏈表

    單向鏈表:鏈表結構中只有一個next指針,僅僅實現單向傳遞
    雙向鏈表:鏈表結構中含有兩個指針,prev和next指針,能夠前后照應

    單向鏈表與雙向鏈表的比較

  • 在插入與刪除節點的操作過程中,假設需要操作的節點是鏈表中間某個節點,此時左右相鄰的兩個節點都是存有數據的節點,并非頭尾兩節點,假設需要操作的是在指定節點的前面進行插入或者刪除,此時對于單向鏈表而言,僅僅知道指定節點后的那一個節點,因此,還需知道前一個節點才能進行指針的賦值操作,因此還需進行一次遍歷操作至指定節點的前一個節點并記錄其信息,在此情況下,節點的插入或者刪除的時間復雜度為O(n),但是由于雙向鏈表的前后指針的特殊性使得在此需求下的時間復雜度變為O(1)

  • 當鏈表為有序狀態下時,雙向鏈表的查找比單向鏈表的效率高一些,因為是雙向的,所以可以決定是從頭開始還是從尾開始,再加上有序的前提,所以平均下來雙向鏈表只需要遍歷一半的數據

  • 綜上所述,雙向鏈表比單向鏈表更加高效,但并不是采取一刀切的方式選取雙向鏈表來應對需求。當內存空間很富裕,倘若追求極致的代碼運行速度,則可以選擇雙向鏈表這種空間復雜度稍高,時間復雜度稍低的數據結構,以空間換取時間;但是在內存空間不充裕的情況下,則需要忽略掉部分運行速度,使得程序能夠安全運行,以時間換空間

  • 鏈表與數組的比較

  • 數組與鏈表采取截然不同的內存組織方式,因此針對不同的需求需要采取不同的使用策略
  • 數組簡單易用,使用的是連續的內存空間,利用CPU的緩存機制去預讀數組中的數據,隨機訪問的效率更高,鏈表的空間零散,對于CPU緩存而言不太友好。
  • 數組的大小固定,尤其當數組的大小特別大時,容易出現內存不足的情況,并且突然改變數組大小后的數據拷貝工作也極其費時。但鏈表不一樣,鏈表依托其分散內存空間的特性,能夠極大程度減少出現內存不足的現象。
  • 與數組相比,鏈表更適合用于數據的插入、刪除操作頻繁的場景,數組更適合用于隨機訪問頻繁的場景,當然并不是照本宣科還是要依照實際情況進行分析
  • 單向鏈表的C++實現

    #pragma once #include<iostream>typedef struct Node {int value;Node* next; }node;class Linklist { private:node* head;int size; public://默認構造函數Linklist();//插入節點,尾插法void AddNode(node* n);//insert采用尾插法,插入pos節點的后面void Insert(int pos, node* n);//刪除pos后的節點void DelNode(int pos);//獲取當前容量int GetLinklistSize();//查找指定元素的位置void FindNode(int value);//釋放空間void FreeNode();//打印鏈表內容void PrintLinklist();//反轉鏈表void ReverseLinklist(); }; #include"linklist.h" #include<iostream> using std::cout; using std::endl;Linklist::Linklist() {this->size = 0;this->head = new node;this->head->value = 0;this->head->next = NULL; }void Linklist::AddNode(node* n) {node* temp = new node;temp->value = n->value;if (n == NULL){cout << "ERROR NODE\n";return;}else if(!this->head->next)//空鏈表{this->head->next = temp;temp->next = NULL;}else //非空鏈表{node* pnode = this->head;for (int i = 0; i < size; ++i){pnode = pnode->next;}pnode->next = temp;temp->next = NULL;}this->size++; }void Linklist::Insert(int pos, node* n) {node* temp = new node;temp->value = n->value;if (pos <= 0 || pos > this->size){cout << "NO SUCH NODE\n";return;}else{node* pnode = this->head;for (int i = 0; i < pos; ++i){pnode = pnode->next;}temp->next = pnode->next;pnode->next = temp;this->size++;} }void Linklist::DelNode(int pos) {if (pos <= 0 || pos > size){cout << "NO SUCH NODE\n";return;}node* pnode = this->head;for (int i = 0; i < pos-1; ++i){pnode = pnode->next;}node* temp = pnode->next;pnode->next = pnode->next->next;this->size--;delete temp; }int Linklist::GetLinklistSize() {return this->size; }void Linklist::FindNode(int value) {node* pnode = this->head;int flag = 0;for (int i = 0; i < size; ++i){pnode = pnode->next;if (pnode->value == value){cout << "[ " << i << " ] ==" << value << endl;flag++;}}if (!flag)cout << "NO SUCH NUMBER YOU WANT\n"; }void Linklist::FreeNode() {if (!this->size)cout << "Linklist is empty\n";else{node* pnode = this->head;for (int i = 0; i <= this->size; ++i){node* temp = pnode;pnode = pnode->next;delete temp;}} }void Linklist::PrintLinklist() {if (!this->size){cout << "NO DATA TO READ\n";return;}else{node* pnode = this->head;for (int i = 0; i < this->size; ++i){cout << "[ " << i + 1 << " ] == " << pnode->next->value << endl;pnode = pnode->next;}} }void Linklist::ReverseLinklist() {if (!this->size){cout << "NO DATA TO READ\n";return;}else{node* pnode = head->next;node* temp;//反轉單向鏈表注意:第一個始終保持在最后一個,更改其next指針// 頭指針也不動,更改自身的next指針即可// 只需要更改一個移動節點,不斷向后逐個移動while (pnode->next){temp = pnode->next;pnode->next = temp->next;temp->next = head->next;head->next = temp;}} } #include"linklist.h"int main() {Linklist lk;node n1 = { 2 };node n2 = { 8 };node n3 = { 15 };node n4 = { 20 };node n5 = { 36 };lk.AddNode(&n1);lk.AddNode(&n2);lk.AddNode(&n3);lk.AddNode(&n4);lk.PrintLinklist();cout << "size == " << lk.GetLinklistSize() << endl;lk.Insert(3, &n1);lk.PrintLinklist();cout << "size == " << lk.GetLinklistSize() << endl;lk.AddNode(&n5);lk.Insert(2, &n4);lk.Insert(4, &n3);lk.PrintLinklist();cout << "size == " << lk.GetLinklistSize() << endl;lk.DelNode(2);lk.PrintLinklist();cout << "size == " << lk.GetLinklistSize() << endl;lk.FindNode(16);lk.FindNode(2);lk.ReverseLinklist();lk.PrintLinklist();return 0; };

    輸出結果

    [ 1 ] == 2 [ 2 ] == 8 [ 3 ] == 15 [ 4 ] == 20 size == 4 [ 1 ] == 2 [ 2 ] == 8 [ 3 ] == 15 [ 4 ] == 2 [ 5 ] == 20 size == 5 [ 1 ] == 2 [ 2 ] == 8 [ 3 ] == 20 [ 4 ] == 15 [ 5 ] == 15 [ 6 ] == 2 [ 7 ] == 20 [ 8 ] == 36 size == 8 [ 1 ] == 2 [ 2 ] == 20 [ 3 ] == 15 [ 4 ] == 15 [ 5 ] == 2 [ 6 ] == 20 [ 7 ] == 36 size == 7 NO SUCH NUMBER YOU WANT [ 0 ] ==2 [ 4 ] ==2 [ 1 ] == 36 [ 2 ] == 20 [ 3 ] == 2 [ 4 ] == 15 [ 5 ] == 15 [ 6 ] == 20 [ 7 ] == 2

    反轉單向鏈表圖解

    總結

    以上是生活随笔為你收集整理的数据结构 链表(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。