栈的实现及应用学习笔记--Java实现

1.定义

栈(Stack)是限定仅在表尾进行插入或删除操作的线性表。因此。表尾端有其特殊含义,称为栈顶(top),相应地,表头端称为栈低。一般来说,栈主要有两个操作:一个是进栈(PUSH),另一个是出栈(POP)。

2. 栈的表示和实现

1) 顺序栈,即栈的顺序存储结构,利用一组地址连续的存储单元依次存放自栈低到栈顶的数据元素。

–java实现

public class ArrayStack<T> implements Serializable {
    private static final long serialVersionUID = 74027006708386243L;
    private Object[] elementData; // 定义一个数组用于保存顺序栈的元素
    private int size = 0; // 保存顺序栈中元素的当前个数
    private int capacity; // 当前数组的长度

    public ArrayStack() {
        elementData = new Object[10]; // 默认长度为10的栈
    }

    public ArrayStack(int initSize) {
        elementData = new Object[initSize]; // 设置栈的长度
    }

    public ArrayStack(T element) {
        this();
        elementData[0] = element;
        size++;
    }

    public ArrayStack(T element, int initSize) {
        this.capacity = initSize;
        elementData = new Object[capacity];
        elementData[0] = equals(element);
        size++;
    }

    /*
     * @Description: 栈长度
     */
    public int size() {
        return size;
    }

    /**
     * @description:入栈
     */
    public void push(T element) {
        // TODO Auto-generated method stub
        ensureCapacity(size + 1);
        elementData[size++] = element;
    }

    // 如果数组的原有长度小于目前所需的长度 ,进行扩容
    private void ensureCapacity(int capacity) {
        // TODO Auto-generated method stub
        int oldcapacity = elementData.length;
        if (capacity > oldcapacity) {
            int newCapacity = (oldcapacity * 3) / 2 + 1;
            if (newCapacity < capacity) {
                newCapacity = capacity;
            }
            // minCapacity is usually close to size
            elementData = Arrays.copyOf(elementData, newCapacity);
        }
    }

    /**
     * @description: 出栈
     */
    public T pop() {
        if (!isEmpty()) {
            T lastValue = (T) elementData[size - 1];
            // 释放栈顶元素
            elementData[--size] = null;
            return lastValue;
        } else {
            return null;
        }
    }

    /**
     * @Description: 返回栈顶元素,但不删除栈顶元素
     */
    public T peek() {
        if (!isEmpty()) {
            return (T) elementData[size - 1];
        } else {
            throw new IndexOutOfBoundsException("空栈异常");
        }
    }

    public boolean isEmpty() {
        // TODO Auto-generated method stub
        return size == 0;
    }

    /**
     * @Description: 清空顺序栈
     */
    public void clear() {
        // 将底层数组所有元素赋为null
        Arrays.fill(elementData, null);
        size = 0;
    }

    public String toString() {
        if (size == 0) {
            return "[]";
        } else {
            StringBuilder sbBuilder = new StringBuilder("[");
            for (int i = size -1 ; i >= 0; i--) {
                sbBuilder.append(elementData[i].toString() + ",");
            }
        int len = sbBuilder.length();
        return sbBuilder.delete(len - 1, len).append("]").toString();
        }
    }
}

2)栈的链表表示

–java 实现

import java.io.Serializable;

public class LinkStack<T> implements Serializable {
    private static final long serialVersionUID = -4378447264374701299L;

    private class Node {
        private T data; // 保存节点的数据
        private Node next;

        public Node() {
            // TODO Auto-generated constructor stub
        }

        public Node(T data, Node next) {
            this.data = data;
            this.next = next;
        }
    }

    private Node top; // 保存该链表栈的栈顶元素
    private int size = 0; // 保存该链栈中已包含的节点数,即栈的长度

    public LinkStack() {
        // TODO Auto-generated constructor stub
        top = null;
    }

    public LinkStack(T element) {
        top = new Node(element, null);
        size++;
    }

    /**
     * @Description: 栈的长度
     */
    public int size() {
        return size;
    }

    /**
     * @despriction: 入栈
     **/
    public void push(T element) {
        top = new Node(element, top);
        size++;
    }

    /**
     * @Description: 出栈
     **/
    public T pop() {
        Node oldTop = top;
        top = top.next;
        oldTop.next = null;
        size--;
        return oldTop.data;
    }

    /**
     * @Description: 访问栈顶元素
     */
    public T peek() {
        return top.data;
    }

    /**
     * @Description: 判断顺序栈是否为空栈
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * @Description: 清空顺序栈
     */
    public void clear() {
        top = null;// 将栈所有元素赋为null
        size = 0;
    }

