JVM記憶體結構劃分

墨澜發表於2024-07-31


"棧"(Stack)是一種遵循後進先出(Last In First Out,LIFO)原則的抽象資料型別。以下是棧的一些基本特點和操作:

特點:

  1. LIFO 原則:最後加入棧的元素將是第一個被移除的元素。
  2. 動態大小:棧的大小可以根據需要動態變化。
  3. 線性結構:元素儲存在棧中的方式是線性的,但只能從一端(棧頂)訪問。

基本操作:

  1. Push:將一個元素新增到棧頂。
  2. Pop:從棧頂移除元素,並返回被移除的元素。
  3. Peek/Top:檢視棧頂元素,但不移除它。
  4. IsEmpty:檢查棧是否為空。
  5. Size:獲取棧中元素的數量。

示例:

在許多程式語言中,可以使用陣列或連結串列來實現棧。以下是使用陣列實現棧的簡單示例:

public class Stack<T> {
    private T[] stack;
    private int top;
    private int capacity;

    public Stack(int capacity) {
        this.capacity = capacity;
        this.stack = (T[]) new Object[capacity];
        this.top = -1;
    }

    public void push(T element) {
        if (top >= capacity - 1) {
            throw new StackOverflowError("Stack is full");
        }
        stack[++top] = element;
    }

    public T pop() {
        if (isEmpty()) {
            throw new IllegalStateException("Stack is empty");
        }
        return stack[top--];
    }

    public T peek() {
        if (isEmpty()) {
            throw new IllegalStateException("Stack is empty");
        }
        return stack[top];
    }

    public boolean isEmpty() {
        return top == -1;
    }

    public int size() {
        return top + 1;
    }
}

程式碼解釋:

  • Stack 類是一個泛型類,可以儲存任意型別的元素。
  • 構造方法接受一個容量引數,初始化棧的大小。
  • push 方法將元素新增到棧頂,如果棧已滿,則丟擲異常。
  • pop 方法從棧頂移除元素並返回它,如果棧為空,則丟擲異常。
  • peek 方法返回棧頂元素但不移除它,如果棧為空,則丟擲異常。
  • isEmpty 方法檢查棧是否為空。
  • size 方法返回棧中元素的數量。

應用場景:

  • 函式呼叫:許多程式語言使用棧來跟蹤函式呼叫,儲存區域性變數和返回地址。
  • 表示式求值:用於評估和簡化算術表示式,如字尾表示式(逆波蘭表示法)。
  • 回溯演算法:如迷宮求解、八皇后問題等。
  • 撤銷操作:在編輯器中實現撤銷(Undo)功能。
  • 深度優先搜尋(DFS):在圖和樹的遍歷中使用。


“堆”(Heap)有兩個不同的概念,一個是指資料結構,另一個是指記憶體管理中的堆。下面分別解釋這兩個概念:

1. 堆(資料結構)

堆是一種特殊的樹狀資料結構,通常用於實現優先佇列。它滿足以下特性:

  • 結構特性:堆通常是一棵完全二叉樹,這意味著除了最後一層外,其他每層都被完全填滿,並且最後一層的節點儘可能地集中在左側。
  • 堆序:堆中的每一個節點都必須滿足特定的順序要求。在最小堆中,父節點的值總是小於或等於其子節點的值;在最大堆中,父節點的值總是大於或等於其子節點的值。

基本操作:

  • Insert(新增):將新元素新增到堆中,並維持堆的性質。
  • Extract(提取):移除並返回堆中的根節點(最小堆中是最小元素,最大堆中是最大元素),然後重新調整堆以維持其性質。
  • Peek/Top:返回堆頂元素,但不移除它,對於最小堆是最小元素,對於最大堆是最大元素。
  • Decrease Key(降低關鍵字):將堆中某個元素的值降低,並重新調整堆以維持堆的性質。
  • Increase Key(提高關鍵字):將堆中某個元素的值提高,如果違反了堆的性質,則需要進行調整。

應用場景:

  • 優先佇列:堆是實現優先佇列的理想資料結構,允許快速訪問最高或最低優先順序的元素。
  • 排序演算法:堆排序演算法使用堆資料結構對陣列進行排序。

2. 堆(記憶體管理)

在計算機記憶體管理中,堆是用於動態記憶體分配的記憶體區域。以下是它的一些關鍵特點:

  • 動態分配:堆用於分配在執行時才知道大小的記憶體塊。
  • 碎片化:由於不同大小的記憶體塊被分配和釋放,堆記憶體可能會變得碎片化。
  • 垃圾回收:在有垃圾回收機制的語言(如Java、C#)中,堆記憶體由垃圾收集器定期清理,回收不再使用的物件所佔用的記憶體。
  • 效能開銷:分配和釋放堆記憶體通常比棧記憶體慢,因為可能涉及記憶體管理的額外開銷,如垃圾回收。

應用場景:

  • 動態記憶體分配:在程式執行期間,為物件分配記憶體。
  • 垃圾回收:自動管理記憶體的生命週期,防止記憶體洩漏。

示例程式碼(堆資料結構):

import java.util.PriorityQueue;

public class HeapExample {
    public static void main(String[] args) {
        // 建立一個最小堆的優先佇列
        PriorityQueue<Integer> minHeap = new PriorityQueue<>();
        
        // 新增元素到堆中
        minHeap.add(20);
        minHeap.add(10);
        minHeap.add(15);

        // 提取堆頂元素
        while (!minHeap.isEmpty()) {
            System.out.println(minHeap.poll()); // 將按最小堆的順序輸出元素
        }
    }
}

PriorityQueue 被用來建立一個最小堆,元素按照升序被新增和提取。這個特性使得 PriorityQueue 成為實現堆排序和優先佇列的理想選擇。

相關文章