栈(stack)是一个先入后出的有序列表;其元素的插入和删除只能从一端进行操作,我们将其称之为栈顶(Top),另一端我们称之为栈底(Bottom)。

栈的应用场景

  1. 子程序的调用:在跳往子程序之前,将下个指令的地址存到堆栈中,子程序结束执行将地址取出,回到原来的程序中。
  2. 处理递归调用:和子程序调用类似,除了存储下一个指令地址以外,将参数、区域变量等数据也存入堆栈中。
  3. 表达式转换:中缀表达式转后缀表达式以及表达式求值。
  4. 二叉树的遍历
  5. 图形的深度优先搜索法。

利用数组模拟栈

分析思路

定义数组变量用来存储数组,模拟栈 ;

定义指针变量top,初始化为-1;

入栈的操作,当有数据加入到栈时,top++;stack[top]=data;

出栈操作,int value=stack[top];top--;return value;

//代码演示
class Stack{
    public int[] stack;
    public int maxsize;
    public int top=-1;
    
    //构造方法
    public Stack() {
    }
    public Stack(int maxsize) {
        this.maxsize = maxsize;
        stack=new int[this.maxsize];
    }

    //栈满
    public boolean isfull(){
        return top==maxsize-1;
    }

    //栈空
    public boolean isEmpty(){
        return top==-1;
    }
    //入栈
    public void push(int num){
        if(isfull()){
            System.out.println("栈满");
            return;
        }
        top++;
        stack[top]=num;
    }

    //出栈
    public int pop(){
        if(isEmpty()){
            System.out.println("栈为空");
        }
        int value=stack[top];
        top--;
        return value;
    }

    //显示栈
    public void show(){
        if(isEmpty()){
            System.out.println("栈空");
            return;
        }
        //需要从栈顶开始显示数据
        for(int i=top;i>=0;i--){
            System.out.println(stack[i]);
        }
    }
}

注意:在类中定义了top;但是在方法中操作top指针的值会改变top的值。


利用链表模拟栈

分析思路

入栈:定义辅助指针完成遍历,遍历到最后,从最后添加节点;同时让top指针指向添加的这个节点

出栈:定义辅助指针完成遍历;遍历找到top的前一个节点;定义辅助变量保存top值用来做函数的返回值,最后删除top这个节点。

显示:首先需要反转整个链表,然后定义辅助指针完成遍历显示。

反转链表:定义反转的头指针Reverse,定义辅助指针完成遍历cur,定义一个用来保存当前指针的下一个指针next;遍历到一个节点,将这个节点取下放在新的链表的最前端;

        //遍历原来的链表,遍历到一个节点将其取出,并放在新的链表的最前端
        while (cur!=null){
            //保存当前节点的下一个节点,后面要使用
            next=cur.next;
            //将cur的下一个节点指向新链表的最前端
            cur.next=Reverse.next;
            //将cur连接到新链表上
            Reverse.next=cur;
            //将cur后移
            cur=next;
        }
            head.next=Reverse.next;
        }
//代码实现
//用链表模拟栈
class Stack2 {
    //定义一个栈顶指针
    public Node top;
    //定义一个头节点
    Node head = new Node();

    //构造方法
    public Stack2() {
    }

    //栈为空
    public boolean isempty() {
        return top == null;
    }

    //入栈
    public void push(Node N) {
        //因为头指针不能动,定义一个辅助指针用来遍历
        Node temp = head;
        while (true) {
            if (temp.next == null) {//找到链表的尾部
                break;
            }
            temp = temp.next;
        }
        temp.next = N;
        top = N;
    }

    //出栈 遍历到最后一个节点top;找到top的前一个节点;将top节点从链表删除
    public Node pop() {
        if (isempty()) {
            System.out.println("链表为空");
        }
        //因为头指针不能动,定义一个辅助指针用来遍历,找到top节点的前一个节点
        Node temp = head;
        //定义出栈的辅助指针,因为top指针需要向前移动
        Node last = top;
        //遍历找到top的前一个节点
        while (true) {
            if (temp.next == top) {//找到了top的前一个节点
                break;
            }
            temp = temp.next;
        }
        //将top节点从链表的末尾删除
        temp.next = top.next;
        //将top指针指向这个节点,完成指针向前移动一位
        top = temp;
        return last;
    }

    //栈的显示,栈的显示从栈顶开始显示,所以我们需要先将链表反转,接着开始遍历显示链表
    public void show() {
        if (head.next==null) {
            System.out.println("链表为空");
            return;
        }
        reverse(head);
        Node temp = head.next;
        while (true) {
            if (temp == null) {//遍历到链表的最后
                break;
            }
            System.out.println(temp.No);
            temp = temp.next;
        }
    }

    //链表反转
    public void reverse(Node head) {
        if(head.next==null ||head.next.next==null){
            //链表为空或只有一个节点,则不需要反转
            return;
        }
        //因为头指针不能动,定义一个辅助指针用来遍历
        Node cur = head.next;
        //定义一个遍历来保存当前节点的下一个节点
        Node next=null;
        //定义一个反转头指针
        Node Reverse =new Node();
        //遍历原来的链表,遍历到一个节点将其取出,并放在新的链表的最前端
        while (cur!=null){
            //保存当前节点的下一个节点,后面要使用
            next=cur.next;
            //将cur的下一个节点指向新链表的最前端
            cur.next=Reverse.next;
            //将cur连接到新链表上
            Reverse.next=cur;
            //将cur后移
            cur=next;
        }
            head.next=Reverse.next;
        }

    }

    //创建节点
    class Node {
        public int No;
        public Node next;

        public Node() {
        }

        public Node(int no) {
            No = no;
        }
    }

posted @ 2020-12-31 19:07  胡木杨  阅读(81)  评论(0)    收藏  举报