玩轉數據結構(01)--數組

1、數據結構分類:

1.線性結構:數組、棧、隊列、鏈表、哈希表...java

2.樹結構:二叉樹、二分搜索樹、AVL、紅黑樹、Treap、Splay、、Trie、線段樹、K-D樹、並查集、哈夫曼樹...數組

3.圖結構:鄰接矩陣、鄰接表數據結構

2、數組

1.定義:把數據碼成一排進行存放app

2.圖解:ide

3.示例代碼  Main.java函數

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;

        int[] scores = new int[]{100, 99, 66};//聲明數組並賦值
        for(int i = 0 ; i < scores.length ; i ++)
            System.out.println(scores[i]);//經過索引訪問的方式來訪問數組的變量

        for(int score: scores)  //數組具備可遍歷的特性
            System.out.println(score);

        scores[0] = 96;  ////經過索引訪問的方式來修改數組的變量

        for(int i = 0 ; i < scores.length ; i ++)
            System.out.println(scores[i]);
    }
}

輸出:ui

4.數組基礎this

數組優勢:快速查詢;spa

索引能夠用語義,也能夠沒有語義;數組最好應用於「索引有語義」的狀況;3d

但並不是全部有語義的索引都適用於數組;例: 身份證號就不適合,佔用空間太大;

數組也能夠處理 「索引沒有語義 」的狀況;主要討論該狀況下數組的使用;

5.二次封裝本身的數組

(Java 自身的數組是靜態數組,不具備對內存空間增、刪、改、查功能;故二次分裝本身的內存,爲動態數組

例圖:

本身的數組類: Array

data:數組名稱

size:數組中實際裝入元素的長度

capacity:數組定義的長度(容量)

代碼示例:Array.java

public class Array {

    private int[] data;	//定義int 型數組 data
    private int size;	//data數組中有效元素的數量

    // 構造函數,傳入數組的容量capacity構造Array
    public Array(int capacity){
        data = new int[capacity];
        size = 0;
    }

    // 無參數的構造函數,默認數組的容量capacity=10
    public Array(){
        this(10);
    }

    // 獲取數組的容量
    public int getCapacity(){
        return data.length;
    }

    // 獲取數組中的元素個數
    public int getSize(){
        return size;
    }

    // 返回數組是否爲空
    public boolean isEmpty(){
        return size == 0;
    }
}

6.向數組中添加元素

向數組末添加元素:賦值給data[size],而後 size+1(右移便可)

向指定位置添加元素:將索引爲1的值及後面的值都向後移動;先將 size-1 的元素移動到size上,直到將值放入 1 中,最後 size+1

移動100

插入到 1 的位置

示例代碼:Array.java

public class Array {

    private int[] data;
    private int size;

    // 構造函數,傳入數組的容量capacity構造Array
    public Array(int capacity){
        data = new int[capacity];
        size = 0;
    }

    // 無參數的構造函數,默認數組的容量capacity=10
    public Array(){
        this(10);
    }

    // 獲取數組的容量
    public int getCapacity(){
        return data.length;
    }

    // 獲取數組中的元素個數
    public int getSize(){
        return size;
    }

    // 返回數組是否爲空
    public boolean isEmpty(){
        return size == 0;
    }

    // 向全部元素後添加一個新元素
    public void addLast(int e){

//        if(size == data.length)           //判斷數組是否裝滿了
//            throw new IllegalArgumentException("AddLast failed. Array is full.");
//
//        data[size] = e;
//        size ++;
        add(size, e);	//複用 add 方法
    }

    // 在全部元素前添加一個新元素
    public void addFirst(int e){
        add(0, e);
    }

    // 在index索引的位置插入一個新元素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; 	//e 覆蓋掉原來索引的值

        size ++;
    }

}

7.數組中查詢元素和修改元素

示例代碼:Array.java

public class Array {

    private int[] data;
    private int size;

    // 構造函數,傳入數組的容量capacity構造Array
    public Array(int capacity){
        data = new int[capacity];
        size = 0;
    }

    // 無參數的構造函數,默認數組的容量capacity=10
    public Array(){
        this(10);
    }

