精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

數據結構—動態數組和時間復雜度分析

開發 后端
當我們在 java 中當創建一個數組時,會在內存中劃分出一塊 連續的內存,當有數據進入的時候會將數據 按順序的存儲在這塊連續的內存中。

[[395604]]

一、數組基礎

1.1 定義

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

1.2 創建流程

當我們在 java 中當創建一個數組時,會在內存中劃分出一塊 連續的內存,當有數據進入的時候會將數據 按順序的存儲在這塊連續的內存中。當需要讀取數組中的數據時,需要提供數組中的 索引,然后數組根據索引將內存中的數據取出來,返回給讀取程序。

把數據碼成一排進行存放:

所有的數據結構都支持幾個基本操作:讀取、插入、刪除數組索引可以有語意,也可以沒有語意,比如說 student[2],就代表是這個數組中的第三個學生。

因為數組在存儲數據時是按順序存儲的,存儲數據的內存也是連續的,所以數組最大的優點就是能夠 快速查詢,尋址讀取數據比較容易,但是插入和刪除就比較困難。

為什么數組最大的優點就是能夠 快速查詢。因為當我們在讀取數據時,只需要告訴數組獲取數據的索引位置就可以了,數組就會把對應位置的數據,讀取出來

插入和 刪除比較困難是因為這些存儲數據的內存是連續的,數組大小固定,插入和刪除都需要移動元素

例如:一個數組中編號 0>1>2>3>4這五個內存地址中都存了數組的數據,但現在你需要往4中插入一個數據,那就代表著從4開始,后面的所有內存中的數據都要往后移一個位置。

二、編寫我們自己的數組類

我們知道想要維護某一個數據,我們需要對這個數據有這最基本的 增、刪、改、查,這幾個基本功能,所以我們自己手動編寫的數組類,也是需要有用這幾個最基本的功能,雖然不會像 List、Map這些類,那么強大,但是對于我們普通的開發來說,基本是可以滿足,下圖所示就是我們一個基本的數組類,那么我們是如何對數組進行改造,來編寫一個屬于我們自己的數組類的呢,這里我們以 增加和刪除做重點講解,本文中的所有源碼會在最后貼出來,請往下看。

從上圖中我們可以得知,我們創建數組類的時候,需要三個元素 data、size、capacity,而我們所需要使用的數組,肯定是要能夠支持 多種數據類型,而不是單一的數據結構,因此,我們可以在設計類的時候,是需要加上泛型支持,讓我們的數據結構可以支持放置 任何數據類型。

data:需要傳遞的數據size:元素中的個數capacity:數組的初始容量

注意:我們上面所說的放置 任何數據類型,只能是類對象,不可以是基本數據類型,但是我們每個基本數據類型都有對應的包裝類,所以我們的基本類型也是可以使用的,不過只是使用的是它的包裝類

