数据结构===栈

栈的定义

栈是一种先进后出的数据结构。它的操作受限。

栈,是一种先进后出,或者后进先出的数据结构。跟数组和链表相比,有一定的限制性。毕竟,它也有自己的适用场景,比如:函数调用,表达式求值等等。栈有2个操作,入栈,出栈。时间复杂度都是O(1)。

实现一个栈

实现一个栈:怎么实现呢,有2种方式,用数组实现或者用链表实现。用数组实现的叫做顺序栈,用链表实现的叫做链式栈。

用数组实现栈

先用数组实现,不考虑扩容的情况,代码如下:

class Stack:
    def __init__(self):
        self.stack = []

    # 入栈操作
    def push(self, item):
        self.stack.append(item)

    # 出栈操作
    def pop(self):
        if not self.is_empty():
            return self.stack.pop()
        else:
            return None

    # 查看栈顶元素
    def peek(self):
        if not self.is_empty():
            return self.stack[-1]
        else:
            return None

    # 判断栈是否为空
    def is_empty(self):
        return len(self.stack) == 0

    # 获取栈的大小
    def size(self):
        return len(self.stack)

这是python的实现方式。可以再看下java的实现方式,如下图:

public class Stack {
    private int[] elements;
    private int top;
    private int capacity;

    // 初始化栈,设置初始容量
    public Stack(int capacity) {
        this.capacity = capacity;
        elements = new int[capacity];
        top = -1; // 初始时栈顶为-1,表示栈为空
    }

    // 入栈操作
    public void push(int item) {
        if (!isFull()) {
            top++;
            elements[top] = item;
        } else {
            System.out.println("栈已满,无法添加元素");
        }
    }

    // 出栈操作
    public int pop() {
        if (!isEmpty()) {
            return elements[top--];
        } else {
            System.out.println("栈为空,无法删除元素");
            return -1; // 或者可以抛出一个异常
        }
    }

    // 查看栈顶元素
    public int peek() {
        if (!isEmpty()) {
            return elements[top];
        } else {
            System.out.println("栈为空,没有元素可查看");
            return -1; // 或者可以抛出一个异常
        }
    }

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

    // 检查栈是否已满
    private boolean isFull() {
        return top == capacity - 1;
    }

    // 获取栈的大小
    public int size() {
        return top + 1;
    }

    // 展示栈的内容(可选)
    public void displayStack() {
        if (isEmpty()) {
            System.out.println("栈为空");
        } else {
            for (int i = top; i >= 0; i--) {
                System.out.print(elements[i] + " ");
            }
            System.out.println();
        }
    }

    // 主函数,用于测试栈的实现
    public static void main(String[] args) {
        Stack stack = new Stack(5); // 创建一个容量为5的栈

        stack.push(1);
        stack.push(2);
        stack.push(3);

        stack.displayStack(); // 显示栈的内容

        System.out.println("栈顶元素: " + stack.peek());

        stack.pop();
        stack.pop();

        stack.displayStack(); // 再次显示栈的内容

        System.out.println("栈的大小: " + stack.size());
        System.out.println("栈是否为空: " + stack.isEmpty());
    }
}

用链表实现栈

用数组实现完了,再用链表实现,如下图:

class Node:
    def __init__(self, data=None):
        self.data = data
        self.next = None

class Stack:
    def __init__(self):
        self.top = None

    # 入栈操作
    def push(self, data):
        if self.top is None:
            self.top = Node(data)
        else:
            new_node = Node(data)
            new_node.next = self.top
            self.top = new_node

    # 出栈操作
    def pop(self):
        if self.top is None:
            return None
        else:
            popped = self.top.data
            self.top = self.top.next
            return popped

    # 查看栈顶元素
    def peek(self):
        return self.top.data if self.top else None

    # 判断栈是否为空
    def is_empty(self):
        return self.top is None

