數據結構與算法 —— Java 實現(線性表)

一、Java 數組的回顧學習

在學 java 基礎的時候,我們會經常用到數組來存儲相同類型的數據,下面我們就來簡單回顧一下 Java 數組的簡單使用,實在忘記怎麼使用 java 數組的同學可以查看這篇文章 Java 數組的使用

import java.util.Arrays;
public class TestArray {
    public static void main(String[] args) {
    
        // 創建一個數組
        int[] arr = new int[5];
        
        // 獲取數組長度
        int len = arr.length;
		
		// 循環給數組賦值
        for (int i=0;i<len;i++) {
            arr[i] = i*i;
        }

        // 遍歷數組
        for (int i=0; i<len; i++)
            System.out.println(arr[i]);
		
		// 顯示數組中的所有元素
		System.out.println(Arrays.toString(arr));
    }
}

以上便是系統給我們提供的 數組 api ,基於此我們可以我們就可以完成很多常規操作。但是內置的數組有時候也會帶來極大的侷限性?

  1. 數組是定長的,我們需要動態的修改數據要怎麼解決呢?
  2. 比如往數組添加一個元素?可以使用 List ArrayList 等等現成的數據結構
  3. 刪除一個元素又要如何來做呢?
  4. 修改元素很簡單,直接替換對應的下標的值即可
  5. 在任意位置插入一個元素該怎麼處理呢?

但是如果能夠出現一個變長數組的話,這些問題就可以很輕鬆的解決了。

二、使用 OOP 編寫變長數組

注意:如果要實現傳入任意數據類型的話,我們就可以把 int 數組 改爲 object即可

2.0 準備

定義一個 MyArray 的 Java 類,然後添加一個私有的數組屬性,並使用 無參的構造方法把數組初始化爲長度爲0的一個數組

/**
 * 封裝數組
 * */
public class MyArray {
    private int[] elements;// 存儲數據的數組,如果存儲其他類型,聲明爲 Object

    public MyArray() {
        elements=new int[0];
    }

}

2.1 實現 add 動態添加一個元素

我們使用定長數組的時候,要實現往數組中添加一個元素,這時候我們想到的一個方式就是創建一個新的數組來實現擴容,順着這個思路就這往下想,是不是輕鬆很多了呢?
在這裏插入圖片描述
思路有了,我們就用代碼實現

// 我們要實現新增一個元素,所以需要傳一個要新增元素的參數
public void add(int element) {
	// 創建一個比元素組容量多一個元素的數組空間
	int[] newArr = new int[elements.length+1];
	// 使用循環給新數組賦值
	for(int i=0;i<elements.length;i++) {
		newArr[i] = elements[i];
	}
	// 賦值完畢之後,把新增的元素放在數組的最後一個位置, 這裏填寫 elements.length 大家可以仔細思考以下 下標和 長度的位置關係
	newArr[elements.length] = element;
	// 把數組更新即可
	elements = newArr;
}

2.2 實現 delete 刪除任意一個位置的元素

刪除一個元素,分爲兩種情況:

  • 一種是刪除末尾元素
  • 一種是刪除中間的元素

刪除末尾的元素比較容易,直接把數組的長度減一,然後把剩下的元素重新賦值給一個新的元素就 OK 了

刪除中間的元素,要考慮一個元素,就是是否越界的情況要考慮在內,如果沒有越界,就把刪除的元素的前面的元素重新賦值,刪除的元素的後面的元素也直接賦值的新數組當中就可以了

在這裏插入圖片描述

    // 刪除數組中的元素
    public void delete(int index) {
        // 判斷下標是否越界
        if (index<0 || index>elements.length-1) {
            throw new RuntimeException("下標越界");
        }

        int newArr[] = new int[elements.length-1];
        // 複製原有數據到新數組
        for (int i=0; i<newArr.length; i++) {
            if (i<index) {
                newArr[i] = elements[i];
            } else {
                // 想要刪除之後的元素
                newArr[i] = elements[i+1];
            }
        }
        // 新數組替換就數組
        elements = newArr;
    }

2.3 實現 size 方法獲取當前數組的長度

直接返回當前數組的長度即可

public int size() {
        return elements.length;
}

2.4 實現 get 獲取指定下標的元素

用戶傳入一個下標值,然後判斷傳入的值是否合理,不合理則返回異常。反之就正常返回數據

    public int get(int index) {
        if (index<0 || index >elements.length)
            throw new RuntimeException("下標越界");
        return elements[index];
    }

