一、链式栈
-
栈是只能在某一端插入和删除的特殊线性表。它按照后进先出的原则存储数据,先进入的数据被压入栈底(push),最后的数据在栈顶(top),需要读数据的时候从栈顶开始弹出数据(top)最后一个数据被第一个读出来。
-
链式栈可以通过单链表的方式来实现,使用链式栈的优点在于它能够克服用数组实现的顺序栈的空间利用率不高的特点,但是需要为每个栈元素分配额外的指针空间来存放指针域;
-
链式栈中的元素以结点的形式存储,结点中存有此节点存于栈中的元素以及指向下个节点的指针。链式栈的数据成员只用保存指向栈顶节点的指针。
-
对于链栈而言,使用了链表来实现栈,链表中的元素存储在不连续的地址,由于是动态申请内存,所以我们可以以非常小的内存空间开始,另外当某个项不使用时也可将内存返还给系统。
类似于顺序栈的图解,方便对比理解,头结点head中并没有存放数据元素,注意这里push操作是采用头插法添加元素,top栈顶指针(实际上在下面的链式栈代码中没有设置)始终为头结点的下一个结点(栈不为空时),pop操作只需删除top结点(head.next)即可;剩下的都是单链表中很基础的方法操作,可以点击单链表常用方法、单链表相关面试真题;
二、实现一个简单的链式栈及基本操作
- 链式栈的数据结构:
class Stack {
private class Entry {
int data;
Entry next;
public Entry() {
this.next = null;
}
public Entry(int val) {
this.data = val;
this.next = null;
}
}
private Entry head;
public Stack() {
this.head = new Entry();
}
}
- 常用操作
- 入栈
//入栈
public void push(int data) { //入栈操作使用单链表的头插法
Entry entry = new Entry(data);
entry.next = this.head.next;
this.head.next = entry;
}
- 出栈
//出栈
public void pop() { //出栈操作只需删除第一个数据结点即可
if (isEmpty()) {
return;
}
Entry cur = this.head.next;
this.head.next = cur.next;
}
这里是出栈的同时拿到出栈的元素
public int getPop() {
if (isEmpty()) {
return -1;
}
Entry cur = this.head.next;
this.head.next = cur.next;
return cur.data;
}
- 得到栈顶元素
//得到栈顶元素
public int getTop() {
if (isEmpty()) {
throw new UnsupportedOperationException("栈空");
}
return this.head.next.data;
}
- 判空
//判空
public boolean isEmpty() {
return this.head.next == null;
}
- 打印
// 打印
public void show() {
Entry cur = this.head.next;
while (cur != null) {
System.out.print(cur.data + " ");
cur = cur.next;
}
System.out.println();
}
}