    public String toString() {
        if (isEmpty()) {
            return "[]";
        } else {
            StringBuilder sb = new StringBuilder("[");
            for (Node current = top; current != null; current = current.next) {
                sb.append(current.data.toString() + ", ");
            }
            int len = sb.length();
            return sb.delete(len - 2, len).append("]").toString();
        }
    }

}
3. 栈的应用

1) 进制转换
通过求余法可以将十进制转换为其他进制,比如要转为8 进制,则将原是进制除以8,记录余数,然后继续将商除以8,一直到商为 0为止,最后将余数倒序写出来即可。

–java实现


public class Conversion {
     /** 
       * @Title: conversion      
       * @Description: 将10进制正整数num转换为n进制     
       * @param num: 10进制正整数 
       * @param n: n进制 
       * @return 转换后的值 
       */
    public String Conversion(int num, int n){
        ArrayStack<Integer> myStack = new ArrayStack<Integer>();
        Integer result = num;
        while(true){
            //将余数存入栈
            myStack.push(result % n);
            result = result / n;
            if (result == 0) {
                break;
            }
        }
        StringBuilder sBuilder = new StringBuilder();
        //按栈的 顺序倒序输出即可
        while ((result = myStack.pop()) != null) {
            sBuilder.append(result);
        }
        return sBuilder.toString();
    }
}

2) 括号匹配检验
一般编程语言中括号都是成对出现的,比如:[],(),{}
凡是遇到括号的前半部分,即为入栈符号(PUSH);凡是遇到括号后半部分,就比对是否与栈顶元素相匹配(PEEK),如果相匹配,则出栈(POP),否者就匹配出错。

–Java实现

public class symbol_match {
    public boolean isMatch(String str) {
    ArrayStack<Character> myStack = new ArrayStack<Character>();
        char[] arr = str.toCharArray();
        for (char c : arr) {
            Character temp = myStack.pop();
            // 栈为空时只将c入栈
            if (temp == null) {
                myStack.push(c);
            }
            // 配对时c不入栈
            else if (temp == '[' && c == ']') {
            }
            // 配对时c不入栈
            else if (temp == '(' && c == ')') {
            }
            else {
                myStack.push(temp);
                myStack.push(c);
            }
        }
        return myStack.isEmpty();
    }
}

3)行编辑
–java实现

/** 
 * @ClassName: LineEdit 
 * @Description: 行编辑: 输入行中字符'#'表示退格, '@'表示之前的输入全都无效. 
 */  
public class lineEdit {
    public String lineEdit(String input) {
    ArrayStack<Character> myStack = new ArrayStack<Character>();
        char[] arr = input.toCharArray();
        for (char c : arr) {
            if (c == '#') {
                myStack.pop();
            } else if (c == '@') {
                myStack.clear();
            }else {
                myStack.push(c);
            }
        }
        StringBuilder sBuilder = new StringBuilder();
        Character temp = null;
        while((temp = myStack.pop()) != null){
            sBuilder.append(temp);
        }
        sBuilder.reverse();
        return sBuilder.toString();
    }   
}

4)汉诺塔游戏,递归实现
汉诺塔问题的描述如下:有A、B和C 3跟柱子,在A上从下往上按照从小到大的顺序放着 n 个圆盘,以B为中介,把盘子全部移动到C上。移动过程中,要求任意盘子的下面要么没有盘子,要么只能有比它大的盘子。本实例将演示如何求解3阶汉诺塔问题。
思路解析
为了将N个盘子从A移动到C,需要先将第N个盘子上面的N-1个盘子移动到B上,这样才能将第N个盘子移动到C上。同理,为了将第N-1个盘子从B移动到C上,需要将N-2个盘子移动到A上,这样才能将第N-1个盘子移动到C上。通过递归就可以实现汉诺塔问题的求解。

–java实现

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class hanoi {

    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        int n;
        BufferedReader buf = new BufferedReader(new        InputStreamReader(System.in));
        System.out.println("请输入盘子数:");
        n = Integer.parseInt(buf.readLine());
        move(n, 'A','B','C');
    }

    private static  void move(int n, char a, char b, char c) {
        // TODO Auto-generated method stub
        if (n == 1) {
        System.out.println("盘 " + n + " 由 " + a + " 移至 " + c);
        }else{
            move(n-1, a, c, b);
        System.out.println("盘 " + n + " 由 " + a + " 移至 " + c);
            move(n-1, b, a, c);
        }
    }

}

运行输出

请输入盘子数:
31 由 A 移至 C2 由 A 移至 B
盘 1C 移至 B
盘 3 由 A 移至 C1 由 B 移至 A
盘 2 由 B 移至 C1 由 A 移至 C
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值