2.5 實現 insert 在任意位置插入一個元素

和刪除元素是一樣的道理,只不過是在任意位置增加一個元素

    // 插入元素到一個指定位置
    public void insert(int index, int element) {
        // 創建一個新數組
        int[] newArr = new int[elements.length + 1];

        for (int i=0;i<newArr.length;i++) {
            // 前面的數據保持一致
            if (i<index) {
                newArr[i] = elements[i];
            } else {
             // 後面的數據在插入的位置留出來
                newArr[i+1] = elements[i];
            }
        }
        // 實現插入操作
        newArr[index] = element;
        // 數組替換
        elements = newArr;
    }

2.6 實現 set 替換任意一個元素

替換隻需要用戶傳入下標值,以及要替換的元素即可

    // 替換指定位置的元素
    public void set(int index, int element) {
        elements[index] = element;
    }

三、棧的實現 (Stack)

3.1 棧的基本特點

棧是一個 單進單出的數據結構,棧只能在一端進,一端出。下面畫一個圖給大家加深一下印象

  1. 棧具有棧底 以及 棧頂兩部分
  2. 每次入棧出棧 都是從棧頂進入和出去的
  3. 第一個入棧的元素會直接壓入棧底,然後慢慢的往棧頂堆,直到棧被裝滿
  4. 棧是具有 先進後出, 後進顯出的特點
    在這裏插入圖片描述

3.2 棧的實現之準備工作

我是使用動態數組完成棧的操作的,當然一個棧的空間應該一開始就指定好的。

/**
 * 實現棧,使用數組存儲數據
 * 每次往棧頂添加元素
 * */
public class MyStack {
    int[] elements;
	
	// 棧的初始化
    public MyStack() {
        elements = new int[0];
    }
}

3.3 棧的實現之入棧 (push)

    // 入棧 push, 把數據放進棧的最後
    public void push(int element) {
        int newArr[] = new int[elements.length+1];

        for (int i=0;i<elements.length-1;i++) {
            newArr[i] = elements[i];
        }
        //
        newArr[elements.length] = element;
        // 更新數組
        elements = newArr;
    }

3.4 棧的實現之出棧(pop)

    // 出棧 pop, 取棧頂元素
    public int pop() {
        if (elements.length == 0) {
            throw new RuntimeException("tack is empty!");
        }

        // 去最後一個元素
        int element = elements[elements.length-1];
        // 創建一個新數組
        int newArr[] = new int[elements.length-1];
        for (int i=0;i<elements.length-1;i++) {
            newArr[i] = elements[i];
        }
        elements = newArr;
        // 返回棧頂元素
        return element;
    }

3.5 棧的實現之查看棧頂元素(peek)

    //查看棧頂元素
    public int peek() {
        if (elements.length == 0) {
            throw new RuntimeException("stack is empty!");
        }
        return elements[elements.length-1];
    }

3.6 棧的實現之判斷棧爲空(isEmpty)

    // 判斷棧是否爲空
    public boolean isEmpty() {
        return elements.length == 0;
    }

四、隊列的實現 (Queue)

4.1 隊列的基本特點

  1. 隊列有兩端,一段是隊首,另一端就是隊尾
  2. 隊列進入元素一般是從隊首進入
  3. 隊列出元素一般是從隊尾出
  4. 隊列的特點,先進先出,後進後出
    在這裏插入圖片描述

4.2 隊列之入隊(add)

第一次用 PPT 動畫做
在這裏插入圖片描述
在這裏插入圖片描述

    // 入隊
    public void add(int element) {
        int newArr[] = new int[elements.length + 1];
        // 數組拷貝
        for (int i=0;i<elements.length;i++) {
            newArr[i] = elements[i];
        }
        newArr[elements.length] = element;
        this.elements = newArr;
    }

4.3 隊列之出隊 (pull)

在這裏插入圖片描述

    // 出隊
    public int pull() {
        int element = elements[0]; // 取出第一個數
        int newArr[] = new int[elements.length-1];
        // 這裏使用新數組的長度來拷貝
        for (int i=0;i<newArr.length;i++) {
            newArr[i] = elements[i+1];
        }
        this.elements = newArr;
        return element;
    }

4.4 隊列之判斷隊列是否爲空(isEmpty)

    // 判斷隊列是否爲空
    public boolean isEmpty() {
        return this.elements.length == 0;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章