您的位置:首页 > 编程语言 > Java开发

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

2017-10-01 16:22 337 查看

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);
}
}

}


运行输出

请输入盘子数:
3
盘 1 由 A 移至 C
盘 2 由 A 移至 B
盘 1 由 C 移至 B
盘 3 由 A 移至 C
盘 1 由 B 移至 A
盘 2 由 B 移至 C
盘 1 由 A 移至 C
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java