我是小黑,一个在互联网“苟且”的程序员。

流水不争先,贵在滔滔不绝

栈(stack)又名堆栈,是一个线性表数据结构,后进先出(FILO)是它最大的特点。

【算法系列】堆栈数据结构_java

使用数组实现堆栈结构

题目描述:

需要使用数组来实现堆栈。需要编写push和pop方法来演示Stack行为(后进先出)。

尽管在java中提供了所有抽象数据类型的实现,如堆栈、队列和链表等,但理解基本数据结构并自己实现它们能让我们有更深刻的理解。

堆栈的数组实现本质上不是动态的。你也可以通过链表实现动态行为的Stack。

思路:

在实现之前我们先看一下栈支持的基本操作:

  • push:将元素压入堆栈的顶部,堆栈大小加1;
  • pop:将栈顶元素删除并返回被删除元素,堆栈大小减1;
  • isEmpty:判断堆栈是否为空;
  • isFull:判断堆栈是否已满;
  • peek:返回栈顶元素,但是不删除它。

这些操作的时间复杂度都是O(1)。

代码实现:

package com.heiz.algorithm.stack;

/**
* @author 小黑说Java
* @ClassName StackCustom
* @Description
* @date 2021/11/21
**/
public class StackCustom {
int size;
int[] arr;
int top;

StackCustom(int size) {
this.size = size;
this.arr = new int[size];
this.top = -1;
}

public void push(int pushedElement) {
if (!isFull()) {
top++;
arr[top] = pushedElement;
System.out.println("Pushed element:" + pushedElement);
} else {
System.out.println("Stack is full !");
}
}

public int pop() {
if (!isEmpty()) {
int returnedTop = top;
top--;
System.out.println("Popped element :" + arr[returnedTop]);
return arr[returnedTop];
} else {
System.out.println("Stack is empty !");
return -1;
}
}

public int peek() {
if (!this.isEmpty())
return arr[top];
else {
System.out.println("Stack is Empty");
return -1;
}
}

public boolean isEmpty() {
return (top == -1);
}

public boolean isFull() {
return (size - 1 == top);
}

public static void main(String[] args) {
StackCustom StackCustom = new StackCustom(10);
StackCustom.pop();
System.out.println("=================");
StackCustom.push(10);
StackCustom.push(30);
StackCustom.push(50);
StackCustom.push(40);
System.out.println("=================");
StackCustom.pop();
StackCustom.pop();
StackCustom.pop();
System.out.println("=================");
}
}

运行结果:

【算法系列】堆栈数据结构_Java_02

如你所见,我们最后push的元素40,先被pop出来,符合栈后进先出(LIFO)的特点。

使用LinkedList实现堆栈结构

使用链表完成堆栈结构,我们主要完成两个重要的操作:


  • ​Push​​ : 将元素推入链表的开头,演示堆栈的推行为;
  • ​Pop​​ :我们将移除链表的第一个元素来演示Stack的Pop行为。

代码实现:

package com.heiz.algorithm.stack;

/**
* @author yuriy.lu
* @ClassName LinkedListStack
* @Description
* @date 2021/11/21
**/
public class LinkedListStack {
private Node head; // 头结点

//链表节点
private static class Node {
int value;
Node next;
}

public LinkedListStack() {
head = null;
}

public int pop() throws LinkedListEmptyException {
if (head == null) {
throw new LinkedListEmptyException();
}
int value = head.value;
head = head.next;
return value;
}

public void push(int value) {
Node oldHead = head;
head = new Node();
head.value = value;
head.next = oldHead;
}

public static void main(String[] args) {
LinkedListStack lls = new LinkedListStack();
lls.push(20);
lls.push(50);
lls.push(80);
lls.push(40);
lls.push(60);
lls.push(75);
System.out.println("Element removed from LinkedList: " + lls.pop());
System.out.println("Element removed from LinkedList: " + lls.pop());
lls.push(10);
System.out.println("Element removed from LinkedList: " + lls.pop());
printList(lls.head);
}

public static void printList(Node head) {
Node temp = head;
while (temp != null) {
System.out.format("%d ", temp.value);
temp = temp.next;
}
System.out.println();
}
}

/**
* Exception to indicate that LinkedList is empty.
*/
class LinkedListEmptyException extends RuntimeException {
private static final long serialVersionUID = 1L;

public LinkedListEmptyException() {
super();
}
public LinkedListEmptyException(String message) {
super(message);
}
}

运行结果:

【算法系列】堆栈数据结构_java_03

使用两个队列实现堆栈

使用两个队列来实现堆栈行为,编写push和pop方法来演示栈的后进先出行为(LIFO)。

思路:

栈有两个最重要的操作push和pop,假设有两个队列:queue1, queue2来实现push和pop;

push:


  • 如果queue1为空,则向queue1添加元素;
  • 如果queue1不为空,将queue1中的所有元素添加到queue2中,将当前元素添加到queue1中,并将queue2中的所有元素复制到queue1中。

pop: 简单地从queue1中删除元素。

代码实现:

package com.heiz.algorithm.stack;

import java.util.LinkedList;
import java.util.Queue;