因此,我們在設計我們的數組類的時候,我們可以這么設計

  1. /** 
  2.  * @program:  
  3.  * @ClassName ArrayPlus 
  4.  * @description: 
  5.  * @author: lyy 
  6.  * @create: 2019-11-18 22:27 
  7.  * @Version 1.0 
  8.  **/ 
  9. public class ArrayPlus<E> { 
  10.  
  11.     private E[] data; 
  12.     private int size
  13.  
  14.     //構造函數,傳入數組的容量capacity 構造array 
  15.     public ArrayPlus(int capacity){ 
  16.         data = (E[])new Object[capacity]; 
  17.         size = 0; 
  18.     } 
  19.     //無參數的構造函數,傳入數組的容量capacity=10 
  20.     public ArrayPlus(){ 
  21.         this(10); 
  22.     } 
  23.  
  24.     //獲取元素中的個數 
  25.     public int getSize(){ 
  26.         return size
  27.     } 
  28.  
  29.     //獲取數組的容量 
  30.     public int getCapacity(){ 
  31.         return data.length; 
  32.     } 
  33.  
  34.     //返回數組是否為空 
  35.     public boolean isEmpty(){ 
  36.         return size == 0; 
  37.     } 
  38.  
  39.     @Override 
  40.     public String toString(){ 
  41.         StringBuffer res = new StringBuffer(); 
  42.         res.append(String.format("Array:Size = %d,capacity = %d\n",size,data.length)); 
  43.         res.append("["); 
  44.         for (int i = 0; i < size; i++) { 
  45.             res.append(data[i]); 
  46.             if(i != size - 1) 
  47.                 res.append(","); 
  48.         } 
  49.         res.append("]"); 
  50.         return res.toString(); 
  51.     } 
  52.  

2.1 數組添加元素

在數組中是如何添加數據的呢,首先我們需要創建一個 擁有初始容量的數組,當我們創建完成之后,size是指向第一個元素的,也就是 index=0的地方,當我們添加第一個數據后 也就是 data[0]=12后,我們的元素中的個數 size,需要往后挪一位的,也就是 size++的操作,每當我們操作一位,就需要將上面的操作重復執行,直到最后一個元素添加到我們的數組中。

如下圖所示:

知道了怎么操作,但是我們要如果通過代碼來完成呢?

首先我們要清楚在添加的時候, 在哪里?添加什么數據?,在哪里:我們要在數據的什么地方進行添加,也就是要添加到數組中的哪個下標—— index的地方,知道了在下標,我們只需要將添加的數據,添加到數組中為 index 的地方即可,除此之外,我們只需要對添加時,做一些基本的判斷就可以了,代碼如下:

  1. //在所有元素后添加一個新元素 
  2.   public void addLast(E e){ 
  3.       add(size,e); 
  4.   } 
  5.  
  6.   //想所有元素前添加一個新元素 
  7.   public void addFirst(E e){ 
  8.       add(0,e); 
  9.   } 
  10.  
  11.   //在第Index個位置插入一個新元素e 
  12.   public void add(int index,E e){ 
  13.       if(size == data.length) 
  14.           throw new IllegalArgumentException("Add failed . Array is full."); 
  15.  
  16.       if(index < 0 || index > size
  17.           throw new IllegalArgumentException("Add failed . Require index < 0 || index > size."); 
  18.  
  19.       for (int i = size - 1; i >= index ; i--) 
  20.           data[i+1] = data[i]; 
  21.  
  22.       data[index]  = e; 
  23.       size++; 
  24.   } 

測試代碼:

  1. public class Main2 { 
  2.  
  3.     public static void main(String[] args) { 
  4.         ArrayPlus<Integer> arr = new ArrayPlus<>(); 
  5.         for (int i = 12; i < 16; i++) 
  6.             arr.addLast(i); 
  7.         System.out.println(arr); 
  8.     } 

返回結果:

  1. Array:Size = 4,capacity = 10 
  2. [12,13,14,15] 

在數組中是如何執行插入呢?如下圖所示:

測試代碼:

  1. public static void main(String[] args) { 
  2.  
  3.        ArrayPlus<Integer> arr = new ArrayPlus<>(); 
  4.        for (int i = 12; i < 16; i++) 
  5.            arr.addLast(i); 
  6.        System.out.println(arr); 
  7.  
  8.        arr.add(1,100); 
  9.        System.out.println(arr); 
  10.  
  11.  
  12.    } 

返回結果:

  1. Array:Size = 4,capacity = 10 
  2. [12,13,14,15] 
  3. Array:Size = 5,capacity = 10 
  4. [12,100,13,14,15] 

2.2 數組刪除元素

如果我們想要刪除 索引為1的元素,是怎樣操作的呢,首先我們需要先將 索引為2的數據,覆蓋到 索引為1的元素上,再將 索引為3的數據放到 索引為2上,依次循環操作,直到最后一位元素,我們在將最后一位元素的數據設置為 null,這樣垃圾回收機制就會自動幫我們清除這個元素。整個過程就完成了刪除元素的功能,具體流程如下圖所示:


實現代碼:

  1. //查找數組中元素e所在的索引,如果不存在元素e,則返回-1 
  2.     public int find(E e){ 
  3.         for (int i = 0; i < size; i++) { 
  4.             if(data[i].equals(e)) 
  5.                 return i; 
  6.         } 
  7.         return -1; 
  8.     } 
  9.  
  10.  //從數組中刪除index位置的元素,返回刪除的元素 
  11.     public E remove(int index){ 
  12.         if(index < 0 || index >= size
  13.             throw new IllegalArgumentException("remove failed . Index is illegal."); 
  14.  
  15.         E ret = data[index]; 
  16.         for (int i = index+1 ; i < size; i++) 
  17.                 data[i - 1] = data[i]; 
  18.  
  19.         size--; 
  20.         // loitering objects != memory leak 
  21.         data[size] = null;//如果一旦使用新的元素,添加新的對象就會覆蓋掉 
  22.         return ret; 
  23.     } 
  24.  
  25.     //從數組中刪除第一個位置的元素,返回刪除的元素 
  26.     public E removeFirst(){ 
  27.         return remove(0); 
  28.     } 
  29.  
  30.     //從數組中刪除最后一個位置的元素,返回刪除的元素 
  31.     public E removeLast(){ 
  32.         return remove(size-1); 
  33.     } 
  34.  
  35.     //從數組中刪除元素e 
  36.     public void removeElement(E e){ 
  37.         int index = find(e); 
  38.         if(index != -1) 
  39.             remove(index); 
  40.  
  41.     } 

測試:

  1. import com.bj.array.ArrayPlus; 
  2.  
  3. public class Main2 { 
  4.  
  5.     public static void main(String[] args) { 
  6.  
  7.         ArrayPlus<Integer> arr = new ArrayPlus<>(); 
  8.         for (int i = 12; i < 16; i++) 
  9.             arr.addLast(i); 
  10.         System.out.println(arr); 
  11.  
  12.         arr.add(1,100); 
  13.         System.out.println(arr); 
  14.  
  15.         arr.remove(1); 
  16.         System.out.println(arr); 
  17.  
  18.  
  19.     } 
  20.  

返回示例:

  1. Array:Size = 4,capacity = 10 
  2. [12,13,14,15] 
  3. Array:Size = 5,capacity = 10 
  4. [12,100,13,14,15] 
  5. Array:Size = 4,capacity = 10 
  6. [12,13,14,15] 

我們看到結果已經把索引為1的刪除了,到這里我們已經完成了一大半了,還有一小點也是最重要的,就是當我們添加數據超過了我們的初始容量大小的時候,就會報錯,初始容量,無法添加超過的數據,那么我們應該怎么操作呢?其實很簡單,我們只需要給我們數組類,添加一個擴容的方法即可,當我們元素的個數等于數組長度的時候,我們就進行擴容,我們稱之為 動態數組。

2.3 動態數組

前邊我們講過的用new給基本類型和對象在運行時分配內存,但它們的已經在編譯時就已經確定下來,因為我們為之申請內存的數據類型在程序里有明確的定義,有明確的單位長度。  但是,總有些時候,必須要等到程序運行時才能確定需要申請多少內存,甚至還需要根據程序的運行情況追加申請更多的內存。從某種意義上講,這樣的內存管理才是真正的動態。下面,我將帶大家編寫一個程序為一個整數型數組分配內存,實現動態數組。  當你們看到下面這個圖的時候,有沒有想到什么,沒錯,有點像C++里面的指針

實現代碼:

  1. //在第Index個位置插入一個新元素e 
  2.    public void add(int index,E e){ 
  3.  
  4.        if(index < 0 || index > size
  5.            throw new IllegalArgumentException("Add failed . Require index < 0 || index > size."); 
  6.  
  7.        if(size == data.length) 
  8.            resize(2 * data.length); 
  9.  
  10.  
  11.        for (int i = size - 1; i >= index ; i--) 
  12.            data[i+1] = data[i]; 
  13.  
  14.        data[index]  = e; 
  15.        size++; 
  16.    } 
  17.  
  18.    private void resize(int newCapacity) { 
  19.        E[] newData = (E[])new Object[newCapacity]; 
  20.        for (int i = 0; i < size; i++) 
  21.            newData[i] = data[i]; 
  22.        data = newData; 
  23.    } 

動態數組測試:

  1. import com.bj.array.ArrayPlus; 
  2.  
  3. public class Main2 { 
  4.  
  5.     public static void main(String[] args) { 
  6.         ArrayPlus<Integer> arr = new ArrayPlus<>(); 
  7.         for (int i = 0; i < 10; i++) 
  8.             arr.addLast(i); 
  9.         System.out.println(arr); 
  10.  
  11.         arr.add(1,100); 
  12.         System.out.println(arr); 
  13.  
  14.         for (int i = 0; i < 6; i++) 
  15.             arr.remove(i); 
  16.  
  17.         arr.removeLast(); 
  18.         System.out.println(arr); 
  19.     } 

測試結果:

  1. Array:Size = 10,capacity = 10 
  2. [0,1,2,3,4,5,6,7,8,9] 
  3. Array:Size = 11,capacity = 20 
  4. [0,100,1,2,3,4,5,6,7,8,9] 
  5. Array:Size = 4,capacity = 10 
  6. [100,2,4,6] 

從結果中我們可以看到,當我們數組元素超過初始容量大小時,自動擴容到初始容量的 兩倍也就是20,當我們數組長度小于1/4的時候,為什么是1/4的時候而不是1/2的時候呢,下面我們會做詳細介紹。當我們數組長度小于1/4的時候,會自動縮回到初始10的容量,不會去占據大量的內存空間。

三、時間復雜度分析

3.1 基礎

五種常見的時間復雜度 1) O(1):常數復雜度, 最快的算法,數組的存取是O(1) 1) O(n):線性復雜度, 例如:數組, 以遍歷的方式在其中查找元素 1) O(logN):對數復雜度 1) O(nlogn):求兩個數組的交集, 其中一個是有序數組,A數組每一個元素都要在B數組中進行查找操作,每次查找如果使用二分法則復雜度是 logN 1) O(n2):平方復雜度,求兩個無序數組的交集

在這里,大O描述的是算法的運行時間和輸入數據之間的關系

3.2 舉例說明

大家可以看下面一個例子

  1. public static int sum(int[] nums){ 
  2.   int sum = 0; 
  3.   for(int num: nums) sum += num; 
  4.   return sum
  • 這個算法是 O(n) 復雜度的,其中 n是nums中的元素個數,算法和n呈線性關系
  • 為什么說他是 O(n)的時間復雜度呢,因為這個算法運行的時間的多少是和 nums中元素的個數成線性關系的,那么這個線性關系,表現在我們的 n 是一次方,它不是 O(n) 方的,也不是 O(n) 的立方,n 對應的是一次方。
  • 我們忽略常數,實際時間是:T=c1*n+c2c1:我們要把這個數據從 nums數組中取出來,其次我們還要把 sum這個數取出來,然后 num這個數和 sum相加,最終呢我們要這個結果扔回給 sum中c2:開始開辟了一個Int型的空間,我們把它叫 sum ,要把 0 初始化賦值給sum,在最終呢我們還要把這個 sum 給 return 回去

一方面把 c1 和 c2 具體分析出來是不大必要的,另一方面也是不太可能的,為什么說不可能呢?如果說把 num 從 nums 中取出來,基于 不同的語言,基于 不同的實現,它實際運行的 時間是不等的,就算轉換成機器碼,它對應的機器碼的指令數也有可能是不同的,就算是指令數是相同的,同樣的一個指令,在我們 cpu 的底層,你使用的 cpu 不同,很有可能,執行的操作也是不同的,所以在實際上我們可能說出 c1 是幾條指令,但是卻很難說出 c1 到底是多少,c2也是同理,正因為如此,我們在進行時間復雜度時,是忽略這些常數的。

忽略這些常數就意味著什么,就意味著這些 t=2*n+2和t=2000*n+10000算法這些都是 O(n) 的算法,見下面列表:換句話說他們都是線性數據的算法,也就是說我們這個算法消耗的時間是和我們輸入數據的規模成一個線性相關的, t=1*n*n+0也線性算法是和我們成平方關系的 ,他的性能比上面的差,因為他是 O(n^2)的

O(n)和O(n^2)并不代表說 O(n)的算法快于 O(n^2)的算法,我們要看 n 的常數,比如 n=3000的時候,或者 n>3000的時候, O(n^2)消耗的時間是遠遠大于 O(n)的,n越大 O(n)遠遠快于 O(n^2)O:描述的是一個算法,也就是說漸進時間復雜度當高階項和低階項同時出現的時候,低階項會被忽略,比如說:T=2*n*n+300n+10當中 2*n*n,是 O(n^2)級別的算法,屬于高階項, 300n是 O(n)的算法低階項,當n無窮大的時候,低階項起的作用很小。

3.3 分析動態數組的時間復雜度

3.3.1 添加操作

添加操作 總體來說屬于 O(n) 級別的復雜度,如下列表

在程序設計中,我們要采用最嚴謹的設計,需要考慮到最壞的情況,所以我們說添加操作時屬于 O(n)級別的復雜度,是因為我們在 addLast的時候,有可能會進行 resize的操作,我們從最壞的情況分析是對的,但是 addLast不可能每次都是進行 resize操作,比如 size 有十個,我們要添加十個元素后才會觸發一個 resize,我們要在添加十個元素才會觸發一個 resize,因此我們使用最壞情況進行分析的是不合理的,那么分析 addLast時間復雜度呢,請看下面小節。

3.3.2 resize的復雜度分析

總共進行了17次基本操作:9次添加操作8次元素轉移操作

  • 9次addLast操作,觸發resize,總共進行了17次基本操作,平均每次addLast操作,進行了2次基本操作
  • 假設 capacity = n,n+1 次addLast,觸發resize,總共進行了2n+1次基本操作,平均,每次addLast操作,進行了2次基本操作
  • 這樣均攤計算,時間復雜度是O(1)的,在這個例子里,這樣均攤計算,比計算最壞情況有意義
  • addLast 均攤復雜度是O(1)的,同理我們看 removeLast操作,均攤復雜度也是O(1)

3.3.3 復雜度震蕩

當我們數組容量滿了的時候,因為是動態數組,回去自動擴容,我們又馬上去remove 一個操作的時候,因為數組容量小于 初始容量的一半的時候,又會 自動 resize縮減為一半的大小,如此操作,就會一個問題,就是我們在 removeLast的時候 resize 過于著急(Eager)

解決方案:Lazy,懶散的,其實也很簡單,如下圖所示:

當我們的 size == capacity /4 時候,才將capacity 減半,實現方式如下:

  1. //從數組中刪除index位置的元素,返回刪除的元素 
  2.     public E remove(int index){ 
  3.         if(index < 0 || index >= size
  4.             throw new IllegalArgumentException("remove failed . Index is illegal."); 
  5.  
  6.         E ret = data[index]; 
  7.         for (int i = index+1 ; i < size; i++) 
  8.                 data[i - 1] = data[i]; 
  9.  
  10.         size--; 
  11.         // loitering objects != memory leak 
  12.         data[size] = null;//如果一旦使用新的元素,添加新的對象就會覆蓋掉 
  13.  
  14.         if(size == data.length / 4 && data.length / 2 != 0) 
  15.             resize(data.length / 2); 
  16.  
  17.         return ret; 
  18.     } 

完整代碼:

  1. package com.bj.array; 
  2.  
  3.  
  4. /** 
  5.  * @program: Data-Structures 
  6.  * @ClassName Array 
  7.  * @description: 
  8.  * @author: lyy 
  9.  * @create: 2019-11-18 22:27 
  10.  * @Version 1.0 
  11.  **/ 
  12. public class ArrayPlus<E> { 
  13.  
  14.     private E[] data; 
  15.     private int size
  16.  
  17.     //構造函數,傳入數組的容量capacity 構造array 
  18.     public ArrayPlus(int capacity){ 
  19.         data = (E[])new Object[capacity]; 
  20.         size = 0; 
  21.     } 
  22.     //無參數的構造函數,傳入數組的容量capacity=10 
  23.     public ArrayPlus(){ 
  24.         this(10); 
  25.     } 
  26.  
  27.     //獲取元素中的個數 
  28.     public int getSize(){ 
  29.         return size
  30.     } 
  31.  
  32.     //獲取數組的容量 
  33.     public int getCapacity(){ 
  34.         return data.length; 
  35.     } 
  36.  
  37.     //返回數組是否為空 
  38.     public boolean isEmpty(){ 
  39.         return size == 0; 
  40.     } 
  41.  
  42.     //在所有元素后添加一個新元素 
  43.     public void addLast(E e){ 
  44.         add(size,e); 
  45.     } 
  46.  
  47.     //想所有元素前添加一個新元素 
  48.     public void addFirst(E e){ 
  49.         add(0,e); 
  50.     } 
  51.  
  52.     //在第Index個位置插入一個新元素e 
  53.     public void add(int index,E e){ 
  54.  
  55.         if(index < 0 || index > size
  56.             throw new IllegalArgumentException("Add failed . Require index < 0 || index > size."); 
  57.  
  58.         if(size == data.length) 
  59.             resize(2 * data.length); 
  60.  
  61.  
  62.         for (int i = size - 1; i >= index ; i--) 
  63.             data[i+1] = data[i]; 
  64.  
  65.         data[index]  = e; 
  66.         size++; 
  67.     } 
  68.  
  69.  
  70.  
  71.     //獲取index索引位置的元素 
  72.    public E get(int index){ 
  73.         if(index < 0 || index >= size
  74.             throw new IllegalArgumentException("Get failed . Index is illegal."); 
  75.  
  76.         return data[index]; 
  77.     } 
  78.  
  79.     //修改index索引位置的元素為e 
  80.     public void set(int index,E e){ 
  81.         if(index < 0 || index >= size
  82.             throw new IllegalArgumentException("Set failed . Index is illegal."); 
  83.  
  84.          data[index] = e; 
  85.     } 
  86.  
  87.     //查找數組中是否有元素e 
  88.     public boolean contains(E e){ 
  89.         for (int i = 0; i < size; i++) { 
  90.             if(data[i].equals(e)) 
  91.                 return true
  92.         } 
  93.         return false
  94.     } 
  95.  
  96.     //查找數組中元素e所在的索引,如果不存在元素e,則返回-1 
  97.     public int find(E e){ 
  98.         for (int i = 0; i < size; i++) { 
  99.             if(data[i].equals(e)) 
  100.                 return i; 
  101.         } 
  102.         return -1; 
  103.     } 
  104.  
  105.     //從數組中刪除index位置的元素,返回刪除的元素 
  106.     public E remove(int index){ 
  107.         if(index < 0 || index >= size
  108.             throw new IllegalArgumentException("remove failed . Index is illegal."); 
  109.  
  110.         E ret = data[index]; 
  111.         for (int i = index+1 ; i < size; i++) 
  112.                 data[i - 1] = data[i]; 
  113.  
  114.         size--; 
  115.         // loitering objects != memory leak 
  116.         data[size] = null;//如果一旦使用新的元素,添加新的對象就會覆蓋掉 
  117.  
  118.         if(size == data.length / 4 && data.length / 2 != 0) 
  119.             resize(data.length / 2); 
  120.  
  121.         return ret; 
  122.     } 
  123.  
  124.     //從數組中刪除第一個位置的元素,返回刪除的元素 
  125.     public E removeFirst(){ 
  126.         return remove(0); 
  127.     } 
  128.  
  129.     //從數組中刪除最后一個位置的元素,返回刪除的元素 
  130.     public E removeLast(){ 
  131.         return remove(size-1); 
  132.     } 
  133.  
  134.     //從數組中刪除元素e 
  135.     //思考?如果返回是否刪除成功 2、如果存在重復數據,如何刪除多個 
  136.     public void removeElement(E e){ 
  137.         int index = find(e); 
  138.         if(index != -1) 
  139.             remove(index); 
  140.  
  141.     } 
  142.  
  143.     @Override 
  144.     public String toString(){ 
  145.         StringBuffer res = new StringBuffer(); 
  146.         res.append(String.format("Array:Size = %d,capacity = %d\n",size,data.length)); 
  147.         res.append("["); 
  148.         for (int i = 0; i < size; i++) { 
  149.             res.append(data[i]); 
  150.             if(i != size - 1) 
  151.                 res.append(","); 
  152.         } 
  153.         res.append("]"); 
  154.         return res.toString(); 
  155.     } 
  156.  
  157.     private void resize(int newCapacity) { 
  158.         E[] newData = (E[])new Object[newCapacity]; 
  159.         for (int i = 0; i < size; i++) 
  160.             newData[i] = data[i]; 
  161.         data = newData; 
  162.     } 
  163.  

 有時候更"懶",會讓我們的程序更方便點,我是牧小農,大家加油!

 

責任編輯:姜華 來源: 牧小農
相關推薦

2014-07-01 15:49:33

數據結構

2014-12-10 09:23:14

2020-12-30 05:35:56

數據結構算法

2020-11-30 06:26:31

算法時間表示法

2024-04-25 08:33:25

算法時間復雜度空間復雜度

2018-12-18 10:11:37

軟件復雜度軟件系統軟件開發

2021-01-05 10:41:42

算法時間空間

2009-07-09 10:45:16

C#基本概念復雜度遞歸與接口

2021-10-15 09:43:12

希爾排序復雜度

2019-11-18 12:41:35

算法Python計算復雜性理論

2019-11-23 23:30:55

Python數據結構時間復雜性

2021-09-17 10:44:50

算法復雜度空間

2022-08-25 11:00:19

編程系統

2024-05-20 09:04:29

時間復雜度代碼

2023-10-30 01:08:35

微信紅包高性能架構

2024-08-22 14:39:34

2022-02-13 20:04:04

鏈表節點代碼

2023-10-05 11:08:53

2019-12-24 09:46:00

Linux設置密碼

2015-10-13 09:43:43

復雜度核心
點贊
收藏

51CTO技術棧公眾號

色狠狠综合天天综合综合| 国产一区二区在线看| 亚洲精品狠狠操| 国产成人av影视| 哥也色在线视频| 成人h动漫精品一区二| 日韩av片免费在线观看| 神马午夜精品91| 国内精品偷拍| 欧美日韩一区二区三区四区五区 | 美女久久久久| 在线电影一区二区三区| 缅甸午夜性猛交xxxx| av网页在线| 成人久久视频在线观看| 国产美女91呻吟求| 日韩欧美国产亚洲| 91欧美在线| 国产丝袜一区二区三区| 国产黄色一区二区三区| 欧美日韩尤物久久| 亚洲国产日韩一级| 永久域名在线精品| 亚洲色偷精品一区二区三区| 韩国毛片一区二区三区| 欧美一区视频在线| 久久久国产精华液| 日本久久一二三四| 亚洲免费一在线| 逼特逼视频在线观看| 亚洲一区二区三区久久久| 色综合久久中文字幕综合网 | 伦xxxx在线| 久久精品亚洲精品国产欧美| 国产福利一区二区三区在线观看| 亚洲一区二区三区高清视频| 香蕉久久夜色精品国产| 欧美精品videosex极品1| 91无套直看片红桃在线观看| 亚洲成人一品| 亚洲成人激情在线观看| 美女流白浆视频| 国产999精品在线观看| 欧美日韩国产一区| 亚洲黄色av网址| 亚洲十八**毛片| 午夜精品一区二区三区电影天堂| 六月婷婷激情网| 国产福利在线视频| 国产亚洲欧美色| 免费成人深夜夜行视频| 五月婷婷免费视频| 97久久人人超碰| 国内精品**久久毛片app| 亚洲黄色精品视频| 国产·精品毛片| 成人国产一区二区| 精品国产无码AV| 国产福利精品导航| 91精品国产高清久久久久久91裸体 | 国产视频911| 日韩伦理一区二区三区av在线| 四虎影视精品成人| 99re6这里只有精品视频在线观看| 国产日韩一区二区三区| 手机av免费在线观看| 成人av电影在线观看| 国产伦精品一区二区三区四区视频 | 国产伦理一区| 人九九综合九九宗合| 中文字幕一区二区人妻电影| 久久综合九色| 国产精品一二区| 91av久久久| 国产在线精品一区二区夜色| 亚洲在线观看视频| 亚洲欧美国产高清va在线播放| 成人综合激情网| 国产一区二区高清不卡| 毛片在线能看| 国产精品久久久久久久久久免费看| 中文字幕一区二区三区乱码| 亚洲第一图区| 精品久久久久久久久久久久久久| 国产精品第12页| 欧美偷拍一区二区三区| 欧美自拍偷拍第一页| 99在线精品一区二区三区| 久久久久无码国产精品一区| 成年人视频免费在线观看| 中文字幕一区二区三中文字幕| 午夜久久久久久久久久久| 97蜜桃久久| 在线欧美一区二区| 天天干天天曰天天操| 国产亚洲成av人片在线观黄桃| 亚洲欧美国产精品久久久久久久 | 欧美激情久久久久久久久久久| 国产视频精品久久久| 99久久99久久精品免费| 欧美喷水视频| 国产福利精品视频| www.色婷婷.com| 久久免费的精品国产v∧| 一区二区三区四区不卡| √天堂8资源中文在线| 欧美色图第一页| 丰满少妇xbxb毛片日本| 日韩成人三级| 91精品国产91久久久久久久久 | 九色91在线视频| 在线观看av的网站| 精品久久久久久| 亚洲av毛片在线观看| 竹菊久久久久久久| 九九热在线精品视频| 国产99免费视频| 成人不卡免费av| 一区精品在线| 另类激情视频| 精品国产一二三区| 三级黄色录像视频| 久久久噜噜噜| 国产日韩亚洲精品| 香蕉久久aⅴ一区二区三区| 91久久一区二区| 91精品小视频| 国内精品福利| 91网在线免费观看| av在线播放网| 色综合视频在线观看| 黄色av电影网站| 亚洲精品小说| 国产精品直播网红| 国内三级在线观看| 狠狠躁夜夜躁人人爽超碰91| 亚洲精品久久一区二区三区777| 欧美第一精品| 国产精品27p| 欧美高清电影在线| 精品欧美aⅴ在线网站| 国产精品91av| 综合一区在线| 成人欧美在线观看| 免费黄网站在线播放| 在线精品亚洲一区二区不卡| 中日韩精品一区二区三区| 99热免费精品在线观看| 国产精品中出一区二区三区| 免费在线国产视频| 精品久久久久一区| 久一区二区三区| 国产69精品久久777的优势| 51xx午夜影福利| 精品91福利视频| 久久综合伊人77777| 国产精品毛片一区视频播| 日韩美女视频一区| 色18美女社区| 欧美一区久久| 国产精品久久7| 91九色porn在线资源| 337p日本欧洲亚洲大胆精品| 日本少妇裸体做爰| av电影在线观看完整版一区二区| 黄页网站在线观看视频| 日韩美女毛片| 国产精品av电影| 天堂中文а√在线| 欧美日韩一本到| 国产在线一卡二卡| 国产 欧美在线| 久久成人免费观看| 羞羞色国产精品网站| 国产精品ⅴa在线观看h| 黄色小网站在线观看| 日韩欧美国产一区二区在线播放| 精品在线视频免费| 久久综合丝袜日本网| 网站一区二区三区| 在线精品国产| 精品无人区一区二区三区| 老司机成人影院| 久久久久www| 蜜臀久久精品久久久久| 在线一区二区三区做爰视频网站| 顶级黑人搡bbw搡bbbb搡| 国产精品性做久久久久久| 午夜免费福利小电影| 青青草综合网| 国产伦精品一区二区三区视频黑人 | 国产精品传媒在线观看| 亚洲欧美日韩一区| 亚洲精品国产成人av在线| 久久久久久穴| 日韩人妻一区二区三区蜜桃视频| 美女一区二区在线观看| 国产精品久久久久久久7电影| 国产一区久久精品| 亚洲精品一二区| 97精品久久人人爽人人爽| 午夜精品一区二区三区免费视频| 国产性猛交xx乱| 成人黄色在线网站| 国产三级三级看三级| 亚洲国产一区二区三区高清| 亚洲免费视频一区| 看全色黄大色大片免费久久久| 国产精品毛片a∨一区二区三区|国| 日韩专区av| 中文字幕在线国产精品| 手机av免费在线观看| 91精品国产综合久久小美女| 一二三区免费视频| 亚洲超碰精品一区二区| 欧美性生交大片| 久久久无码精品亚洲日韩按摩| 久久久久久国产精品日本| 日韩av中文字幕一区二区三区| 99国产精品白浆在线观看免费| 精品亚洲成人| 看高清中日韩色视频| 99re8这里有精品热视频免费| 国产精品露脸av在线| 在线观看爽视频| 久久久久久久久久婷婷| www免费视频观看在线| 欲色天天网综合久久| 色就是色亚洲色图| 精品国产乱码91久久久久久网站| 亚洲综合网av| 欧美影院精品一区| 黄色在线视频网址| 亚洲国产精品麻豆| 校园春色 亚洲| 亚洲天堂久久久久久久| 国产精品久久久久久成人| 久久综合九色综合久久久精品综合| 东京热av一区| 国产成人精品一区二区三区四区 | 自拍偷自拍亚洲精品被多人伦好爽| 欧美激情综合亚洲一二区| 超碰在线观看免费| 久久韩国免费视频| 蜜芽在线免费观看| 日韩专区在线观看| 成人午夜电影在线观看| 亚洲人成绝费网站色www| 涩涩视频在线观看免费| 精品亚洲一区二区| 每日更新在线观看av| 亚洲性猛交xxxxwww| 久青草国产在线| 亚洲午夜未删减在线观看| 国产中文在线观看| 国产一区二区三区日韩欧美| 国产视频网站在线| 亚洲性视频网址| 91亚洲欧美| 色噜噜久久综合伊人一本| 欧美成年黄网站色视频| 久久久精品2019中文字幕神马| 秋霞午夜在线观看| 九九热精品在线| 97在线超碰| 欧美一级免费看| av高清一区| 91精品国产综合久久香蕉922| 国产va免费精品观看精品| 亚洲自拍小视频免费观看| 97se亚洲| 久久天天狠狠| 日韩欧美一区二区三区免费看| 国产精品jizz在线观看老狼| 欧美日韩四区| 亚洲欧洲日产国码无码久久99| 免费在线亚洲| 视频在线观看免费高清| 国产精品一区免费在线观看| 尤物网站在线观看| 久久精品综合网| 99成人在线观看| 亚洲一区二区三区四区五区中文| 日本三级一区二区| 色综合久久久久综合99| 91福利免费视频| 精品国产凹凸成av人网站| 青春有你2免费观看完整版在线播放高清| 一区二区福利视频| 在线观看男女av免费网址| 91精品国产高清自在线| 男女啪啪999亚洲精品| 成人动漫在线观看视频 | 伊人久久大香线蕉av一区| 欧美日韩国产探花| 成人在线免费观看av| 精品一区二区三区av| 国产精品嫩草av| 1024亚洲合集| www欧美在线| 欧美一区二区福利在线| 黑人与亚洲人色ⅹvideos| 欧美日韩成人在线播放| 亚洲a∨精品一区二区三区导航| 亚洲最大av网| 成人在线免费视频观看| 美女黄色免费看| 日韩精品亚洲专区| 日韩精品人妻中文字幕有码 | 麻豆国产精品777777在线| www.啪啪.com| 亚洲人精品午夜| 国产一区二区视频网站| 亚洲黄色在线看| av片在线观看免费| 国产精品香蕉av| 国产精品久久久久久久久久白浆| 亚洲乱码一区二区三区三上悠亚 | 亚洲欧洲无码一区二区三区| 精品成人免费视频| 日韩一区二区三区高清免费看看| 国产黄在线播放| 午夜精品久久久久久99热| 国产精选久久| 亚洲欧洲一区二区在线观看| 米奇777在线欧美播放| 在线xxxxx| 亚洲最大成人综合| 中文字幕一区二区三区波野结 | 国产资源在线看| 欧美亚洲视频在线观看| 中文字幕区一区二区三| 在线天堂一区av电影| 欧美aaaaaa午夜精品| 成人午夜剧场视频网站| 欧美日韩国产一中文字不卡| xxxx国产精品| 久久最新资源网| 欧美.com| 中文字幕一区二区三区乱码 | 成年人小视频在线观看| 有码一区二区三区| 国产女人18毛片18精品| 久久精品欧美视频| 日日夜夜亚洲精品| 在线视频欧美一区| 国产一区二区在线看| 91嫩草|国产丨精品入口| 欧美一区二区三区视频| 成人video亚洲精品| 91色在线视频| 欧美精品91| 韩国av中国字幕| 亚洲成人中文在线| 少妇人妻精品一区二区三区| 国内精品小视频| 日本久久成人网| 青青草原av在线播放| 国产亚洲制服色| 免费在线不卡av| 久久久国产精品一区| www999久久| www.av91| 91日韩在线专区| 蜜臀尤物一区二区三区直播 | 日本高清在线观看视频| 成人情视频高清免费观看电影| 狠狠综合久久| 国产精品嫩草av| 在线观看www91| 久久黄色美女电影| 国产精品亚洲一区| 久久国产精品99国产| 女女互磨互喷水高潮les呻吟| 欧美日韩视频专区在线播放| 成人在线观看免费网站| 国产精品日韩一区二区| 国产精品婷婷| 欧美美女性生活视频| 日韩免费福利电影在线观看| 黄在线观看免费网站ktv| 青青草原亚洲| 国产一区二区福利视频| 日本一区二区欧美| 伊人久久精品视频| 日本精品一区二区三区在线观看视频| 久操网在线观看| 欧美国产一区二区在线观看| 国产视频在线观看视频| 欧美性受xxxx黑人猛交| 欧美激情电影| 最新在线黄色网址| 欧美日韩一区二区三区在线看| 久草在线资源站资源站| 日本在线一区| 国产iv一区二区三区| 极品国产91在线网站| 九九热精品在线| 日本在线电影一区二区三区| 一级黄色电影片|