
栈是限定仅在表尾进行插入和删除操作的线性表,一种**先进后出**的数据结构。
栈顶: 允许插入和删除的一端。
栈底:不允许插入和删除的一端。
压栈:栈的插入操作。
出栈:栈的删除操作。
栈的底层可以是顺序表,可以是链表实现。
栈的顺序实现就是使用顺序表为底层实现。
实现的接口(成员方法)如下:
顺序表可以多实现一个判满接口。
public class MyStack { //默认构造方法 public MyStack() {} //入栈 public void push(int val) {} //判满 public boolean isFull() { } //出栈 public int pop() {} //获取栈顶元素 但是不删除 public int peek() { } //获取栈元素个数 public int size(){} //判空 public boolean isEmpty() { } } 我们使用一个数组,和一个int类型usedSize来表示栈中元素个数。
public int[] elem; public int usedSize; 在构造方法中我们将数组申请10个int空间。
public MyStack() { this.elem = new int[10]; } 注意事项:
public void push(int val) { if (isFull()) { this.elem = Arrays.copyOf(elem, 2 * elem.length); } elem[usedSize++] = val; } 直接判断usedSize是否等于数组长度。
public boolean isFull() { return usedSize == elem.length; } 直接返回usedSize即可。
public int size(){ return usedSize; } 注意事项:
public int pop() throws IndexIllegalException{ try { if (isEmpty()) { throw new IndexIllegalException("栈为空"); } }catch (IndexIllegalException e){ e.printStackTrace(); } return elem[--usedSize]; } 注意事项:
public int peek() throws IndexIllegalException{ try { if (isEmpty()) { throw new IndexIllegalException("栈为空"); } }catch (IndexIllegalException e){ e.printStackTrace(); } return elem[usedSize - 1]; } 直接返回usedSize等不等于0。
public boolean isEmpty() { return usedSize == 0; } 在实现栈前我们先思考使用什么样的链表来实现?
由于栈的特性是先入后出,如果使用单链表我们出栈时要拿到最后一个节点前一个节点,使复杂度为O(N),所以我们使用双向链表。
实现的接口如下:
public class MyStack { //入栈 public void push(int val) {} //出栈 public int pop() {} //获取栈顶元素 但是不删除 public int peek() { } //判空 public boolean isEmpty() { } //获取栈元素个数 public int size(){} } 跟双向链表的内部类实现差不多。
static class ListNode{ public int val; public ListNode prev; public ListNode next; public ListNode(int val) { this.val = val; } } public ListNode head; public ListNode last; 实现思路:
public void push(int val){ ListNode cur = new ListNode(val); if(isEmpty()){ head = last = cur; return; } last.next = cur; cur.prev = last; last = cur; } 实现思路:
public int pop() throws NullPointerException{ try{ if(isEmpty()){ throw new NullPointerException; } }catch(NullPointerException e){ e.printStackTrace(); } ListNode cur = last; last = last.prev; last.next = null; return cur.val; } 直接返回头是否为空就行。
public boolean isEmpty(){ return head == null; } 实现思路:
public int peek(){ try{ if(isEmpty()){ throw new NullPointerException; } }catch(NullPointerException e){ e.printStackTrace(); } return last.val; } 直接循环遍历即可。
public int size(){ ListNode cur = head; int size = 0; while(cur != null){ cur = cur.next; size++; } return size; } 
接口说明:
提供的常用方法如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FhLLHxMB-1720973208640)(https://i-blog.csdnimg.cn/direct/f414e542bd80432095def0a48671fd3f.png)]
有效的括号
逆波兰表达式求值
栈的压入 弹出序列
最小栈