鏈表和順序表的一些區別

順序表與鏈表是非常基本的數據結構,它們可以被統稱為線性表。

線性表(Linear List)是由 n(n≥0)個數據元素(結點)a[0],a[1],a[2]…,a[n-1] 組成的有限序列。

順序表和鏈表,是線性表的不同存儲結構。它們各自有不同的特點和適用范圍。針對它們各自的缺點,也有很多改進的措施。

一、順序表

順序表一般表現為數組,使用一組地址連續的存儲單元依次存儲數據元素,如圖 1 所示。它具有如下特點:

  • 長度固定,必須在分配內存之前確定數組的長度。
  • 存儲空間連續,即允許元素的隨機訪問。
  • 存儲密度大,內存中存儲的全部是數據元素。
  • 要訪問特定元素,可以使用索引訪問,時間復雜度為?O(1)O(1)
  • 要想在順序表中插入或刪除一個元素,都涉及到之后所有元素的移動,因此時間復雜度為?O(n)O(n)

圖 1 順序表

順序表最主要的問題就是要求長度是固定的,可以使用倍增-復制的辦法來支持動態擴容,將順序表變成“可變長度”的。

具體做法是初始情況使用一個初始容量(可以指定)的數組,當元素個數超過數組的長度時,就重新申請一個長度為原先二倍的數組,并將舊的數據復制過去,這樣就可以有新的空間來存放元素了。這樣,列表看起來就是可變長度的。

一個簡單的實現如下所示,初始的容量為 4。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <string.h>
struct?sqlist {
????int?*items, size, capacity;
????sqlist():size(0), capacity(4) {
????????// initial capacity = 4
????????items =?new?int[capacity];
????}
????void?doubleCapacity() {
????????capacity *= 2;
????????int* newItems =?new?int[capacity];
????????memcpy(newItems, items,?sizeof(int)*size);
????????delete[] items;
????????items = newItems;
????}
????void?add(int?value) {
????????if?(size >= capacity) {
????????????doubleCapacity();
????????}
????????items[size++] = value;
????}
};

這個辦法不可避免的會浪費一些內存,因為數組的容量總是倍增的。而且每次擴容的時候,都需要將舊的數據全部復制一份,肯定會影響效率。不過實際上,這樣做還是直接使用鏈表的效率要高,具體原因會在下一節進行分析。

二、鏈表

鏈表,類似它的名字,表中的每個節點都保存有指向下一個節點的指針,所有節點串成一條鏈。根據指針的不同,還有單鏈表、雙鏈表和循環鏈表的區分,如圖 2 所示。

圖 2 鏈表

單鏈表是只包含指向下一個節點的指針,只能單向遍歷。

雙鏈表即包含指向下一個節點的指針,也包含指向前一個節點的指針,因此可以雙向遍歷。

循環單鏈表則是將尾節點與首節點鏈接起來,形成了一個環狀結構,在某些情況下會非常有用。

還有循環雙鏈表,與循環單鏈表類似,這里就不再贅述。

由于鏈表是使用指針將節點連起來,因此無需使用連續的空間,它具有以下特點:

  • 長度不固定,可以任意增刪。
  • 存儲空間不連續,數據元素之間使用指針相連,每個數據元素只能訪問周圍的一個元素(根據單鏈表還是雙鏈表有所不同)。
  • 存儲密度小,因為每個數據元素,都需要額外存儲一個指向下一元素的指針(雙鏈表則需要兩個指針)。
  • 要訪問特定元素,只能從鏈表頭開始,遍歷到該元素,時間復雜度為?O(n)O(n)
  • 在特定的數據元素之后插入或刪除元素,不涉及到其他元素的移動,因此時間復雜度為?O(1)O(1)。雙鏈表還允許在特定的數據元素之前插入或刪除元素。

在上一節說到,利用倍增-復制的辦法,同樣可以讓順序表長度可變,而且效率比鏈表還要好,下面就簡單的實現一個單鏈表來驗證這一點,至于元素插入的順序就不要在意了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <stdio.h>
#include <time.h>
??
struct?node {
????int?value;
????node *next;
};
struct?llist {
????node *head;
????void?add(int?value) {
????????node *newNode =?new?node();
????????newNode->value = value;
????????newNode->next = head;
????????head = newNode;
????}
};
int?main() {
????int?size = 100000;
????sqlist list1;
????llist list2;
????long?start =?clock();
????for?(int?i = 0;i < size;i++) {
????????list1.add(i);
????}
????long?end =?clock();
????printf("sequence list: %d\n", end - start);
????start =?clock();
????for?(int?i = 0;i < size;i++) {
????????list2.add(i);
????}
????end =?clock();
????printf("linked list: %d\n", end - start);
????return?0;
}

