JVM内存结构划分

JVM内存结构划分

栈(Stack)是一种基本的数据结构,用于按照“后进先出”(Last In First Out,LIFO)的原则存储和访问数据。以下是栈的一些关键概念和特性:

基本操作

  • 压栈(Push):将一个元素添加到栈顶。
  • 弹栈(Pop):移除栈顶元素,并返回它。
  • 查看栈顶(Peek/Top):查看但不移除栈顶元素。

实现方式

  • 栈可以用数组或链表来实现。数组实现提供了基本的索引访问,而链表实现则允许动态大小调整。

*时间复杂度**:

  • 压栈和弹栈操作通常都是O(1)时间复杂度,即常数时间内完成。

空间复杂度

  • 栈的空间复杂度取决于其最大容量。如果栈大小固定,则空间复杂度为O(n),其中n是栈的大小;如果栈大小可变,则空间复杂度为O(1),即不考虑最坏情况下的容量。

应用场景

  • 表达式求值和运算符优先级检查。
  • 函数调用时的返回地址和局部变量存储(调用栈)。
  • 撤销操作(Undo)的实现。
  • 括号匹配检查。
  • 深度优先搜索(DFS)算法的实现。

栈的遍历

  • 通常从栈顶开始,按照压栈的逆序进行遍历。

数据结构特性

  • 栈是一种线性数据结构,但它只允许在一端(栈顶)进行操作。

栈溢出

  • 当栈空间被占满,无法再压入新元素时,称为栈溢出,可能会抛出异常(例如Java中的StackOverflowError)。
复制代码
public class StackArrayImpl {
    private int[] stack;
    private int top;
    private int capacity;

    // 构造函数,初始化栈的大小
    public StackArrayImpl(int size) {
        capacity = size;
        stack = new int[capacity];
        top = -1; // 栈为空时,栈顶索引设置为-1
    }

    // 压栈操作
    public void push(int value) {
        if (top >= capacity - 1) {
            System.out.println("Stack Overflow. Cannot push more elements.");
            return;
        }
        stack[++top] = value; // 栈顶索引递增后,将元素放入栈顶位置
    }

    // 弹栈操作
    public int pop() {
        if (top == -1) {
            System.out.println("Stack Underflow. Cannot pop from an empty stack.");
            return -1; // 栈为空时返回-1或其他错误代码
        }
        return stack[top--]; // 返回栈顶元素,并递减栈顶索引
    }

    // 查看栈顶元素
    public int peek() {
        if (top == -1) {
            System.out.println("Stack is empty. Nothing to peek.");
            return -1; // 栈为空时返回-1或其他错误代码
        }
        return stack[top]; // 返回栈顶元素但不移除
    }

    // 判断栈是否为空
    public boolean isEmpty() {
        return top == -1;
    }

    // 判断栈是否已满
    public boolean isFull() {
        return top == capacity - 1;
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        StackArrayImpl stack = new StackArrayImpl(5); // 创建一个大小为5的栈

        // 压栈操作
        stack.push(1);
        stack.push(2);
        stack.push(3);

        // 查看栈顶元素
        System.out.println("Top element is: " + stack.peek());

        // 弹栈操作
        System.out.println("Popped element is: " + stack.pop());

        // 判断栈是否为空
        System.out.println("Is the stack empty? " + stack.isEmpty());
    }
}

在这个示例中,StackArrayImpl类使用一个整型数组stack来存储栈中的元素,top变量用于追踪栈顶的位置。构造函数初始化栈的大小,push方法用于向栈中添加元素,pop方法用于移除并返回栈顶元素,peek方法用于查看栈顶元素而不移除它。isEmptyisFull方法分别用于判断栈是否为空和是否已满。

堆(Heap)是一个非常重要的内存区域,用于存储对象实例和数组

内存分配:ava堆用于动态内存分配,几乎所有的对象实例和数组都是在这里分配的。

堆配置:可以使用JVM参数(如-Xms-Xmx)来设置堆的初始大小和最大大小。

堆空间监控:可以使用JMX(Java Management Extensions)和其他监控工具来实时监控堆的使用情况。

复制代码
public class MinHeap {
    private int[] heap;
    private int size; // 当前堆中元素的数量
    private int capacity; // 堆的最大容量

    // 构造函数,初始化堆的大小
    public MinHeap(int capacity) {
        this.capacity = capacity;
        this.heap = new int[capacity];
        this.size = 0;
    }

    // 向堆中添加元素
    public void add(int value) {
        if (size >= capacity) {
            System.out.println("Heap Overflow. Cannot add more elements.");
            return;
        }
        heap[size] = value;
        swim(size); // 上浮调整
        size++;
    }

    // 访问堆顶元素
    public int peek() {
        if (size == 0) {
            System.out.println("Heap is empty.");
            return Integer.MIN_VALUE; // 或者抛出异常
        }
        return heap[0];
    }

    // 移除堆顶元素
    public int remove() {
        if (size == 0) {
            System.out.println("Heap is empty.");
            return Integer.MIN_VALUE; // 或者抛出异常
        }
        int removed = heap[0];
        heap[0] = heap[size - 1];
        size--;
        sink(0); // 下沉调整
        return removed;
    }

    // 上浮操作,保持堆的有序性
    private void swim(int index) {
        while (index > 0 && heap[parent(index)] > heap[index]) {
            swap(parent(index), index);
            index = parent(index);
        }
    }

    // 下沉操作,保持堆的有序性
    private void sink(int index) {
        while (leftChild(index) < size) {
            int j = leftChild(index);
            if (j + 1 < size && heap[j] > heap[j + 1]) {
                j++;
            }
            if (heap[index] < heap[j]) {
                swap(index, j);
                index = j;
            } else {
                break;
            }
        }
    }

    // 交换堆中的两个元素
    private void swap(int i, int j) {
        int temp = heap[i];
        heap[i] = heap[j];
        heap[j] = temp;
    }

    // 获取父节点的索引
    private int parent(int index) {
        return (index - 1) / 2;
    }

    // 获取左子节点的索引
    private int leftChild(int index) {
        return 2 * index + 1;
    }

    // 获取右子节点的索引
    private int rightChild(int index) {
        return 2 * index + 2;
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        MinHeap minHeap = new MinHeap(10); // 创建一个容量为10的最小堆

        // 向堆中添加元素
        minHeap.add(4);
        minHeap.add(1);
        minHeap.add(3);
        minHeap.add(2);

        // 访问堆顶元素
        System.out.println("Top element is: " + minHeap.peek());

        // 移除堆顶元素
        System.out.println("Removed element is: " + minHeap.remove());
    }
}

在这个示例中,MinHeap类使用一个整型数组heap来存储堆中的元素。size变量用于追踪当前堆中元素的数量,而capacity表示堆的最大容量。add方法用于向堆中添加新元素,并调用swim方法来维护堆的有序性。peek方法用于返回堆顶元素,而remove方法用于移除并返回堆顶元素,并调用sink方法来维护堆的有序性。swimsink操作确保了堆的最小堆性质。

作者:静默虚空
欢迎任何形式的转载,但请务必注明出处。
限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。

posted @   糊涂图-4060  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示