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

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

第二十二篇 玩转数据结构——构建动态数组

發(fā)布時(shí)間:2023/12/10 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第二十二篇 玩转数据结构——构建动态数组 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
1.. 數(shù)組基礎(chǔ)
  • 數(shù)組就是把數(shù)據(jù)碼成一排進(jìn)行存放。
  • Java中,數(shù)組的每個(gè)元素類(lèi)型必須相同,可以都為int類(lèi)型,string類(lèi)型,甚至是自定義類(lèi)型。
  • 數(shù)組的命名要語(yǔ)義化,例如,如果數(shù)組用來(lái)存放學(xué)生的成績(jī),那么命名為scores就比較合適。
  • 索引(index)是數(shù)組中的一個(gè)重要概念,它是我們給數(shù)組中的每個(gè)元素分配的編號(hào),從0開(kāi)始,依次遞增。如果數(shù)組中存放了n個(gè)元素,第一個(gè)元素的索引是0,最后一個(gè)元素的索引是n-1。
  • 通過(guò)索引,我們可以對(duì)數(shù)組中的元素進(jìn)行快速訪(fǎng)問(wèn),例如,我們?cè)L問(wèn)索引為2的元素也就是數(shù)組中的第3個(gè)元素,就可以通過(guò)scores[2]這種形式。
  • 在Java中聲明一個(gè)簡(jiǎn)單的數(shù)組
  • public class Main {public static void main(String[] args) {int[] arr = new int[10];for (int i = 0; i < arr.length; i++)arr[i] = i;} }

    ?

  • 聲明一個(gè)有初始值的數(shù)組
  • public class Main {public static void main(String[] args) {int[] scores = new int[]{100, 99, 86};for (int i = 0; i < scores.length; i++)System.out.println(scores[i]);} }

    ?

  • for循環(huán)的另一種使用形式
  • public class Main {public static void main(String[] args) {int[] scores = new int[]{100, 99, 86};for (int score : scores)System.out.println(score);} }

    ?

  • 修改數(shù)組中的元素
  • socres[1] = 98;

    ?

  • 數(shù)組的索引可以是語(yǔ)義化的,也可以是非語(yǔ)義化的。
  • 數(shù)組的最大優(yōu)點(diǎn),就是可以通過(guò)索引對(duì)數(shù)據(jù)進(jìn)行快速查詢(xún),因此,我們傾向于使用語(yǔ)義化的索引,這樣我們就很清楚自己在查什么。
  • 如果我們的應(yīng)用場(chǎng)景中,索引沒(méi)有語(yǔ)義,那么使用其它數(shù)據(jù)結(jié)構(gòu)可能是更好的選擇。
  • 對(duì)于一些特殊應(yīng)用場(chǎng)景,雖然使用了語(yǔ)義化索引,但依然不適合使用數(shù)組,例如,身份證號(hào),我們不能使用身份證號(hào)來(lái)作為數(shù)組的索引,因?yàn)檫@個(gè)數(shù)字太大了,會(huì)導(dǎo)致巨大的空間浪費(fèi)。
  • 如果數(shù)組的索引是非語(yǔ)義化的,我們就需要考慮很多問(wèn)題,例如,當(dāng)數(shù)組的空間未被填滿(mǎn)時(shí),如何表示空位處的元素?如何向數(shù)組中添加新的元素?如何刪除掉數(shù)組中原有的元素?等等。Java所提供的原生數(shù)組是無(wú)法解決這些問(wèn)題的,我們需要定制屬于自己的數(shù)組類(lèi)Array,即,基于Java的原生數(shù)組,二次封裝屬于我們自己的數(shù)組類(lèi)。