    // 獲取數組的容量
    public int getCapacity(){
        return data.length;
    }

    // 獲取數組中的元素個數
    public int getSize(){
        return size;
    }

    // 返回數組是否爲空
    public boolean isEmpty(){
        return size == 0;
    }

    // 向全部元素後添加一個新元素
    public void addLast(int e){
        add(size, e);
    }

    // 在全部元素前添加一個新元素
    public void addFirst(int e){
        add(0, e);
    }

    // 在index索引的位置插入一個新元素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 ++;
    }

    // 獲取index索引位置的元素
    public int get(int index){
        if(index < 0 || index >= size)
            throw new IllegalArgumentException("Get failed. Index is illegal.");
        return data[index];
    }

    // 修改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;
    }

    @Override  //覆蓋父類的方法
    public String toString(){

        StringBuilder res = new StringBuilder();	//新建字符串 res
        res.append(String.format("Array: size = %d , capacity = %d\n", size, data.length));	//初始化字符串res
        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.java

public class Main {

    public static void main(String[] args) {

        Array arr = new Array(20);	//添加容量爲20
        for(int i = 0 ; i < 10 ; i ++)
            arr.addLast(i);
        System.out.println(arr);

        arr.add(1, 100);	//在索引是 1 的位置插入 100
        System.out.println(arr);

        arr.addFirst(-1);		//在數組首位添加 -1
        System.out.println(arr);	
    }
}

輸出:

8.數組中包含,搜索和刪除元素

刪除元素:插入元素的反過程,索引2的值 左移到 1 的值,實際是索引2賦值給索引1,覆蓋掉原來的值,size 的值覆蓋掉 size-1的值。size的值 -1(左移);由於要求訪問數組元素 < size,故用戶沒法訪問到 size 索引中的值(圖中的100)

刪除完成

示例代碼:Array.java

public class Array {

    private int[] data;
    private int size;

    // 構造函數,傳入數組的容量capacity構造Array
    public Array(int capacity){
        data = new int[capacity];
        size = 0;
    }

    // 無參數的構造函數,默認數組的容量capacity=10
    public Array(){
        this(10);
    }

    // 獲取數組的容量
    public int getCapacity(){
        return data.length;
    }

    // 獲取數組中的元素個數
    public int getSize(){
        return size;
    }

    // 返回數組是否爲空
    public boolean isEmpty(){
        return size == 0;
    }

    // 向全部元素後添加一個新元素
    public void addLast(int e){
        add(size, e);
    }

    // 在全部元素前添加一個新元素
    public void addFirst(int e){
        add(0, e);
    }

    // 在index索引的位置插入一個新元素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 ++;
    }

    // 獲取index索引位置的元素
    public int get(int index){
        if(index < 0 || index >= size)
            throw new IllegalArgumentException("Get failed. Index is illegal.");
        return data[index];
    }

    // 修改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;
    }

    // 查找數組中是否有元素e(新增代碼)
    public boolean contains(int e){
        for(int i = 0 ; i < size ; i ++){
            if(data[i] == e)
                return true;
        }
        return false;
    }

    // 查找數組中元素e所在的索引,若是不存在元素e,則返回-1(新增代碼)
    public 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;
    }

    // 從數組中刪除第一個元素, 返回刪除的元素(新增代碼)
    public int removeFirst(){
        return remove(0);
    }

    // 從數組中刪除最後一個元素, 返回刪除的元素(新增代碼)
    public int removeLast(){
        return remove(size - 1);
    }

    // 從數組中刪除元素e(新增代碼)
    public void removeElement(int e){
        int index = find(e);
        if(index != -1)
            remove(index);
    }

    @Override
    public String 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.java

public class Main {

    public static void main(String[] args) {

        Array 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);
        // [-1, 0, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9]

        arr.remove(2);	//刪除索引爲2的元素(新增代碼)
        System.out.println(arr);

        arr.removeElement(4);//刪除元素 4(新增代碼)
        System.out.println(arr);

        arr.removeFirst();
        System.out.println(arr);//刪除頭元素(新增代碼)
    }
}

輸出:

8.使用泛型