/**
* @author 小黑说Java
* @ClassName StackUsingTwoQueues
* @Description
* @date 2021/11/21
**/
public class StackUsingTwoQueues {

Queue<Integer> queue1;
Queue<Integer> queue2;

StackUsingTwoQueues() {
queue1 = new LinkedList<>();
queue2 = new LinkedList<>();
}

public void push(int i) {
if (queue1.size() == 0)
queue1.add(i);
else {
int sizeOfQueue1 = queue1.size();
for (int j = 0; j < sizeOfQueue1; j++)
queue2.add(queue1.remove());
queue1.add(i);
for (int k = 0; k < sizeOfQueue1; k++)
queue1.add(queue2.remove());
}
}

public int pop() {
if (queue1.size() == 0)
throw new QueueEmptyException("Underflow Exception");
return queue1.remove();
}

public static void main(String[] args) {
StackUsingTwoQueues stack = new StackUsingTwoQueues();
stack.push(20);
stack.push(40);
stack.push(70);
stack.push(50);
stack.push(90);
stack.push(110);
stack.push(30);
System.out.println("Removed element : " + stack.pop());
stack.push(170);
System.out.println("Removed element : " + stack.pop());
}
}

/**
* Exception to indicate that Queue is empty.
*/

class QueueEmptyException extends RuntimeException {
private static final long serialVersionUID = 1L;

public QueueEmptyException() {
super();
}

public QueueEmptyException(String message) {
super(message);
}
}

运行结果:

【算法系列】堆栈数据结构_后端_04

使用另一个堆栈对一个堆栈进行排序

使用另一个堆栈对一个堆栈进行排序。可以使用栈的push和pop操作来实现这一点。

思路:


  • 假设有两个栈,stack和tempStack;
  • 从堆栈中取出一个currentData元素,并将其与tempStack的head进行比较;
  • 如果currentData更大,则将其推到tempStack;
  • 如果currentData小于tempStack的head,从tempStack中取出一个元素并将其推入堆栈,直到得到大于currentData的元素;
  • 最后,tempStack将被排序为堆栈。

代码实现:

package com.heiz.algorithm.stack;

/**
* @author 小黑说Java
* @ClassName StackCustom
* @Description
* @date 2021/11/21
**/
public class StackCustom {
int size;
int arr[];
int top;

StackCustom(int size) {
this.size = size;
this.arr = new int[size];
this.top = -1;
}

public void push(int pushedElement) {
if (!isFull()) {
top++;
arr[top] = pushedElement;
} else {
System.out.println("Stack is full !");
}
}

public int pop() {
if (!isEmpty()) {
int returnedTop = top;
top--;
return arr[returnedTop];

} else {
System.out.println("Stack is empty !");
return -1;
}
}

public int peek() {
return arr[top];
}

public boolean isEmpty() {
return (top == -1);
}

public boolean isFull() {
return (size - 1 == top);
}

public static void main(String[] args) {
StackCustom stackCustom = new StackCustom(10);
System.out.println("=================");
stackCustom.push(10);
stackCustom.push(30);
stackCustom.push(50);
stackCustom.push(40);
stackCustom.printStack(stackCustom);
StackCustom sortedStack = sortStack(stackCustom);
System.out.println("=================");
System.out.println("After Sorting :");
System.out.println("=================");
sortedStack.printStack(sortedStack);
}

/**
* 排序算法
*/
public static StackCustom sortStack(StackCustom stack) {
StackCustom tempStack = new StackCustom(10);
while (!stack.isEmpty()) {
int currentData = stack.pop();
while (!tempStack.isEmpty() && tempStack.peek() > currentData) {
stack.push(tempStack.pop());
}
tempStack.push(currentData);
}
return tempStack;
}

public void printStack(StackCustom stack) {
if (top >= 0) {
System.out.println("Elements of stacks are:");
for (int i = 0; i <= top; i++) {
System.out.println(arr[i]);
}
}
}
}
package com.heiz.algorithm.stack;/** * @author 小黑说Java * @ClassName StackCustom * @Description * @date 2021/11/21 **/public class StackCustom {    int size;    int arr[];    int top;    StackCustom(int size) {        this.size = size;        this.arr = new int[size];        this.top = -1;    }    public void push(int pushedElement) {        if (!isFull()) {            top++;            arr[top] = pushedElement;        } else {            System.out.println("Stack is full !");        }    }    public int pop() {        if (!isEmpty()) {            int returnedTop = top;            top--;            return arr[returnedTop];        } else {            System.out.println("Stack is empty !");            return -1;        }    }    public int peek() {        return arr[top];    }    public boolean isEmpty() {        return (top == -1);    }    public boolean isFull() {        return (size - 1 == top);    }    public static void main(String[] args) {        StackCustom stackCustom = new StackCustom(10);        System.out.println("=================");        stackCustom.push(10);        stackCustom.push(30);        stackCustom.push(50);        stackCustom.push(40);        stackCustom.printStack(stackCustom);        StackCustom sortedStack = sortStack(stackCustom);        System.out.println("=================");        System.out.println("After Sorting :");        System.out.println("=================");        sortedStack.printStack(sortedStack);    }    /**     * 排序算法     */    public static StackCustom sortStack(StackCustom stack) {        StackCustom tempStack = new StackCustom(10);        while (!stack.isEmpty()) {            int currentData = stack.pop();            while (!tempStack.isEmpty() && tempStack.peek() > currentData) {                stack.push(tempStack.pop());            }            tempStack.push(currentData);        }        return tempStack;    }    public void printStack(StackCustom stack) {        if (top >= 0) {            System.out.println("Elements of stacks are:");            for (int i = 0; i <= top; i++) {                System.out.println(arr[i]);            }        }    }}复制代码

运行结果:

【算法系列】堆栈数据结构_链表_05


以上是堆栈结构详细解析的全部内容,如果对你有所帮助,点个赞是对我最大的鼓励!