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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

二、数组

發布時間:2025/3/19 编程问答 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 二、数组 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、線性表

1、定義

線性表(Linear List):零個或多個數據元素的有限序列

序列(有序):若元素存在多個,則第一個元素無前驅,最后一個無后繼,其他每個元素都有且只有一個前驅和后繼

2、數學表示

線性表:(a1, a2, a3, ..., ai-1, ai, ai+1, ..., an )
ai-1 是 ai 的直接前驅元素, ai+1 是 ai 的直接后繼元素。線性表元素的個數為n(n≥0)定義為線性表的長度,當 n = 0 時,稱為空表

3、線性表的抽象數據類型

ADT 線性表(List) Data線性表的數據對象集合為{a1, a2, ......, an},每個元素的類型均為DataType。其中,除第一個元素a1外,每一個元素有且只有一個直接前驅元素, 除了最后一個元素an外,每一個元素有且只有一個直接后繼元素。 數據元素之間的關系是一對一的關系。 Operation InitList(*L): 初始化操作,建立一個空的線性表L。 ListEmpty(L): 若線性表為空,返回true,否則返回false。 ClearList(*L): 將線性表清空。 GetElem(L, i, *e): 將線性表L中的第i個位置元素值返回給e。 LocateElem(L, e): 在線性表L中查找與給定值e相等的元素,如果查找成功,返回該元素在表中序號表示成功; ListInsert(*L,i,e): 在L的第i個位置插入新元素e。 ListDelete(*L,i,*e): 刪除L中的第i個元素,并用e返回其值。 ListLength(L): 返回L中的元素個數 endADT

二、數組(Array)概述

1、定義

數組是一種線性表數據結構。用一組連續的內存空間來存儲一組具有相同類型的數據

解讀:

  • 線性表:eg:數組、隊列、棧、鏈表
  • 非線性表:eg:樹、堆、圖等
  • 連續內存空間 + 相同類型數據 =》隨機訪問

2、存儲


==》元素存儲的內存地址:

a[i]_address = base_address + i * data_type_size

其中, data_type_size 表示數組中每個元素的大小。

==》擴展:二維數組的內存尋址公式
對于 m*n 的數組,a[i][j] ( i < m, j < n )的地址為:

a[i][j]_address = base_address + ( i * n + j ) * type_size

三、數組的相關操作

低效的“插入”和“刪除”

1、插入

(1)傳統過程

將一個數據插入到數組中的第 k 個位置。為了把第 k 個位置騰出來,給新來的數據,需要將第 k~n 這部分的元素都順序地往后挪一位。
==》
最好情況時間復雜度為 O(1)
最壞情況時間復雜度為 O(n)
平均情況時間復雜度為 (1+2+…n)/n=O(n)

(2)特殊場景

情況: 如果數組中存儲的數據并沒有任何規律,數組只是被當作一個存儲數據的集合。
方法: 將第 k 位的數據搬移到數組元素的最后,把新的元素直接放入第 k 個位置。

==》復雜度為 O(1)

目標:將 x 插入第 3 個位置 a, b, c, d, e ==》a,b,x,d,e,c

2、刪除

(1)傳統過程

要刪除第 k 個位置的數據,為了內存的連續性,也需要搬移數據。

==》
最好情況時間復雜度為 O(1)
最壞情況時間復雜度為 O(n)
平均情況時間復雜度為 (1+2+…n)/n=O(n)

(2)特殊場景

情況: 不一定非得追求數組中數據的連續性。
方法: 先記錄下已經刪除的數據(只記錄數據被刪除,不執行搬移數據的操作)。當數組沒有更多空間存儲數據時,觸發真正的刪除操作,也就是將多次刪除操作集中在一起執行,從而提高刪除的效率。

==》擴展: JVM 標記清除垃圾回收算法的核心思想

==》很多時候我們并不是要去死記硬背某個數據結構或者算法,而是要學習它背后的思想和處理技巧,這些東西才是最有價值的。

四、數組訪問越界問題

1、示例

int main(int argc, char* argv[]){int i = 0;int arr[3] = {0};for(; i <= 3; i++){arr[i] = 0;printf("hello world\0");}return 0; }

結果如下:

發生數組訪問越界==》運行結果并非是打印三行“hello word”,而是四行“hello word”或無限打印“hello world”

2、分析

(1)在 C 語言中,只要不是訪問受限的內存,所有的內存空間都是可以自由訪問的。根據我們前面講的數組尋址公式,a[3] 也會被定位到某塊不屬于數組的內存地址上,而這個地址正好是存儲變量i 的內存地址(下面解釋),那么 a[3]=0 就相當于 i=0,所以就會導致代碼無限循環。

(2)函數體內的局部變量存在棧上,且是連續壓棧。在Linux進程的內存布局中,棧區在高地址空間,從高向低增長。變量i和arr在相鄰地址,且i比arr的地址大,所以arr越界正好訪問到i。當然,前提是i和arr元素同類型,否則那段代碼仍是未決行為。

五、容器 vs. 數組


很多語言都提供了容器類,比如 Java 中的 ArrayList、C++ STL 中的 vector。
容器類的最大的優勢就是可以將很多數組操作的細節封裝起來。
容器適用于業務開發,省時省力;非常底層的開發(網絡框架等)或性能要求特別高,優先使用數組

  • Java ArrayList 無法存儲基本類型,比如int、long,需要封裝為Integer、Long類,而 Autoboxing、Unboxing 則有一定的性能消耗,所以如果特別關注性能,或者希望使用基本類型,就可以選用數組。
  • 如果數據大小事先已知,并且對數據的操作非常簡單,用不到 ArrayList 提供的大部分方法,也可以直接使用數組。
  • 表示多維數組時,用數組往往會更加直觀。比如 Object[][] array;而用容器的話則需要這樣定義:ArrayList<ArrayList> array。
  • 總結

    以上是生活随笔為你收集整理的二、数组的全部內容,希望文章能夠幫你解決所遇到的問題。

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