泛型:使數據結構能夠放置全部的「數據類型」;但只能放置類對象,不能是基本數據類型(boolean、byte、char、short、int、long、float、double),爲了解決這個問題,Java 中每一個基本數據類型都有對應的包裝類(將原本不是類對象的變成了類對象);

基本數據類型對應的包裝類[Boolean、Byte、Char、Short、Int、Long、Float、Double ]  兩者之間能夠互相轉換

示例代碼(Array.java)

public class Array<E> { 	//聲明爲E類型的泛型數組

    private E[] data;	//(修改代碼)
    private int size;

    // 構造函數,傳入數組的容量capacity構造Array
    public Array(int capacity){
        data = (E[])new Object[capacity];//(修改代碼,java 中不支持直接new出泛型數組)
		//解決方式:New Object,在 Java 中任意類都是 Object 類的子類;再通過強制類型轉換(E[])轉換成E類型)
        size = 0;
    }

    // 無參數的構造函數,默認數組的容量capacity=10
    public Array(){
        this(10);
    }

    // 獲取數組的容量
    public int getCapacity(){
        return data.length;
    }

    // 獲取數組中的元素個數
    public int getSize(){
        return size;
    }

    // 返回數組是否爲空
    public boolean isEmpty(){
        return size == 0;
    }

    // 在index索引的位置插入一個新元素e
    public 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 ++;
    }

    // 向全部元素後添加一個新元素
    public void addLast(E e){	//(修改代碼)
        add(size, e);
    }

    // 在全部元素前添加一個新元素
    public void addFirst(E e){	//(修改代碼)
        add(0, e);
    }

    // 獲取index索引位置的元素
    public E get(int index){	//(修改代碼)
        if(index < 0 || index >= size)
            throw new IllegalArgumentException("Get failed. Index is illegal.");
        return data[index];
    }

    // 修改index索引位置的元素爲e
    public void set(int index, E e){
        if(index < 0 || index >= size)
            throw new IllegalArgumentException("Set failed. Index is illegal.");
        data[index] = e;
    }

    // 查找數組中是否有元素e
    public boolean contains(E e){
        for(int i = 0 ; i < size ; i ++){
            if(data[i].equals(e))	//(修改代碼,對象之間的比較用equals,值比較)
                return true;
        }
        return false;
    }

    // 查找數組中元素e所在的索引,若是不存在元素e,則返回-1
    public int find(E e){
        for(int i = 0 ; i < size ; i ++){
            if(data[i].equals(e))	//(修改代碼,對象之間的比較用equals,值比較)
                return i;
        }
        return -1;
    }

    // 從數組中刪除index位置的元素, 返回刪除的元素
    public E remove(int index){		//(修改代碼,int改成E)
        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] = null; // loitering objects != memory leak 使數組最後引用中的值被垃圾回收
        return ret;
    }

    // 從數組中刪除第一個元素, 返回刪除的元素
    public E removeFirst(){	//(修改代碼,int改成E)
        return remove(0);
    }

    // 從數組中刪除最後一個元素, 返回刪除的元素
    public E removeLast(){	//(修改代碼,int改成E)
        return remove(size - 1);
    }

    // 從數組中刪除元素e
    public void removeElement(E e){	//(修改代碼,int改成E)
        int index = find(e);
        if(index != -1)
            remove(index);
    }

    @Override
    public String 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.java

public class Main {

    public static void main(String[] args) {

        Array<Integer> arr = new Array<>(20);	//(修改代碼,Array 後添加<Integer>,int 類型的包裝類)
        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);
        // [-1, 0, 100, 1, 2, 3, 4, 5, 6, 7, 8, 9]

        arr.remove(2);
        System.out.println(arr);

        arr.removeElement(4);
        System.out.println(arr);

        arr.removeFirst();
        System.out.println(arr);
    }
}

輸出:與以前同樣

新建 Student.java

public class Student {

    private String name;
    private int score;

    public Student(String studentName, int studentScore){
        name = studentName;
        score = studentScore;
    }

    @Override
    public 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("Alice", 100));
        arr.addLast(new Student("Bob", 66));
        arr.addLast(new Student("Charlie", 88));
        System.out.println(arr);
    }
}

輸出: