(3)栈原理与应用场景讲解

 数据结构&算法模块总结

1.顺序栈和链表栈


(1)顺序栈实现

①顺序栈基于数组,数组满时需要动态扩容

②代码实现

// 基于数组实现的顺序栈
public class ArrayStack {
  private String[] items;  // 数组
  private int count;       // 栈中元素个数
  private int n;           //栈的大小

  // 初始化数组,申请一个大小为n的数组空间
  public ArrayStack(int n) {
    this.items = new String[n];
    this.n = n;
    this.count = 0;
  }

  // 入栈操作
  public boolean push(String item) {
    // 数组空间不够了,直接返回false,入栈失败。
    if (count == n) return false;
    // 将item放到下标为count的位置,并且count加一
    items[count] = item;
    ++count;
    return true;
  }
  
  // 出栈操作
  public String pop() {
    // 栈为空,则直接返回null
    if (count == 0) return null;
    // 返回下标为count-1的数组元素,并且栈中元素个数count减一
    String tmp = items[count-1];
    --count;
    return tmp;
  }
}

③扩容复杂度分析

(2)链表实现

    逻辑原理和数组类似,直接看代码就好了。

public class StackBasedOnLinkedList {
    private Node top = null;   

    public void push(int value) {  
        Node newNode = new Node(value, null);  
        // 判断是否栈空  
        if (top == null) {  top = newNode;  } 
        else {  newNode.next = top;  top = newNode;   }  
    }   

    /**  * 我用-1表示栈中没有数据。  */  
    public int pop() {  
        if (top == null) return -1;  
        int value = top.data;  
        top = top.next;  return value;  
    }   

    public void printAll() {  
        Node p = top;  
        while (p != null) {  
        System.out.print(p.data + " ");  
        p = p.next;  
        }  
        System.out.println();  
    }   

    private static class Node {  
        private int data;  
        private Node next;   
        public Node(int data, Node next) {  
            this.data = data;  
            this.next = next;  
        }   
        public int getData() {  
            return data;  
        }  
    }  
}

(3)数据结构中栈与内存中栈区别

①内存中的堆栈是真实存在的物理区,数据结构中的堆栈是抽象的数据存储结构

【参考:JVM虚拟机栈和Native方法栈】

//例如main函数和add函数代码关系
main(){
  int res=0;
  int ret=0;
  int a=1;
  add(ret);  
}

int add(int sum;){
  int x=3;
  int y=5;
  ....
}

        这段代码中每个函数就是一个栈帧,在JVM虚拟机的内存模型如下:

        本质上:栈中存放的是多个栈帧,每个栈帧对应一个被调用的方法,主要包括局部变量表、操作数栈、动态链接、方法返回地址(方法出口)。每一个方法的执行,JVM 都会创建一个栈帧,并且将栈帧压入 Java 栈,方法执行完毕,该栈帧出栈。这里不详细介绍了。

2.栈应用场景


(1)浏览器前进和后退功能模拟

        在浏览器中,我们浏览页面时可以选择后退或前进。后退即返回之前浏览的页面,而前进则是在后退基础上使用,但它并不能前进到未加载过的页面。

        用两个栈即可实现

  • 把首次浏览的页面依次压入栈X

  • 当点击后退按钮时,再依次从栈X中出栈,并将出栈的数据依次放入栈Y。

  • 当点击前进按钮时,依次从栈Y中取出数据,放入栈X中。

  • 当栈X中没有数据时,那就说明没有页面可以继续后退浏览了。当栈Y中没有数据,那就说明没有页面可以点击前进按钮浏览了

 

 (2)两个栈实现队列

         将浏览器的功能再抽象化,其实可以发现就是栈模拟队列的过程。其实现思路如下:

    ①入队(add):每次入队,所有元素压入stack1中(此时顺序是逆序)。

    ②出队(remove):首先检查stack2中是否有元素,如果没有则stack1元素全部弹到stack2中(顺序还原了),然后stack2进行pop弹出顶部即可。如果stack2已经有元素直接弹出就行了。因为队列先进来的元素只会再stack1中,除非stack2空了才压进来。

    ③队首元素(peek):和出队一样,要检查stack2是否为空进行压入。然后stack2进行peek操作查看顶部元素即可。

    ④队空(empty):stack1和stack2必须全空,才表示没队列元素。

实现代码如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值