博客主页: 【小扳_-CSDN博客】
❤感谢大家点赞收藏⭐评论✍
文章目录
1.0 栈的说明
2.0 用链表来实现栈
2.1 实现栈 - 入栈方法(push)
2.2 实现栈 - 出栈(pop)
2.3 实现栈 - 查看栈顶元素(peek)
2.4 实现栈 - 判断是否为空栈(isEmpty)
2.5 实现栈 - 判断是否为满栈(isFull)
2.6 实现栈 - 重写迭代器
2.7 用链表实现栈的完整代码
3.0 用数组来实现栈
3.1 实现栈 - 入栈(push)
3.2 实现栈 - 出栈(pop)
3.3 实现栈 - 查找栈顶元素(peek)
3.4 实现栈 - 判断是否为空栈(isEmpty)
3.5 实现栈 - 判断是否为满栈(isFull)
3.6 实现栈 - 重写迭代器
3.7 用数组实现栈的完整代码
栈是一种数据结构,它具有后进先出(LIFO)的特性,即最后入栈的元素最先出栈。栈通常可以通过数组或链表来实现。栈有两个基本操作:入栈(push)和出栈(pop)。入栈操作将元素放入栈顶,出栈操作将栈顶元素移除并返回。栈还有一个辅助操作叫做查看栈顶元素(peek),用于查看栈顶的元素但不移除它。
首先,需要准备实现带哨兵的单链表,用来存放数据。把链表的头部称为栈顶,链表的尾部称为栈底,对于栈来说,只对栈顶操作,对栈底不会有任何的操作。所以该链表中需要的成员变量有 sentry 哨兵节点、 size 记录节点的数量、capacity 栈的容量。为了更好的实现相关的API,所以另外定义了一个接口。
代码如下:
public class LinkedListStack
implements StackInterface { static class Node { public E value; Node next; public Node() { } public Node(E value, Node next) { this.value = value; this.next = next; } } private int size; private final int capacity; private final Node sentry; public LinkedListStack(int capacity) { this.capacity = capacity; this.sentry = new Node<>(null,null); } }
用链表实现栈中,入栈就相当于在链表中进行头插节点,需要注意的是,在进行入栈的时候需要先判断是否栈满了,若栈满了,返回 false;反则,返回 true 。
代码如下:
public boolean push(E value) { if (isFull()) { System.out.println("栈容量满了!!!"); return false; } sentry.next = new Node<>(value,sentry.next); size++; return true; }
sentry.next 所指向的就是头节点,现在头节点要换成新入栈的节点,则就是 sentry.next 指向该节点,而新入栈的节点指向原来就旧的头节点。需要注意的是,记得进行 size++ 。
用链表实现栈中,出栈相当于头删节点,不过结束的时候需要返回该节点的值,所以先找到头节点 head = sentry.next ,然后再让哨兵节点指向头节点的下一个节点,即可将该头节点从该链表中删除掉了,sentry.next = head.next 。最后返回 head.value 。
代码如下:
public E pop() { if (isEmpty()) { return null; } Node
first = sentry.next; sentry.next = first.next; size--; return first.value; } 在进行出栈操作时,需要先判断该链表是否为空,若是空链表,则返回 null ;若不是空链表,则返回该删除节点的值。还需要注意的是,每一次删除后,都需要进行 size-- 操作。
用链表实现栈中,查看栈顶元素相当与查找头节点,即 head = sentry.next,因此直接返回该头节点的值即可 head.value 。
@Override public E peek() { if (isEmpty()) { return null; } Node
first = sentry.next; return first.value; } 在查看栈顶元素时,也要先判断该栈是否为空栈。若为空栈,直接返回 null 。
当且仅当 size == 0 时,则为空栈。还有一种判断的方式,就是当 sentry.next 时,也为空栈。
代码如下:
public boolean isEmpty() { return size == 0; //return sentry.next == null; }
用链表实现栈时,当 size == capacity 时,则为满栈。
代码如下:
public boolean isFull() { return size == capacity; }
先实现该接口 Iterable
代码如下:
public Iterator
iterator() { return new Iterator () { Node p = sentry.next; @Override public boolean hasNext() { return p != null; } @Override public E next() { E key = p.value; p = p.next; return key; } }; }
相关的接口:
public interface StackInterface
{ /** * 先栈顶压入元素 * value - 代压入值 * 压入成功返回true,否则返回false */ boolean push(E value); /** * 从栈顶弹出元素 * 栈非空返回栈顶元素,栈为空返回 null */ E pop(); /** 返回栈顶元素,不弹出 栈非空返回栈顶元素,栈为空返回 null */ E peek(); /** * 判断栈是否为空 * 空返回true,否则返回false */ boolean isEmpty(); /** * 判断栈是否满 * 满返回true,否则返回false */ boolean isFull(); } 用链表实现栈的代码:
import java.util.Iterator; public class LinkedListStack
implements StackInterface ,Iterable { static class Node { public E value; Node next; public Node() { } public Node(E value, Node next) { this.value = value; this.next = next; } } private int size; private final int capacity; private final Node sentry; public LinkedListStack(int capacity) { this.capacity = capacity; this.sentry = new Node<>(null,null); } @Override public boolean push(E value) { if (isFull()) { System.out.println("栈容量满了!!!"); return false; } sentry.next = new Node<>(value,sentry.next); size++; return true; } @Override public E pop() { if (isEmpty()) { return null; } Node first = sentry.next; sentry.next = first.next; size--; return first.value; } @Override public E peek() { if (isEmpty()) { return null; } Node first = sentry.next; return first.value; } @Override public boolean isEmpty() { return size == 0; //return sentry.next == null; } @Override public boolean isFull() { return size == capacity; } @Override public Iterator iterator() { return new Iterator () { Node p = sentry.next; @Override public boolean hasNext() { return p != null; } @Override public E next() { E key = p.value; p = p.next; return key; } }; } }
该类中的成员变量有 Object[] array 的数组,来存放数据;还有 int top ,用来记录数据的个数,当 top - 1 索引对应该位置,称为栈顶;0 索引对应的位置,称为栈底。这样的设置,提高了对栈顶操作的效率。
代码如下:
public class ArrayStack
{ private int top; private Object[] arrayStack; public ArrayStack() { } public ArrayStack(int capacity) { arrayStack = new Object[capacity]; } } 利用该类的构造方法,可以自定义初始化数组的容量。
用数组实现栈,相当与在数组 top 位置中存放数据,即 arrayStack[top] = value 。
代码如下:
public boolean push(E value) { if (isFull()) { return false; } arrayStack[top++] = value; return true; }
但是在入栈之前需要先判断该栈是否满了,若为满栈,则不能继续存放数据了。若存放数据之后,需要将 top++ 进行自加的操作。
用数组实现栈,出栈相当于进行尾删,不过先得记录要删除的数据,将其返回即可。
代码如下:
public E pop() { if (isEmpty()) { return null; } return (E)arrayStack[--top]; }
但是,在出栈之前需要先判断该栈是否为空栈。
用数组实现栈,查找栈顶元素相当于去查找数组 top - 1索引的值。
代码如下:
public E peek() { if (top == 0) { return null; } return (E) arrayStack[top - 1]; }
在查找栈顶元素之前,需要先判断 top 是否为 0 ,为 0 即为空,没有必要查找了。
用数组实现栈,判断是否为空栈,就是判断 top 是否等于 0 。
代码如下:
public boolean isEmpty() { return top == 0; }
用数组实现栈,判断是否为满栈,就是判断 top 是否等于该数组的长度 arrayStack.length 。
代码如下:
@Override public boolean isFull() { return arrayStack.length == top; }
先实现该接口 Iterable
代码如下:
public Iterator
iterator() { return new Iterator () { int p = top; @Override public boolean hasNext() { return p > 0; } @Override public E next() { return (E)arrayStack[--p]; } }; }
接口代码:
public interface StackInterface
{ /** * 先栈顶压入元素 * value - 代压入值 * 压入成功返回true,否则返回false */ boolean push(E value); /** * 从栈顶弹出元素 * 栈非空返回栈顶元素,栈为空返回 null */ E pop(); /** 返回栈顶元素,不弹出 栈非空返回栈顶元素,栈为空返回 null */ E peek(); /** * 判断栈是否为空 * 空返回true,否则返回false */ boolean isEmpty(); /** * 判断栈是否满 * 满返回true,否则返回false */ boolean isFull(); } 用数组实现栈的代码:
import java.util.Iterator; public class ArrayStack
implements StackInterface ,Iterable { private int top; private Object[] arrayStack; public ArrayStack() { } public ArrayStack(int capacity) { arrayStack = new Object[capacity]; } @Override public boolean push(E value) { if (isFull()) { return false; } arrayStack[top++] = value; return true; } @Override public E pop() { if (isEmpty()) { return null; } return (E)arrayStack[--top]; } @Override public E peek() { if (top == 0) { return null; } return (E) arrayStack[top - 1]; } @Override public boolean isEmpty() { return top == 0; } @Override public boolean isFull() { return arrayStack.length == top; } @Override public Iterator iterator() { return new Iterator () { int p = top; @Override public boolean hasNext() { return p > 0; } @Override public E next() { return (E)arrayStack[--p]; } }; } }