1. 程式人生 > 其它 >基礎資料結構(一) 陣列

基礎資料結構(一) 陣列

基礎資料結構(一):陣列

面試經典:

​ 給你一個檔案裡面包含全國人民的年齡資料,現在要你統計每一個年齡有多少人?
給定機器為單臺+2CPU+2G記憶體。不得使用現成的容器,比如map等

​ 在以上情況下你該如何以最高效的方法來解決這個問題?

解題思路

首先排序演算法能否使用呢?遍歷

從演算法時間複雜度分析 最快O(N) N=14億 想象一下能排的出來嗎?

並且記憶體不夠(6G塞不了2G)

這時候我們就能使用一種非常簡單的方法處理 【陣列演算法】

全國人民 14億

年齡 0~180

int data [] = new int[180];

這不就OK了嗎?

data[0]++; // 0 歲人加一  data[0] 的值就表示0歲有多少人

下面看程式碼 (最主要的就是讀取檔案時一行一行讀)

InputStreamReader isr = new InputStreamReader(new FileInputStream(fileName), "UTF-8");
BufferedReader br = new BufferedReader(isr);
int tot = 0 ;	//21億
int data [] = new int[200];
while((str = br.readLine()) != null){		//一行一行的讀 O(n)
    int age = Integer.parseInt(str);
    data[age] ++ ;
    tot ++ ;
}

這裡突出的就是陣列的一個最優特點【下標】

陣列是什麼?

  • 有序的元素序列
  • 用於儲存多個同類型資料的集合 通常使用【Array】表示 也叫做線性表

陣列特點

  • 陣列是相同資料型別的元素的集合。
  • 陣列中的各元素的儲存是有先後順序的,它們在記憶體中按照這個先後順序連續存放在一起。記憶體地址
  • 陣列元素用整個陣列的名字和它自己在陣列中的順序位置來表示。例如,a[0]表示名字為a的陣列中的第一個元素,a[1]代表陣列a的第二個元素,以此類推。

陣列表現形式

int[] a; // 一維陣列
int[][] b; // 多維陣列

隨機訪問

陣列是連續的記憶體空間和相同型別的資料

正是因為這兩個限制,它才有了一個非常重要的特性:【隨機訪問】

但有利就有弊,這兩個限制也讓陣列的很多操作變得非常低效,

比如要想在陣列中刪除、插入一個數據,為了保證連續性,就需要做大量的資料搬移工作。

隨機訪問的重要應用:查詢,面試重點

如何實現一個數組的增刪改查?

package model;

/**
 * @author : ywb
 * @date : 2022-04-12 14:01
 */
public class MyArray {
    final int size;		//陣列的長度
    final int[] data;
    private int index;		//當前已經存的資料大小

    public MyArray(int size) {
        this.size = size;
        data = new int[size];		//分配的記憶體空間{0,0,0,0,0}
        index = 0;
    }
    public void print(){
        System.out.println("index:" + index);
        Arrays.stream(data).forEach(System.out::print);
        System.out.println();
    }
    public void insert(int loc,int n){		//時間複雜度 O(n);
        if(index ++ < size){
            for(int i = size - 1; i > loc ; i --){	//為什麼不能寫size 0~size-1 如果loc是0 O(n),O(1)=>O(n)
                data[i] = data[i - 1];	//把資料往後移一個
            }
            data[loc] = n;
        }
        //擴容 會把size*2 0.75
    }
    public void delete(int loc){	//O(n)
        for(int i = loc ; i < size ; i++){
            if(i != size - 1){		//怕越界所以加一個判斷
                data[i] = data[i + 1];
            }else{
                data[i] = 0;			//預設為0 就是沒存資料的
            }
        }
        index -- ;
    }

    public void update(int loc,int n){  //O(1)
        data[loc] = n;
    }

    public int get(int loc){		//O(1)
        return data[loc];
    }
}

實現總結

根據實現可以看出

插入 刪除 屬於複製新陣列 資料挪移 時間複雜度O(n)

查詢 修改 使用下標訪問 時間複雜度O(1)

所以 【增刪】慢 【查改】 快

下面來說下ArrayList吧?

ArrayList 和陣列

首先本質都是一樣的 陣列

但是ArrayList 是JDK封裝了。不需要管擴容等操作

陣列的話就要你全部操作

兩者之間應該如何選用?

不知道資料大小的肯定選ArrayList.

如果你知道資料的大小而且你又非常關注效能那就用陣列。

總結

陣列是一個最基礎最簡單的資料結構

它是儲存相同型別的一組資料,最大的兩個特點就是

【下標】和【隨機訪問】缺點就是插入和刪除是很慢的,時間複雜度為O(n)。