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

来源:互联网 发布:西安交大远程网络教育 编辑:程序博客网 时间:2024/06/06 07:02

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
原创粉丝点击