摘要:概述數(shù)組是一種很基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu),幾乎絕大多數(shù)編程語言都會支持?jǐn)?shù)組這種數(shù)據(jù)結(jié)構(gòu)。數(shù)組是一種線性結(jié)構(gòu),使用一組連續(xù)的內(nèi)存空間,來存儲相同類型的數(shù)據(jù)。
1. 概述
數(shù)組(Array)是一種很基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu),幾乎絕大多數(shù)編程語言都會支持?jǐn)?shù)組這種數(shù)據(jù)結(jié)構(gòu)。數(shù)組是一種線性結(jié)構(gòu),使用一組連續(xù)的內(nèi)存空間,來存儲相同類型的數(shù)據(jù)。
所謂線性結(jié)構(gòu),就是指數(shù)據(jù)是前后排列的,只有前后兩個方向,除了數(shù)組,其他的比如鏈表、棧、隊(duì)列都是線性結(jié)構(gòu)。
因?yàn)閿?shù)組是使用連續(xù)的內(nèi)存空間來存儲數(shù)據(jù)的,所以數(shù)組的最大的特點(diǎn)就是支持根據(jù)下標(biāo)隨機(jī)訪問數(shù)據(jù),這是數(shù)組最大的優(yōu)勢。但是,有利就有弊,雖然數(shù)組高效的支持下標(biāo)訪問,只不過在插入和刪除數(shù)據(jù)的時候就比較低效了,為了保證內(nèi)存的連續(xù)性,必須要進(jìn)行數(shù)據(jù)搬移。
2. 插入數(shù)據(jù)
先來看看插入操作,假如有一個數(shù)組 [3, 4, 6, 8, 7, 2, 5],第一種情況是插入的元素位于數(shù)組的最后一個位置,那么不用進(jìn)行數(shù)據(jù)搬移,時間復(fù)雜度為 O(1) ,如果插入的位置是第一個,那么必須移動整個數(shù)組,時間復(fù)雜度為 O(n) 。
這里有另外一個處理思路:如果數(shù)組中存儲的數(shù)據(jù)不在乎彼此順序的話,那么插入數(shù)據(jù)的時候,我們可以直接將插入位置的元素放到數(shù)組最后一位,騰出位置給新的元素。就像下圖這樣:
3. 刪除數(shù)據(jù)
再來看看刪除操作,還是上面的數(shù)組 [3, 4, 6, 8, 7, 2, 5],如果刪除的是最后一個元素,那么不需要進(jìn)行數(shù)據(jù)搬移,如果刪除的是第一個元素,那么數(shù)組每一個元素都會向前移動一位。
只不過,在某些場景下,如果不是特別追求數(shù)據(jù)的連續(xù)性,那么我們可以采用另一種思路來處理刪除操作。例如數(shù)組的大小為 10 ,現(xiàn)在存儲了 7 個元素,分別是 [3, 4, 6, 8, 7, 2, 5],如果我們要刪除 3 4 6 這三個元素,我們先將其標(biāo)記為刪除,等到數(shù)組空間不夠的時候,在集中性的進(jìn)行數(shù)據(jù)搬移,這樣就大大減少了數(shù)據(jù)搬移的次數(shù)!
是不是非常高效呢?
4. Java 容器
在 Java 語言中,提供了一個可以支持動態(tài)擴(kuò)容的數(shù)組容器:ArrayList,如果你熟悉 Java 語言的話,幾乎每天都會和這個容器打交道,它封裝了一些數(shù)組的操作,并且在數(shù)組空間不夠的時候,自動擴(kuò)容為原來的 1.5 倍。
只不過,在使用 ArrayList 的時候,要是能夠指定大小,最好指定,這樣會減少申請內(nèi)存空間和數(shù)據(jù)搬移的操作。
5. 代碼示例
下面是簡單的支持動態(tài)擴(kuò)容的數(shù)組實(shí)現(xiàn):
/* * 泛型動態(tài)數(shù)組 */ public class GenericArray{ private T[] data; private int count;//數(shù)組中存儲的個數(shù) public GenericArray(int capacity) { this.data = (T[]) new Object[capacity]; this.count = 0; } public GenericArray() { this(16); } //返回?cái)?shù)組中元素的個數(shù) public int getSize() { return this.count; } //返回?cái)?shù)組容量 public int getCapacity() { return this.data.length; } //設(shè)置某個位置的數(shù)據(jù) public void set(int index, T value) { if (count == data.length) { //擴(kuò)容 resize(data.length * 2); } checkIndex(index); if (index == count) { data[count ++] = value; return; } //常規(guī)刪除 for (int i = count; i < index; i --) data[i] = data[i - 1]; data[index] = value; count ++; } //在數(shù)組末尾插入數(shù)據(jù) public void insert(T value) { set(count, value); } //刪除數(shù)據(jù) public T remove(int index) { if(index == count) throw new IllegalArgumentException("Index Illegal!"); checkIndex(index); T result = data[index]; for (int i = index; i < count - 1; i ++) data[i] = data[i + 1]; count --; //縮容 if (count == data.length / 2) { resize(data.length / 2); } return result; } //檢查下標(biāo)的方法 public void checkIndex(int index) { if(index < 0 || index > count) throw new IllegalArgumentException("Index Illegal!"); } //重新設(shè)置數(shù)組的容量, 對應(yīng)的操作是擴(kuò)容和縮容 private void resize(int capacity) { T[] temp = (T[]) new Object[capacity]; for (int i = 0; i < count; i++) { temp[i] = data[i]; } data = temp; } }
是不是很簡單呢?后面接著講數(shù)據(jù)結(jié)構(gòu)與算法的知識!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/73676.html
摘要:為檢查長度為的列表,二分查找需要執(zhí)行次操作。最后需要指出的一點(diǎn)是高水平的讀者可研究一下二叉樹關(guān)于二叉樹,戳這里數(shù)據(jù)結(jié)構(gòu)與算法二叉樹算法常見練習(xí)在一個二維數(shù)組中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。 常見數(shù)據(jù)結(jié)構(gòu) 簡單數(shù)據(jù)結(jié)構(gòu)(必須理解和掌握) 有序數(shù)據(jù)結(jié)構(gòu):棧、隊(duì)列、鏈表。有序數(shù)據(jù)結(jié)構(gòu)省空間(儲存空間?。?無序數(shù)據(jù)結(jié)構(gòu):集合、字典、散列表,無序...
摘要:為檢查長度為的列表,二分查找需要執(zhí)行次操作。最后需要指出的一點(diǎn)是高水平的讀者可研究一下二叉樹關(guān)于二叉樹,戳這里數(shù)據(jù)結(jié)構(gòu)與算法二叉樹算法常見練習(xí)在一個二維數(shù)組中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。 常見數(shù)據(jù)結(jié)構(gòu) 簡單數(shù)據(jù)結(jié)構(gòu)(必須理解和掌握) 有序數(shù)據(jù)結(jié)構(gòu):棧、隊(duì)列、鏈表。有序數(shù)據(jù)結(jié)構(gòu)省空間(儲存空間小) 無序數(shù)據(jù)結(jié)構(gòu):集合、字典、散列表,無序...
摘要:為檢查長度為的列表,二分查找需要執(zhí)行次操作。最后需要指出的一點(diǎn)是高水平的讀者可研究一下二叉樹關(guān)于二叉樹,戳這里數(shù)據(jù)結(jié)構(gòu)與算法二叉樹算法常見練習(xí)在一個二維數(shù)組中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。 常見數(shù)據(jù)結(jié)構(gòu) 簡單數(shù)據(jù)結(jié)構(gòu)(必須理解和掌握) 有序數(shù)據(jù)結(jié)構(gòu):棧、隊(duì)列、鏈表。有序數(shù)據(jù)結(jié)構(gòu)省空間(儲存空間?。?無序數(shù)據(jù)結(jié)構(gòu):集合、字典、散列表,無序...
摘要:用來標(biāo)示該輪冒泡排序中,數(shù)組是否是有序的。適用情況當(dāng)冒泡算法運(yùn)行到后半段的時候,如果此時數(shù)組已經(jīng)有序了,需要提前結(jié)束冒泡排序。當(dāng)?shù)谝惠喢芭菖判蚪Y(jié)束后,元素會被移動到下標(biāo)的位置。 這篇文章包含了你一定知道的,和你不一定知道的冒泡排序。 gif看不了可以點(diǎn)擊【原文】查看gif。 源碼: 【地址】 1. 什么是冒泡排序 可能對于大多數(shù)的人來說比如我,接觸的第一個算法就是冒泡排序。 我看過的很...
摘要:上一篇數(shù)據(jù)結(jié)構(gòu)與算法樹寫在前面這是學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法的最后一篇博客,也是在面試中常常會被問到的一部分內(nèi)容排序和搜索。 上一篇:JS數(shù)據(jù)結(jié)構(gòu)與算法_樹 寫在前面 這是《學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與算法》的最后一篇博客,也是在面試中常常會被問到的一部分內(nèi)容:排序和搜索。在這篇博客之前,我每每看到排序頭就是大的,心里想著類似冒泡排序,兩層遍歷啪啪啪就完事了,然后再也無心去深入研究排序相...
摘要:這是一個簡單的遞歸函數(shù),你可以使用它來生成數(shù)列中指定序號的數(shù)值這個函數(shù)的問題在于它的執(zhí)行效率非常低有太多值在遞歸調(diào)用中被重新計(jì)算。 本章內(nèi)容銜接上一章 數(shù)據(jù)結(jié)構(gòu)與算法:二分查找 內(nèi)容提要 兩種基本數(shù)據(jù)結(jié)構(gòu): 數(shù)組 常見操作: 數(shù)組降維、數(shù)組去重 鏈表 遞歸:遞歸是很多算法都使用的一種編程方法 - 如何將問題分成基線條件和遞歸條件 - 分而治之策略解決棘手問題 ...
閱讀 1002·2021-09-30 09:58
閱讀 2829·2021-09-09 11:55
閱讀 2001·2021-09-01 11:41
閱讀 991·2019-08-30 15:55
閱讀 3350·2019-08-30 12:50
閱讀 3495·2019-08-29 18:37
閱讀 3295·2019-08-29 16:37
閱讀 2011·2019-08-29 13:00