在我的電腦上,鏈表的耗時大約是順序表的 4~8 倍。會這樣,是因為數組只需要很少的幾次大塊內存分配,而鏈表則需要很多次小塊內存分配,內存分配操作相對是比較慢的,因而大大拖慢了鏈表的速度。這也是為什么會出現內存池。

因此,鏈表并不像理論分析的那樣美好,在實際應用中要受很多條件制約,一般情況下還是安心用順序表的好。

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

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

相關文章

ANCS推送簡介

總體原理 ANCS通過藍牙BLE 4.0實現&#xff0c;僅支持iPhone 4S及以上且系統版本在IOS 7以上的手機&#xff0c;同時在外設端需要支持藍牙4.0協議。 1、外設端進行廣播&#xff0c;手機打開藍牙&#xff0c;搜索外設&#xff0c;連接外設&#xff0c;之后進行綁定&#xff08;這…

好記性不如爛筆頭,記錄幾個常用的Linux操作

作者&#xff1a;老王Shell公共函數庫Linux系統里有一些公共的Shell函數庫可供使用&#xff0c;最重要的是/etc/rc.d/init.d/functions&#xff0c;在/etc/init.d目錄下有很多腳本都用到了這個函數庫&#xff0c;里面提供了很多有用的方法&#xff0c;比如&#xff1a;killproc…

用matlab簡單電路模型,基于MATLAB的電路模型仿真應用

基于MATLAB的電路模型仿真應用實驗指導書一、實驗目的1、掌握采用M文件及SIMULINK對電路進行仿真的方法。2、熟悉POWERSYSTEM BLOCKSET 模塊集的調用、設置方法。3&#xff0e;進一步熟悉M腳本文件編寫的方法和技巧。二、實驗原理1、通過M文件實現電路仿真的一般仿真步驟為&…

春節期間小游戲同時在線人數最高達2800萬人/小時

微信官方發布2018年春節期間微信數據報告&#xff1a;除夕至初五&#xff0c;總共有2,297億條微信消息&#xff0c;28億條微信朋友圈成功發出&#xff0c;音視頻通話總時長175億乙分鐘。其中&#xff0c;90后用廣的消息發送量占總量的42.5%&#xff0c;80后用戶25.9%&#xff0…

C語言中* 和

&x是對x變量取地址&#xff0c;也就是返回的是x的地址。 int *i;這里面的*說明變量i是一個指針&#xff0c;存的是一個地址。 而 *i整體代表的是一個數值&#xff0c;例如可以int *i 5 這里整體的*i代表的是5&#xff0c;而i代表的是這個值存儲的地址

餐館的故事-淺析職責鏈模式

我們在餐館吃飯的時候&#xff0c;一般都是在拿到菜單后&#xff0c;選擇喜歡的菜&#xff0c;然后通知服務員。服務員會將我們的定單交給大廚&#xff0c;大廚可能會親自去做這道菜&#xff0c;也可能安排給小廚來做&#xff0c;總之&#xff0c;我們不用擔心他們沒有人做菜&a…

JDBC數據對象存儲

一&#xff1a;將查詢的結果生成對象&#xff0c;儲存在數組中。 1 package day31;2 3 import java.sql.Connection;4 import java.sql.PreparedStatement;5 import java.sql.ResultSet;6 import java.sql.SQLException;7 import java.util.ArrayList;8 9 public class java_ob…

個人工作13年的一些人生真實領悟

此文不定期的更新&#xff0c;想起來就寫一些&#xff0c;我都忘了我曾經會過什么了。你可能會在許多的文章里看到類似的&#xff0c;但這些是我個人的真實體會。 1 技術服從于業務 此問題以前的一個文章提過&#xff0c;不再多說。 適用于大多數對技術的盲目崇拜者。在絕大…

matlab非齊次方程組的通解,用matlab求非齊次線性方程組的通解?

先向大家介紹一下非齊次線性方程組。所謂非齊次線性方程組就是方程組等號右邊的常數項不全為零的線性方程組。全部等于零時&#xff0c;就稱為齊次線性方程組。下面我們就講解一下如何利用matlab快速求非齊次線性方程組的通解。工具/材料matlab電腦操作方法01線性方程組Axb的求…