2.. 實(shí)現(xiàn)自定義數(shù)組類(lèi)Array所包含的基本方法:

  • public class Array {private int[] data; //設(shè)置為private,不希望用戶(hù)從外部直接獲取這些信息,防止用戶(hù)篡改數(shù)據(jù)private int size;//構(gòu)造函數(shù),傳入數(shù)組的容量capacity構(gòu)造Arraypublic Array(int capacity) {data = new int[capacity];size = 0;}//無(wú)參數(shù)構(gòu)造函數(shù),默認(rèn)數(shù)組容量capacity=10public Array() {this(10); //這里的capacity是IDE自動(dòng)添加的提示信息,實(shí)際不存在 }//獲取數(shù)組中的元素個(gè)數(shù)public int getSize() {return size;}//獲取數(shù)組的容量public int getCapacity() {return data.length;}//判斷數(shù)組是否為空public boolean isEmpty() {return size == 0;} }

    ?

3.. 實(shí)現(xiàn)向自定義數(shù)組中添加元素的方法

  • 向數(shù)組中添加元素的最簡(jiǎn)單的方法就是向數(shù)組的末尾添加元素
  • //向數(shù)組末尾添加一個(gè)新元素 public void addLast(int e) {if (size == data.length) {throw new IllegalArgumentException("AddLast failed. Array is full.");}data[size] = e;size++; }

    ?

  • 向數(shù)組中指定索引位置插入一個(gè)元素
  • //在index位置插入一個(gè)新元素e public void add(int index, int e) {if (size == data.length) {throw new IllegalArgumentException("Add failed. Array is full.");}if (index < 0 || index > size) {throw new IllegalArgumentException("Add failed. Require index >= 0 and index <= size");}for (int i = size - 1; i >= index; i--) {data[i + 1] = data[i];}data[index] = e;size++; }

    ?

  • 定義完向數(shù)組中指定索引位置插入一個(gè)元素的方法add之后,我們之前定義的向數(shù)組末尾插入元素的方法addLast其實(shí)可以調(diào)用add方法來(lái)實(shí)現(xiàn),我們調(diào)整addLast方法如下:
  • //向數(shù)組末尾添加一個(gè)新元素 public void addLast(int e) {add(size, e); }

    ?

  • 我們還可以調(diào)用add方法實(shí)現(xiàn)一個(gè)向數(shù)組開(kāi)頭添加一個(gè)新元素的方法
  • //向數(shù)組開(kāi)頭添加一個(gè)新元素 public void addFirst(int e) {add(0, e); }

    ?

4.. 實(shí)現(xiàn)在數(shù)組中查詢(xún)?cè)睾托薷脑氐姆椒?/p>

  • 實(shí)現(xiàn)自定義打印數(shù)組格式
  • @Override public String toString() { //覆蓋父類(lèi)的toString方法 StringBuilder res = new StringBuilder();res.append(String.format("Array: size=%d, capacity=%d\n", size, data.length));res.append('[');for (int i = 0; i < size; i++) {res.append(data[i]);if (i != size - 1) {res.append(", ");}}res.append(']');return res.toString(); }

    ?

  • 在main函數(shù)中進(jìn)行測(cè)試:
  • public class Main {public static void main(String[] args) {Array arr = new Array(20);for (int i = 0; i < 10; i++) {arr.addLast(i); //測(cè)試addLast方法 }System.out.println(arr);arr.add(1, 100); //測(cè)試add方法 System.out.println(arr);arr.addFirst(-1); //測(cè)試addFirst方法 System.out.println(arr);}}

    ?

  • 打印效果如下:
  • Array: size=10, capacity=20 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] Array: size=11, capacity=20 [0, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9] Array: size=12, capacity=20 [-1, 0, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    ?

  • 實(shí)現(xiàn)獲取指定索引元素的方法
  • //獲取index位置的元素 public int get(int index) {if (index < 0 || index >= size) {throw new IllegalArgumentException("Get failed. Index is illegal.");}return data[index]; }

    ?

  • 實(shí)現(xiàn)修改指定索引元素的方法
  • //修改index位置的元素為e public void set(int index, int e) {if (index < 0 || index >= size) {throw new IllegalArgumentException("Set failed. Index is illegal.");}data[index] = e; }

    ?

  • 實(shí)現(xiàn)查看數(shù)組中是否包含元素e的方法
  • //查找數(shù)組中是否存在元素e public boolean contains(int e) {for (int i = 0; i < size; i++) {if (data[i] == e) {return true;}}return false; }

    ?

  • 實(shí)現(xiàn)查看數(shù)組中指定元素的索引的方法,若找不到,返回-1
  • //查看數(shù)組中元素e的索引,若找不到元素e,返回-1 public int find(int e){for(int i=0;i<size;i++){if(data[i] == e){return i;}}return -1; }

    ?

  • 實(shí)現(xiàn)刪除數(shù)組中指定索引的元素的方法
  • //刪除掉index位置的元素,并且返回所刪除的元素 public int remove(int index) {if (index < 0 || index >= size) {throw new IllegalArgumentException("Add failed. Require index >= 0 and index < size");}int ret = data[index];for (int i = index + 1; i < size; i++) {data[i - 1] = data[i];}size--;return ret; }//刪除掉數(shù)組開(kāi)頭的元素,并返回所刪除的元素 public int removeFirst() {return remove(0); }//刪除掉數(shù)組末尾的元素,并返回所刪除的元素 public int removeLast() {return remove(size - 1); }//如果數(shù)組中有元素e,那么將其刪除,否則什么也不做 public void removeElement(int e) {int index = find(e);if (index != -1) {remove(index);} }

    ?

5.. 整理我們目前實(shí)現(xiàn)的業(yè)務(wù)邏輯:

  • public class Array {private int[] data; //設(shè)置為private,不希望用戶(hù)從外部直接獲取這些信息,防止用戶(hù)篡改數(shù)據(jù)private int size;//構(gòu)造函數(shù),傳入數(shù)組的容量capacity構(gòu)造Arraypublic Array(int capacity) {data = new int[capacity];size = 0;}//無(wú)參數(shù)構(gòu)造函數(shù),默認(rèn)數(shù)組容量capacity=10public Array() {this(10); //這里的capacity是IDE自動(dòng)添加的提示信息,實(shí)際不存在 }//獲取數(shù)組中的元素個(gè)數(shù)public int getSize() {return size;}//獲取數(shù)組的容量public int getCapacity() {return data.length;}//判斷數(shù)組是否為空public boolean isEmpty() {return size == 0;}//向數(shù)組末尾添加一個(gè)新元素epublic void addLast(int e) {add(size, e);}//向數(shù)組開(kāi)頭添加一個(gè)新元素epublic void addFirst(int e) {add(0, e);}//在index位置插入一個(gè)新元素epublic void add(int index, int e) {if (size == data.length) {throw new IllegalArgumentException("Add failed. Array is full.");}if (index < 0 || index > size) {throw new IllegalArgumentException("Add failed. Require index >= 0 and index <= size");}for (int i = size - 1; i >= index; i--) {data[i + 1] = data[i];}data[index] = e;size++;}//獲取index位置的元素public int get(int index) {if (index < 0 || index >= size) {throw new IllegalArgumentException("Get failed. Index is illegal.");}return data[index];}//修改index位置的元素為epublic void set(int index, int e) {if (index < 0 || index >= size) {throw new IllegalArgumentException("Set failed. Index is illegal.");}data[index] = e;}//查找數(shù)組中是否存在元素epublic boolean contains(int e) {for (int i = 0; i < size; i++) {if (data[i] == e) {return true;}}return false;}//查看數(shù)組中元素e的索引,若找不到元素e,返回-1public int find(int e) {for (int i = 0; i < size; i++) {if (data[i] == e) {return i;}}return -1;}//刪除掉index位置的元素,并且返回刪除的元素public int remove(int index) {if (index < 0 || index >= size) {throw new IllegalArgumentException("Remove failed. Index is illegal.");}int ret = data[index];for (int i = index + 1; i < size; i++) {data[i - 1] = data[i];}size--;return ret;}//刪除掉數(shù)組開(kāi)頭的元素,并返回刪除的元素public int removeFirst() {return remove(0);}//刪除掉數(shù)組末尾的元素,并返回刪除的元素public int removeLast() {return remove(size - 1);}//如果數(shù)組中有元素e,那么將其刪除,否則什么也不做public void removeElement(int e) {int index = find(e);if (index != -1) {remove(index);}}@Overridepublic String toString() { //覆蓋父類(lèi)的toString方法 StringBuilder res = new StringBuilder();res.append(String.format("Array: size=%d, capacity=%d\n", size, data.length));res.append('[');for (int i = 0; i < size; i++) {res.append(data[i]);if (i != size - 1) {res.append(", ");}}res.append(']');return res.toString();} }

    ?

6.. 現(xiàn)在我們的自定義數(shù)組的元素只允許為int類(lèi)型,我們需要進(jìn)行優(yōu)化,讓數(shù)組可以放置"任意"類(lèi)型的元素,解決這個(gè)問(wèn)題的技術(shù)稱(chēng)之為"泛型"。這里的"任意"加了引號(hào),這是因?yàn)樵贘ava中一個(gè)泛型類(lèi)并不能放置任意數(shù)據(jù)類(lèi)型的元素,泛型不能放置基本數(shù)據(jù)類(lèi)型,只能放置類(lèi)對(duì)象。在Java中,共有8中基本數(shù)據(jù)類(lèi)型:int、short、long、boolean、byte、char、float、double。如果將數(shù)組設(shè)置成泛型數(shù)組,那么就無(wú)法放置這些基本數(shù)據(jù)類(lèi)型了。為了解決這個(gè)問(wèn)題,Java語(yǔ)言為每個(gè)基本數(shù)據(jù)類(lèi)型都設(shè)計(jì)了一個(gè)包裝類(lèi),把本來(lái)不是類(lèi)對(duì)象的數(shù)據(jù)包裝成了類(lèi)對(duì)象。這8中基本數(shù)據(jù)類(lèi)型所對(duì)應(yīng)的包裝類(lèi)分別為:Int、Short、Long、Boolean、Byte、Char、Float、Double,在需要的情況下,包裝類(lèi)與其對(duì)應(yīng)的基本數(shù)據(jù)類(lèi)型可以自動(dòng)進(jìn)行轉(zhuǎn)換。

7.. 優(yōu)化后,Array類(lèi)的業(yè)務(wù)邏輯如下:
  • public class Array<E> {private E[] data; //設(shè)置為private,不希望用戶(hù)從外部直接獲取這些信息,防止用戶(hù)篡改數(shù)據(jù)private int size;//構(gòu)造函數(shù),傳入數(shù)組的容量capacity構(gòu)造Arraypublic Array(int capacity) {data = (E[]) new Object[capacity];size = 0;}//無(wú)參數(shù)構(gòu)造函數(shù),默認(rèn)數(shù)組容量capacity=10public Array() {this(10); //這里的capacity是IDE自動(dòng)添加的提示信息,實(shí)際不存在 }//獲取數(shù)組中的元素個(gè)數(shù)public int getSize() {return size;}//獲取數(shù)組的容量public int getCapacity() {return data.length;}//判斷數(shù)組是否為空public boolean isEmpty() {return size == 0;}//向數(shù)組末尾添加一個(gè)新元素epublic void addLast(E e) {add(size, e);}//向數(shù)組開(kāi)頭添加一個(gè)新元素epublic void addFirst(E e) {add(0, e);}//在index位置插入一個(gè)新元素epublic void add(int index, E e) {if (size == data.length) {throw new IllegalArgumentException("Add failed. Array is full.");}if (index < 0 || index > size) {throw new IllegalArgumentException("Add failed. Require index >= 0 and index <= size");}for (int i = size - 1; i >= index; i--) {data[i + 1] = data[i];}data[index] = e;size++;}//獲取index位置的元素public E get(int index) {if (index < 0 || index >= size) {throw new IllegalArgumentException("Get failed. Index is illegal.");}return data[index];}//修改index位置的元素為epublic void set(int index, E e) {if (index < 0 || index >= size) {throw new IllegalArgumentException("Set failed. Index is illegal.");}data[index] = e;}//查找數(shù)組中是否存在元素epublic boolean contains(E e) {for (int i = 0; i < size; i++) {if (data[i].equals(e)) {return true;}}return false;}//查看數(shù)組中元素e的索引,若找不到元素e,返回-1public int find(E e) {for (int i = 0; i < size; i++) {if (data[i].equals(e)) {return i;}}return -1;}//刪除掉index位置的元素,并且返回刪除的元素public E remove(int index) {if (index < 0 || index >= size) {throw new IllegalArgumentException("Remove failed. Index is illegal.");}E ret = data[index];for (int i = index + 1; i < size; i++) {data[i - 1] = data[i];}size--; //data[size]會(huì)指向一個(gè)類(lèi)對(duì)象,這部分空間不會(huì)被釋放loitering objectsdata[size] = null;return ret;}//刪除掉數(shù)組開(kāi)頭的元素,并返回刪除的元素public E removeFirst() {return remove(0);}//刪除掉數(shù)組末尾的元素,并返回刪除的元素public E removeLast() {return remove(size - 1);}//如果數(shù)組中有元素e,那么將其刪除,否則什么也不做public void removeElement(E e) {int index = find(e);if (index != -1) {remove(index);}}@Overridepublic String toString() { //覆蓋父類(lèi)的toString方法 StringBuilder res = new StringBuilder();res.append(String.format("Array: size=%d, capacity=%d\n", size, data.length));res.append('[');for (int i = 0; i < size; i++) {res.append(data[i]);if (i != size - 1) {res.append(", ");}}res.append(']');return res.toString();} }

    ?

8.. 再次在main方法中實(shí)例化我們的自定義數(shù)組,進(jìn)行測(cè)試:

  • public class Main {public static void main(String[] args) {Array<Integer> arr = new Array<>(20);for (int i = 0; i < 10; i++) {arr.addLast(i);}System.out.println(arr);arr.add(1, 100);System.out.println(arr);arr.addFirst(-1);System.out.println(arr);arr.remove(2);System.out.println(arr);arr.removeElement(4);System.out.println(arr);arr.removeFirst();System.out.println(arr);arr.removeLast();System.out.println(arr);} }

    ?

  • 輸出結(jié)果如下:
  • Array: size=10, capacity=20 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] Array: size=11, capacity=20 [0, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9] Array: size=12, capacity=20 [-1, 0, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9] Array: size=11, capacity=20 [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9] Array: size=10, capacity=20 [-1, 0, 1, 2, 3, 5, 6, 7, 8, 9] Array: size=9, capacity=20 [0, 1, 2, 3, 5, 6, 7, 8, 9] Array: size=8, capacity=20 [0, 1, 2, 3, 5, 6, 7, 8]

    ?

9.. 測(cè)試讓自定義數(shù)組去承載對(duì)象

  • public class Student {private String name;private int score;public Student(String studetName, int studentScore) {name = studetName;score = studentScore;}@Overridepublic String toString() {return String.format("Student(name: %s, score: %d)", name, score);}public static void main(String[] args) {Array<Student> arr = new Array<>();arr.addLast(new Student("XueZou", 98));arr.addLast(new Student("Guiche", 100));arr.addLast(new Student("QUiShui", 99));System.out.println(arr);} }

    ?

  • 輸出結(jié)果如下:
  • Array: size=3, capacity=10 [Student(name: XueZou, score: 98), Student(name: Guiche, score: 100), Student(name: QUiShui, score: 99)]

    ?

10.. 動(dòng)態(tài)數(shù)組,即數(shù)組的容量可伸縮
  • 修改add方法的業(yè)務(wù)邏輯,使自定義數(shù)組支持?jǐn)U容
  • //在index位置插入一個(gè)新元素e public void add(int index, E e) {if (index < 0 || index > size) {throw new IllegalArgumentException("Add failed. Require index >= 0 and index <= size");}if (size == data.length) {resize(2 * size); //擴(kuò)大為原容量的2倍 }for (int i = size - 1; i >= index; i--) {data[i + 1] = data[i];}data[index] = e;size++; }

    ?

  • 我們需要實(shí)現(xiàn)resize方法,業(yè)務(wù)邏輯如下:
  • private void resize(int newCapacity) {E[] newData = (E[]) new Object[newCapacity];for (int i = 0; i < size; i++) {newData[i] = data[i];}data = newData; }

    ?

  • 實(shí)現(xiàn)擴(kuò)容后,進(jìn)行測(cè)試:
  • public static void main(String[] args) {Array<Integer> arr = new Array<>();for (int i = 0; i < 10; i++) {arr.addLast(i);}System.out.println(arr);arr.add(1, 100);System.out.println(arr);arr.addFirst(-1);System.out.println(arr); }

    ?

  • 輸出效果如下:
  • Array: size=10, capacity=10 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] Array: size=11, capacity=20 [0, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9] Array: size=12, capacity=20 [-1, 0, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    ?

  • 修改remove方法,使數(shù)組中的元素減少到一定程度時(shí),自動(dòng)縮小數(shù)組容量
  • //刪除掉index位置的元素,并且返回刪除的元素 public E remove(int index) {if (index < 0 || index >= size) {throw new IllegalArgumentException("Remove failed. Index is illegal.");}E ret = data[index];for (int i = index + 1; i < size; i++) {data[i - 1] = data[i];}size--; //data[size]會(huì)指向一個(gè)類(lèi)對(duì)象,這部分空間不會(huì)被釋放loitering objectsdata[size] = null;if (size == data.length / 2) {resize(data.length / 2); //被利用的空間等于總空間的一半時(shí),將數(shù)組容量減少一半 }return ret; }

    ?

  • 實(shí)現(xiàn)自動(dòng)降低容量后,進(jìn)行測(cè)試:
  • public static void main(String[] args) {Array<Integer> arr = new Array<>();for (int i = 0; i < 10; i++) {arr.addLast(i);}System.out.println(arr);arr.add(1, 100);System.out.println(arr);arr.addFirst(-1);System.out.println(arr);arr.remove(2);System.out.println(arr);arr.removeElement(4);System.out.println(arr);arr.removeFirst();System.out.println(arr); }

    ?

  • 輸出效果如下:
  • Array: size=10, capacity=10 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] Array: size=11, capacity=20 [0, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9] Array: size=12, capacity=20 [-1, 0, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9] Array: size=11, capacity=20 [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9] Array: size=10, capacity=10 [-1, 0, 1, 2, 3, 5, 6, 7, 8, 9] Array: size=9, capacity=10 [0, 1, 2, 3, 5, 6, 7, 8, 9]

    ?

11.. 簡(jiǎn)單的時(shí)間復(fù)雜度分析
  • O(1), O(n), O(lgn), O(nlgn), O(n^2)
  • 大O描述的是算法的運(yùn)行時(shí)間和輸入數(shù)據(jù)之間的關(guān)系
  • 通常我們會(huì)說(shuō)下面的這段代碼的算法是O(n)的,n在這里簡(jiǎn)單理解為nums中的元素個(gè)數(shù),O(n)是說(shuō)下面這段代碼的運(yùn)行效率,與nums中的元素個(gè)數(shù)n是呈線(xiàn)性關(guān)系的,線(xiàn)性關(guān)系體現(xiàn)在n是一次方。
  • public static int sum(int[] nums) {int sum = 0;for (int num: nums) {sum += num;return sum;}

    ?

  • 按照這個(gè)思路我們對(duì)上面所實(shí)現(xiàn)的方法,挨個(gè)分析一下它們的算法的時(shí)間復(fù)雜度:添加操作中addLast(e)方法的時(shí)間復(fù)雜度是O(1),這表示我們的算法所消耗的時(shí)間與我們數(shù)據(jù)的規(guī)模沒(méi)有關(guān)系,這里所指的數(shù)據(jù)規(guī)模是我們數(shù)組中的元素個(gè)數(shù);addFirst(e)方法的時(shí)間復(fù)雜度是O(n),因?yàn)槊總€(gè)元素都需要向后移動(dòng)一位;add(index, e)方法的時(shí)間復(fù)雜度與index的具體取值相關(guān),它的時(shí)間復(fù)雜度也是O(n);綜合來(lái)看,添加操作是一個(gè)O(n)級(jí)別的算法。
  • 刪除操作中,removeLast(e)方法的時(shí)間復(fù)雜度是O(1);removeFirst(e)的時(shí)間復(fù)雜度是O(n);remove(index, e)的時(shí)間復(fù)雜度也是O(n);綜合來(lái)看,刪除操作的時(shí)間復(fù)雜度也是O(n)。
  • 修改操作set(index, e)的時(shí)間復(fù)雜度是O(1),這是數(shù)組的最大優(yōu)勢(shì),專(zhuān)業(yè)術(shù)語(yǔ)稱(chēng)為"支持隨機(jī)訪(fǎng)問(wèn)"。
  • 查詢(xún)操作中,get(index)方法的時(shí)間復(fù)雜度是O(1);find(e)方法和contains(e)方法的時(shí)間復(fù)雜度都是O(n)。
12.. 總的來(lái)看,對(duì)于動(dòng)態(tài)數(shù)組來(lái)說(shuō),增刪改查四種操作:
  • 增:時(shí)間復(fù)雜度O(n);
  • 刪:時(shí)間復(fù)雜度O(n);
  • 改:已知索引O(1),未知索引O(n);
  • 查:已知索引O(1),未知索引O(n);
  • 因此,索引具有語(yǔ)義時(shí),選擇數(shù)組是非常好的,我們可以通過(guò)索引輕松檢索數(shù)據(jù)中的內(nèi)容。
13.. resize的時(shí)間復(fù)雜度分析
  • 對(duì)于添加操作,如果我們只使用addLast方法,那么它的時(shí)間復(fù)雜度本來(lái)應(yīng)該是O(1),但是,由于存在resize方法,而resize方法的時(shí)間復(fù)雜度是O(n),所以addLast方法的時(shí)間復(fù)雜度就不是O(1)了,但是它的均攤復(fù)雜度是O(1);
  • 類(lèi)似的對(duì)于刪除操作,如果只使用removeLast方法,那么它的均攤復(fù)雜度也是O(1);
14.. 復(fù)雜度震蕩
  • 復(fù)雜度震蕩,是指我們?cè)跀?shù)組容量的臨界位置交替進(jìn)行添加和刪除操作,這會(huì)導(dǎo)致數(shù)組不斷執(zhí)行擴(kuò)容和縮容操作,而擴(kuò)容和縮容的時(shí)間復(fù)雜度都是O(n),出現(xiàn)這種問(wèn)題的原因在于,我們執(zhí)行removeLast方法后,resize得有點(diǎn)著急(Eager),解決方案是使用更加懶惰的策略(Lazy),簡(jiǎn)單理解就是,當(dāng)數(shù)組占用量剛好減到1/2時(shí),不著急縮容,等減到1/4時(shí),再觸發(fā)縮容,只縮1/2。
  • 我們需要稍微改動(dòng)一下remove方法,如下所示:
  • public E remove(int index) {if (index < 0 || index >= size) {throw new IllegalArgumentException("Remove failed. Index is illegal.");}E ret = data[index];for (int i = index + 1; i < size; i++) {data[i - 1] = data[i];}size--; //data[size]會(huì)指向一個(gè)類(lèi)對(duì)象,這部分空間不會(huì)被釋放loitering objectsdata[size] = null;if (size == data.length / 4 && data.length / 2 != 0) { //改動(dòng)在這里resize(data.length / 2); //被利用的空間等于總空間的一半時(shí),將數(shù)組容量減少一半 }return ret; }

    ?

轉(zhuǎn)載于:https://www.cnblogs.com/xuezou/p/9276945.html

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的第二十二篇 玩转数据结构——构建动态数组的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。