Java中使用顺序表ArrayList和链表LinkedList方式实现栈Stack

首先我们应该知道栈:
遵循后进先出/先进后出的原则。最先放入栈中的元素 — 栈底元素,最后放入栈中的元素 — 栈顶元素。将元素放入栈中 ---- 入栈/压栈,将元素从栈中取出 ---- 出栈/弹栈。

import java.util.Stack;
    
    public class StackDemo {
    	public static void main(String[] args) {
    		Stack<String> s = new Stack<String>();
    		
    		// 添加元素
    		s.push("a");
    		s.push("b");
    		s.push("c");
    		s.push("d");
    		s.push("e");
    		s.push("f");
    		
    		// 查看栈顶元素
    		// 如果栈为空,则抛出空栈异常,因此最好判断栈是否为空
    		if(s.isEmpty())
    			System.out.println(s.peek());
    		
    		// 移除栈顶元素
    		System.out.println(s.pop());
    		
    		// 查找元素
    		// 从栈顶网栈底查找,且以1为基数
    		System.out.println(s.search("b"));
    		
    		System.out.println(s);
    	}
    }

上面通过java中Stack类创建的栈实例,实现对栈元素的插入、查找、移除和添加等基本操作。下面将介绍使用顺序表ArrayList和链表LinkedList方式实现栈Stack。

#1,通过顺序表方式实现

        import java.util.Arrays;
        import java.util.EmptyStackException;
        
        public class StackDemo2 {
        	public static void main(String[] args) {
        		// ....这里操作省略,读者可以粘贴上面的代码测试
        	}
        }
    
    // 这里自定义一个ArrStack类,用于实现顺序表结构原理
        class ArrStack{
        	// 定义两个属性,字符数组生成栈的空间并存储数据和size用于记录栈的长度;
        	private String[] data = new String[10];
        	private int size = 0;
        	
        	// 实现判断栈是否为空
        	public boolean empty() {
        		return size == 0;
        	}
        	
        	// 获取栈中最后插入的元素,即数组中最后一个元素
        	public String peek() {
        		// 判断栈中是否有元素
        		if(size == 0)
        			throw new EmptyStackException();   // 如果栈中没有元素,则抛出异常
        		return data[size - 1];  // 栈中有元素,则返回数组中最后一个元素
        	}
        	
        	public String pop() {
        		String str = this.peek();  // 先获取栈(数组)中最后一个元素
        		size--;
        		return str;
        	}
        	
        	public void push(String str) {
        		// 判断是否需要扩容
        		// size从0开始
        		if(size >= data.length)
        			data = Arrays.copyOf(data, data.length * 2); 
        			 // 栈的默认初始长度为10,扩容为增加到原长度的两倍
        		data[size++] = str;
        		/*
    				这里可以分解为:
    				data[size] = str;  // 向数组最后插入元素,相当于在栈顶插入元素
    				size++;   // 栈长度加一
    			*/
        	}
        	
        	public int search(String str) {
        		int k = -1;   /
        		for(int i = size - 1; i >= 0; i--) {
        			if(data[i] == str || str != null && str.equals(data[i]))
        				k = (size - i);   // 由于查找的元素,栈返回的是从栈顶到栈底的第一个元素
        				// 所以不应该是i+1,而是size - (i+1)+1;这里用k记录,为查找到则返回-1
        		}
        		return k;
        	}
        }

如上所示,在代码中自定义了一个ArrStack用于实现顺序表栈。看起来还是比较简单吧,哈哈。下面则介绍通过链表方式来实现。
# 2, 链表结构方式的栈

import java.util.Arrays;
import java.util.EmptyStackException;
import java.util.LinkedList;

public class StackDemo3 {
	public static void main(String[] args) {
				// 这里操作代码省略,读者可以自行写入并测试
	}
}

class LinkStack{
	private int size = 0;  // 记录链表长度
	private Node first;  // 定义链表中节点的头节点,这里指向的是栈的栈顶节点
	
	// 定义一个内部类,表示节点
	private class Node{
	// 这里只需要实现简单的逻辑和功能,因此只定义两个属性
		public Node next;  // next属性表示指向链表栈中前一个节点,这里当然是前面插入的节点啦
		// 另外的,这里的逻辑和和链表有一点,就是next在链表中指向的是下一个节点,
		//  而这里指向的是前面插入的节点, 这里的逻辑读者也要搞清楚
		
		public String data;  // 这个属性则记录节点上的数据啦
		public Node(Node next, String data) {
			super();
			this.next = next;
			this.data = data;
		}   // 定义的节点构造函数
	}
	
	public boolean empty() {
		return size == 0;
	}
	
	public String peek() {
		// 判断栈中是否有元素
		if(size == 0)
			throw new EmptyStackException();
		return this.first.data;  // 前面所说,first指向的是栈链表的栈顶节点,
		// 因此这里直接返回使用this.first.data表示栈顶节点的元素
	}
	
	public String pop() {
		String str = this.peek();  // 先获得栈顶元素
		this.first = this.first.next;  // 将栈顶节点指针指向原栈顶节点的前一个节点
		size--;  // 栈长度减一
		return str;
	}
	
	public void push(String str) {
		Node node = new Node(null, str);
		
		// 这里向栈顶插入新节点(元素),首先创建新节点
		if(size == 0) {
			this.first = node;   // 如果栈为空,
		}else { // 栈不为空
			node.next = this.first;  // 将新节点的前一个节点定义为栈链表中的栈顶节点
			this.first = node;  // 栈顶节点指针指向新节点,将新节点定义为新的栈顶节点
		}
		size++;
	}
	
	public int search(String str) {
		int k = -1;
		Node node = this.first;
		for(int i =0; i <= size - 1; i++) {
			if(node .data == str || str != null && str.equals(node .data))  // 判断元素是否相等
				k = i + 1;  // 因为这里是直接从栈顶开始向栈底开始查找,因此,i + 1就是该节点的为值
			node  =node.next;   // 指向前面的节点
		}
		return k;
	}
}

上面就简单实现了链表形式的栈结构。
在这里插入图片描述

这里附图一张链表的结构示意图。如果读者能看懂,那么恭喜你对链表的结构原理基本掌握啦。不懂请读者继续多学习啦。 欢迎评论交流。