这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战
本系列文章为个人学习总结,如果有发现错误或存在疑问之处,欢迎留言指点!
本文是重学数据结构系列的第四篇,系列文章如下:
1.算法时间复杂度和空间复杂度
2.重学数据结构--链表
3.重学数据结构--队列
4.重学数据结构--栈
5.重学数据结构--树
1.介绍
- 栈,英文名
stack,它是一种先入后出的有序列表。 - 栈是是一种插入和删除只能在线性表听一端执行的特殊线性表。允许插入和删除的一端,为变化的一端,称为
栈顶(Top),另一端为固定的一端,称为栈底(Bottom)。 - 最先放入栈中的元素在栈底,最后放入的元素在栈顶,而删除元素刚好相反,最后放入的元素最先删除,最先放入的元素最后删除。
下面分别为入栈和出栈示意图:
2.栈的快速入门
由于栈是一种有序列表,所以我们可以用数组或者链表来模拟栈,这里我们用数组模拟栈的相关操作。
数组模拟栈
思路
- 定义数组用于存储数据
- 定义一个top来表示栈顶,初始化为-1(表示栈内没有任何数据)
- 入栈操作,当有数据加入到栈时,
top++;stack[top] = data; - 出栈操作,
int value = stack[top];top--;return value;
具体实现
/**
* 数组模拟栈
*/
class ArrayStack{
private Integer maxSize;
private Integer stack[];
private Integer top = -1;
public ArrayStack(Integer maxSize) {
this.maxSize = maxSize;
stack = new Integer[maxSize];
}
//栈满(
public boolean isFull(){
return top == maxSize-1;
}
//栈空
public boolean isEmpty(){
return top == -1;
}
// 入栈
public void push(Integer data){
//判断栈是否满
if(!isFull()){
top++;
stack[top] = data;
}
}
// 出栈
public Integer pop(){
//判断栈是否为空
if(isEmpty()){
throw new RuntimeException("栈空,没有数据可出栈");
}
int value = stack[top--];
return value;
}
// 遍历栈
public void list(){
//判断栈是否为空
if(isEmpty()){
System.out.println("栈空,没有数据~~~~");
return;
}
for (int i = top; i >-1 ; i--) {
System.out.printf("stack[%d]=%d\n",i,stack[i]);
}
}
}
测试:
public static void main(String[] args) {
ArrayStack stack = new ArrayStack(5);
stack.push(2);
stack.push(3);
stack.push(4);
stack.push(6);
stack.push(7);
stack.list();
System.out.println();
System.out.println("出栈的数据为:"+stack.pop());
System.out.println();
stack.list();
}
}
3.Java中的队列
Java中的队列Queue顶级接口,源码如下:
public interface Queue<E> extends Collection<E> {
/**
* 添加一个元素到队列,如果队列容量满了,抛出异常IllegalStateException
* Inserts the specified element into this queue if it is possible to do so
* immediately without violating capacity restrictions, returning
* {@code true} upon success and throwing an {@code IllegalStateException}
* if no space is currently available.
*
* @param e the element to add
* @return {@code true} (as specified by {@link Collection#add})
* @throws IllegalStateException if the element cannot be added at this
* time due to capacity restrictions
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this queue
* @throws NullPointerException if the specified element is null and
* this queue does not permit null elements
* @throws IllegalArgumentException if some property of this element
* prevents it from being added to this queue
*/
boolean add(E e);
/**
* 添加一个元素到队列,添加成功返回true,失败返回false
* Inserts the specified element into this queue if it is possible to do
* so immediately without violating capacity restrictions.
* When using a capacity-restricted queue, this method is generally
* preferable to {@link #add}, which can fail to insert an element only
* by throwing an exception.
*
* @param e the element to add
* @return {@code true} if the element was added to this queue, else
* {@code false}
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this queue
* @throws NullPointerException if the specified element is null and
* this queue does not permit null elements
* @throws IllegalArgumentException if some property of this element
* prevents it from being added to this queue
*/
boolean offer(E e);
/**
* 移除并返回队列头元素,如果队列为空抛出异常
* Retrieves and removes the head of this queue. This method differs
* from {@link #poll poll} only in that it throws an exception if this
* queue is empty.
*
* @return the head of this queue
* @throws NoSuchElementException if this queue is empty
*/
E remove();
/**
* 移除并返回队列头元素,如果队列为空返回null
* Retrieves and removes the head of this queue,
* or returns {@code null} if this queue is empty.
*
* @return the head of this queue, or {@code null} if this queue is empty
*/
E poll();
/**
* 返回队列头部元素,如果队列为空抛出异常
* Retrieves, but does not remove, the head of this queue. This method
* differs from {@link #peek peek} only in that it throws an exception
* if this queue is empty.
*
* @return the head of this queue
* @throws NoSuchElementException if this queue is empty
*/
E element();
/** 返回列头元素,如果队列为空返回null
* Retrieves, but does not remove, the head of this queue,
* or returns {@code null} if this queue is empty.
*
* @return the head of this queue, or {@code null} if this queue is empty
*/
E peek();
}
下层实现树如下图
使用举例:
Queue<Integer> queue = new LinkedList<>();
// 入队
queue.add(1); // 队列容量满了,抛出异常
queue.offer(2); // 队列容量满了返回false
queue.add(3);
System.out.println(queue.peek()); // 出队不删除头部元素,队列空抛异常
System.out.println(queue.element()); //出队不删除头部元素,队列空返回null
System.out.println(queue.remove()); // 出队并删除头部元素,队列空抛异常
System.out.println(queue.poll()); // 出队并删除头部元素,队列空返回null
System.out.println(queue.poll());
4.Java中的栈
Java中没有对应的栈接口,但是有Stack类,它是基于Vector实现的。Java中使用栈更推荐使用Deque的实现类来完成栈的相关操作,因为Vector的相关方法都是加锁实现的,效率相对低。Deque中相关栈源码如下:
public interface Deque<E> extends Queue<E> {
/**
* 入栈
* Pushes an element onto the stack represented by this deque (in other
* words, at the head of this deque) if it is possible to do so
* immediately without violating capacity restrictions, throwing an
* {@code IllegalStateException} if no space is currently available.
*
* <p>This method is equivalent to {@link #addFirst}.
*
* @param e the element to push
* @throws IllegalStateException if the element cannot be added at this
* time due to capacity restrictions
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this deque
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
* @throws IllegalArgumentException if some property of the specified
* element prevents it from being added to this deque
*/
void push(E e);
/**
* 出栈
* Pops an element from the stack represented by this deque. In other
* words, removes and returns the first element of this deque.
*
* <p>This method is equivalent to {@link #removeFirst()}.
*
* @return the element at the front of this deque (which is the top
* of the stack represented by this deque)
* @throws NoSuchElementException if this deque is empty
*/
E pop();
}
Deque继承了Queue类,其下层实现树如下图:
使用举例如下:
public static void main(String[] args) {
Deque<Integer> stack = new LinkedList<>();
// 入栈
for (int i = 0; i < 10; i++) {
stack.push(i);
}
// 出栈
while (!stack.isEmpty()){
System.out.println(stack.pop());
}
}