Linux 終端仿真程序Putty

PuTTY是一個Telnet、SSH、rlogin、純TCP以及串行接口連接軟件。較早的版本僅支持Windows平臺&#xff0c;現在的版本中開始支持各類Unix平臺。 用linux作為桌面系統&#xff0c;身為工程師很多時候需要通過Telnet、SSH協議進行遠程管理&#xff0c;通過串口進行設備配置。Putty…

Mysql 數據庫水平分表 存儲過程

數據庫存儲量達到一定程度的時候&#xff0c;就需要進行分表以減輕檢索的消耗。 常用的分表方式包括水平和垂直分表。本次進行的是按照uid進行水平分表。 ##分表思路&#xff1a; 水平分表平均的將數據按照特定方式分配到多個表中。理論上每個表的訪問頻次和數據量都是同一水平…

中國架構師,名符其實有多少?

先說一下讀后感&#xff1a;我前段時間去過幾個公司面試架構師&#xff0c;要求還是蠻高的&#xff0c;要熟悉大數據量處理&#xff0c;要熟悉高并發&#xff0c;要熟悉XX體系架構&#xff0c;要能在關鍵技術上實現突破。總之&#xff0c;架構錯了&#xff0c;就啥都錯了。呵呵…

粗識靜態鏈表

為了彌補鏈表在內存分配上的不足&#xff0c;出現了靜態鏈表這么一個折中的辦法。靜態鏈表比較類似于內存池&#xff0c;它會預先分配一個足夠長的數組&#xff0c;之后鏈表節點都會保存在這個數組里&#xff0c;這樣就不需要頻繁的進行內存分配了。 當然&#xff0c;這個方法的…

php用date語句獲取時間,關于php date()函數獲取時間的設置和使用方法

date()函數是PHP自帶的時間函數&#xff0c;可以獲取當前服務器的時間echo date(Y-m-d H:i:s); //輸出:2020-05-18 11:02:35date()函數中可以使用的字母含義&#xff1a;a-"am"(上午)或者"pm"(下午)A-"AM"或者"PM"Y-年&#xff0c;顯示…

Django_form補充

問題1: 注冊頁面輸入為空&#xff0c;報錯&#xff1a;keyError&#xff1a;找不到passworddef clean(self): print("---",self.cleaned_data) # if self.cleaned_data["password"]self.cleaned_data["repeat_password"]: …

WF4.0:NativeActivity中的錯誤處理

備注&#xff1a;這篇文章的使用環境是.NET framework 4.0 RC 1 在WF4中創建native活動時&#xff0c;NativeActivity是非常強大的。其眾多的功能之一是圍繞錯誤處理。 調度子活動的時的基本錯誤處理。 當NativeActivity執行的時候&#xff0c;它是通過一個NativeActivityConte…

程序員提高建議之踏踏實實“扎馬步”

踏踏實實“扎馬步” 今天無意中看了“校長”的“程序員&司機”&#xff0c;其中談到了關于程序員速成的問題。其實速成班畢業的“系統殺手”早已在遍布大江南北&#xff0c;只是在互聯網時代&#xff0c;互聯網的應用型軟件生命周期越來越短&#xff0c;業務驅動主導…

c語言scanf返回值

1. scanf 函數是有返回值的&#xff0c;它的返回值可以分成三種情況1) 正整數&#xff0c;表示正確輸入參數的個數。例如執行 scanf("%d %d", &a, &b);如果用戶輸入"3 4"&#xff0c;可以正確輸入&#xff0c;返回2&#xff08;正確輸入了兩個變量…

gpgga格式讀取MATLAB,GPS編碼格式及讀取.doc

GPS接收機只要處于工作狀態就會源源不斷地把接收并計算出的GPS導航定位信息通過串口傳送到計算機中。前面的代碼只負責從串口接收數據并將其放置于緩存&#xff0c;在沒有進一步處理之前緩存中是一長串字節流&#xff0c;這些信息在沒有經過分類提取之前是無法加以利用的。因此…

Cadence 電源完整性仿真實踐(二)

轉載于:http://blog.csdn.net/wu20093346/article/details/38050917 通過以上步驟對每個平面進行了單節點分析并觀測了響應曲線&#xff0c;接下來將觀測平面對的目標阻抗是否滿足要求&#xff0c;通過選擇電容器的方法來減小含有電容器阻抗響應曲線中的反諧振波峰。在SigWave窗…