如何基于链表数组实现栈-算法通关村

如何基于链表/数组实现栈-算法通关村


1.栈基础知识

1.1栈的特征

  • 栈和队列是比较特殊的线性表,又称之为访问受限的线性表。栈是很多表达式、符号等运算的基础,也是递归的底层实现。理论上递归能做的题目栈都可以,只是有些问题用栈会非常复杂。
  • 栈底层实现仍然是链表或者顺序表,栈与线性表的最大区别是数据的存取的操作被限制了,其插入和删除操作只允许在线性表的一端进行。一般而言,把允许操作的一端称为栈顶(Top),不可操作的一端称为栈底(Bottom),同时把插入元素的操作称为入栈(Push),删除元素的操作称为出栈(Pop)。若栈中没有任何元素,则称为空栈。

1.2栈的操作

  • 栈的常用操作主要有:

    • push(E):增加一个元素E
    • pop():弹出元素E
    • peek():显示栈顶元素,但是不出栈
    • empty():判断栈是否为空
  • 我们在设计自己的栈的时候,不管用数组还是链表,都要实现上面几个方法。如果想测试一下自己对栈是否理解,做一下这道题就够了:入栈顺序为1234,所有可能的出栈序列是什么?

1.3Java 中的栈

  • java 的 util 中提供了栈 Stack 类。

  •   public class MainTest {
          public static void main(String[] args) {
              Stack<Integer> stack = new Stack();
              stack.push(1);
              stack.push(2);
              stack.push(9);
              System.out.println("栈顶元素为:" + stack.peek());
              while(!stack.empty()){
                  //只显示,不出栈
                  System.out.println(stack.peek());
                  //出栈并且显示
                  System.out.println(stack.pop());
              }
          }
      }
    

2.基于数组实现栈

  • top有的地方指向栈顶元素,有的地方指向栈顶再往上的一个空单位,本文采用指向栈顶空位置。

  • 采用顺序表实现的的栈,内部以数组为基础,实现对元素的存取操作。在应用中还要注意每次入栈之前先判断栈的容量是否够用,如果不够用,可以进行扩容。

  •   public class Test_Arr_Stack {
          public static void main(String[] args) {
              MyStack<String> stack = new MyStack<>();
              System.out.println(stack.peek());
              System.out.println(stack.isEmpty());
              stack.push("java");
              stack.push("is");
              stack.push("beautiful");
              stack.push("language");
              System.out.println(stack.peek());
              System.out.println(stack.isEmpty());
              System.out.println(stack.pop());
              System.out.println(stack.pop());
          }
      }
      
      class MyStack<T>{
          //实现栈的数组
          private Object[] stack;
          //栈顶元素为
          private int top;
      
          MyStack(){
              //初始容量为10
              stack = new Object[10];
          }
      
          //判断是否为空
          public boolean isEmpty(){
              return top == 0;
          }
      
          //返回栈顶元素
          public T peek(){
              T t = null;
              if(top > 0){
                  t = (T)stack[top-1];
              }
              return t;
          }
      
          //入栈
          public void push(T t){
              expandCapacity(top+1);
              stack[top] = t;
              top++;
          }
      
          //出栈
          public T pop(){
              T t = peek();
              if(top > 0){
                  stack[top-1] = null;
                  top--;
              }
              return t;
          }
      
          //扩大容量
          public void expandCapacity(int size){
              int len = stack.length;
              if(size > len){
                  size = size*3/2+1;
                  stack = Arrays.copyOf(stack, size);
              }
          }
      }
      
    

3.基于链表实现栈

  • 链栈的插入和删除都在头结点

  •   public class Test_LinkStack {
          public static void main(String[] args) {
              LinkStack<String> stack = new LinkStack<>();
              System.out.println(stack.peek());
              System.out.println(stack.isEmpty());
              stack.push("java");
              stack.push("is");
              stack.push("beautiful");
              stack.push("language");
              System.out.println(stack.peek());
              System.out.println(stack.isEmpty());
              System.out.println(stack.pop());
              System.out.println(stack.pop());
          }
      }
      
      
      class LinkStack<T>{
          //定义链表
          class LinkNode<T>{
              public T data;
              public LinkNode next;
          }
      
          public LinkNode<T> head;
          //构造函数初始化头指针
          LinkStack(){
              head = null;
          }
      
          //判断栈是否为空
          public boolean isEmpty(){
              if(head == null){
                  return true;
              }else{
                  return false;
              }
          }
      
          //取栈顶元素
          public T peek(){
              if(head == null){
                  return null;
              }
              T t = head.data;
              return t;
          }
      
          //入栈
          public void push(T t){
              if(t == null){
                  throw new NullPointerException("参数不能为空...");
              }
              if(head == null){
                  head = new LinkNode<T>();
                  head.data = t;
                  head.next = null;
              }else{
                  LinkNode<T> temp = head;
                  head = new LinkNode<T>();
                  head.data = t;
                  head.next = temp;
              }
          }
      
          //出栈
          public T pop(){
              if(head == null){
                  return null;
              }
              T t = head.data;
              head = head.next;
              return t;
          }
      }
    
  • 21
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

种一棵树leng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值