# 测试代码
s = Stack()
s.push(1)
s.push(2)
s.push(3)
print(s.pop())  # 输出:3
print(s.peek())  # 输出:2
print(s.is_empty())  # 输出:False

java的实现方式,如下图:

public class Node<T> {
    private T data;
    private Node<T> next;

    public Node(T data) {
        this.data = data;
        this.next = null;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public Node<T> getNext() {
        return next;
    }

    public void setNext(Node<T> next) {
        this.next = next;
    }
}

public class LinkedListStack<T> {
    private Node<T> top;

    public LinkedListStack() {
        this.top = null;
    }

    // 入栈操作
    public void push(T data) {
        Node<T> newNode = new Node<>(data);
        newNode.setNext(top);
        top = newNode;
    }

    // 出栈操作
    public T pop() {
        if (isEmpty()) {
            throw new IllegalStateException("Stack is empty");
        }
        T data = top.getData();
        top = top.getNext();
        return data;
    }

    // 查看栈顶元素
    public T peek() {
        if (isEmpty()) {
            throw new IllegalStateException("Stack is empty");
        }
        return top.getData();
    }

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

    // 获取栈的大小
    public int size() {
        int size = 0;
        Node<T> current = top;
        while (current != null) {
            size++;
            current = current.getNext();
        }
        return size;
    }

    // 测试代码
    public static void main(String[] args) {
        LinkedListStack<Integer> stack = new LinkedListStack<>();
        stack.push(200);
        stack.push(300);
        stack.push(600);
        System.out.println(stack.pop());  
        System.out.println(stack.peek());  
        System.out.println(stack.isEmpty()); 
        System.out.println(stack.size());  
    }
}

好了,实现方式就是这样的。再来看看动态扩容的栈是怎么实现的。

支持动态扩容的栈

这个跟普通的栈有一个不同的地方,在入栈的时候栈满了会进行扩容,然后复制之前的数据,再进行入栈操作。用java实现,如下图:

public class DynamicArrayStack<T> {
    private static final int DEFAULT_CAPACITY = 10;
    private static final int RESIZE_FACTOR = 2;
    private Object[] elements;
    private int top;

    public DynamicArrayStack() {
        elements = new Object[DEFAULT_CAPACITY];
        top = -1;
    }

    // 入栈操作
    public void push(T item) {
        ensureCapacity();
        elements[++top] = item;
    }

    // 出栈操作
    public T pop() {
        if (isEmpty()) {
            throw new EmptyStackException();
        }
        return (T) elements[top--];
    }

    // 查看栈顶元素
    public T peek() {
        if (isEmpty()) {
            throw new EmptyStackException();
        }
        return (T) elements[top];
    }

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

    // 获取栈的大小
    public int size() {
        return top + 1;
    }

    // 确保数组有足够的容量
    private void ensureCapacity() {
        if (top == elements.length - 1) {
            resize();
        }
    }

    // 调整数组大小
    private void resize() {
        int newSize = elements.length * RESIZE_FACTOR;
        elements = Arrays.copyOf(elements, newSize);
    }

    // 测试代码
    public static void main(String[] args) {
        DynamicArrayStack<Integer> stack = new DynamicArrayStack<>();

        stack.push(1);
        stack.push(2);
        stack.push(3);

        System.out.println(stack.pop());  // 输出:3
        System.out.println(stack.peek());  // 输出:2
        System.out.println(stack.size());  // 输出:2
        System.out.println(stack.isEmpty());  // 输出:false
    }
}

栈的应用

栈应用非常多,比如,在浏览器里有个向前,向后的箭头,就可以用2个栈来存储;函数的调用,也是可以用栈的。例子就不多举了。

小结

这篇文章讲述了栈的数据结构。

主要是讲解了栈的数据结构,以及实现,目的是了解底层的数据结构及应用,还有动态扩容的栈,栈的时间复杂度,空间复杂度都是O(1)。基本上就这么多。至于实现,用什么语言不重要,原理懂了,写一个,应该都不是什么难事。

  • 14
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值