Java栈的实现(顺序栈、链式栈)及栈的应用



Java栈的实现(顺序栈、链式栈)及栈的应用

1. 顺序栈的实现
顺序栈实现1
[java] view plaincopy在CODE上查看代码片派生到我的代码片
package lang;

import java.io.Serializable;
import java.util.Arrays;

/**
* @ClassName: ArrayStack
* @Description: 顺序栈
* @date 2014年1月20日 上午8:47:19
* @param <T>
*/
public class ArrayStack<T> implements Serializable {

/**
* @Fields serialVersionUID : TODO
*/
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];//默认长度为10的栈
}

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

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

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

/**
* @Title: push
* @Description: 入栈
* @param element
*/
public void push(T element) {
ensureCapacity(size + 1);
elementData[size++] = element;
}

private void ensureCapacity(int minCapacity) {
//如果数组的原有长度小于目前所需的长度
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
int newCapacity = (oldCapacity * 3) / 2 + 1;
if (newCapacity < minCapacity)
newCapacity = minCapacity;
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}

}

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

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

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

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

public String toString() {
if (size == 0) {
return “[]“;
} else {
StringBuilder sb = new StringBuilder(“[");
for (int i = size - 1; i > -1; i--) {
sb.append(elementData[i].toString() + “, “);
}
int len = sb.length();
return sb.delete(len – 2, len).append(“]”).toString();
}
}
}
顺序栈实现2

[java] view plaincopy在CODE上查看代码片派生到我的代码片
package lang;

import java.util.ArrayList;
import java.util.EmptyStackException;

public class ArrayStack2<E> extends ArrayList<E> {

/**
* @Fields serialVersionUID : TODO
*/
private static final long serialVersionUID = -4396620094929287983L;

public ArrayStack2() {
super();
}

public ArrayStack2(final int initialSize) {
super(initialSize);
}

public boolean empty() {
return isEmpty();
}

public E peek() throws EmptyStackException {
final int n = size();
if (n <= 0) {
throw new EmptyStackException();
} else {
return get(n – 1);
}
}

public E peek(final int n) throws EmptyStackException {
final int m = (size() – n) – 1;
if (m < 0) {
throw new EmptyStackException();
} else {
return get(m);
}
}

public E pop() throws EmptyStackException {
final int n = size();
if (n <= 0) {
throw new EmptyStackException();
} else {
return remove(n – 1);
}
}

public E push(final E item) {
add(item);
return item;
}

public int search(final Object object) {
int i = size() – 1; // Current index
int n = 1; // Current distance
while (i >= 0) {
final Object current = get(i);
if ((object == null && current == null)
|| (object != null && object.equals(current))) {
return n;
}
i–;
n++;
}
return -1;
}
}
2. 链式栈的实现:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
package lang;

import java.io.Serializable;

/**
* @ClassName: LinkStack
* @Description: 链式栈
* @date 2014年1月20日 下午3:46:40
* @param <T>
*/
public class LinkStack<T> implements Serializable{
/**
* @Fields serialVersionUID : TODO
*/
private static final long serialVersionUID = -4378447264374701299L;

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


private Node next; //指向下个节点的引用

public Node(){

}

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

private Node top; //保存该链栈的栈顶元素

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

public LinkStack(){
top = null;
}

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

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

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

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

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

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

/**
* @Title: clear
* @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. 栈的应用
3.1 将10进制正整数num转换为n进制
[java] view plaincopy在CODE上查看代码片派生到我的代码片
package stack.apply;

import org.junit.Test;

import lang.ArrayStack;

/**
* @ClassName: Conversion
* @Description: 将10进制正整数num转换为n进制
* @date 2014年1月21日 上午9:47:22
*/
public class Conversion {

/**
* @Title: conversion
* @Description: 将10进制正整数num转换为n进制
* @param num: 10进制正整数
* @param n: n进制
* @return 转换后的值
*/
private 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 sb = new StringBuilder();
// 按出栈的顺序倒序排列即可
while ((result = myStack.pop()) != null) {
sb.append(result);
}
return sb.toString();
}

@Test
public void testConversion(){
String s = conversion(13,2);
System.out.println(s);
}
}

3.2 行编辑:
输入行中字符’#'表示退格, ‘@’表示之前的输入全都无效.

[java] view plaincopy在CODE上查看代码片派生到我的代码片
package stack.apply;

import org.junit.Test;

import lang.ArrayStack;

/**
* @ClassName: LineEdit
* @Description: 行编辑: 输入行中字符’#'表示退格, ‘@’表示之前的输入全都无效.
* @date 2014年1月21日 上午10:17:06
*/
public class LineEdit {
/**
* @Title: lineEdit
* @Description: 行编辑
* @param input
* @return
*/
private 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 sb = new StringBuilder();
Character temp = null;
while ((temp = myStack.pop()) != null) {
sb.append(temp);
}
// 反转字符串
sb.reverse();
return sb.toString();
}

@Test
public void testLineEdit(){
String s = lineEdit(“abcd#dsa@#usera#22#8″);
System.out.println(s);
}
}

3.3 检验符号是否匹配.
‘['和']‘, ‘(‘和’)'成对出现时字符串合法.
例如”[][]()”, “[[([]([])()[])]]”是合法的; “([(])”, “[())"是不合法的

[java] view plaincopy在CODE上查看代码片派生到我的代码片
package stack.apply;

import org.junit.Test;

import lang.ArrayStack;

/**
* @ClassName: Match
* @Description: 检验符号是否匹配. ‘['和']‘, ‘(‘和’)'成对出现时字符串合法.
* 例如”[][]()”, “[[([]([])()[])]]”是合法的; “([(])”, “[())"是不合法的
* @date 2014年1月21日 上午10:14:47
*/
public class Match {
/**
* @Title: isMatch
* @Description: 检验符号是否匹配
* @param str 输入要匹配的字符串
* @return 是否匹配
*/
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 == ‘)’) {
}
// 不配对时c入栈
else {
myStack.push(temp);
myStack.push(c);
}
}
return myStack.isEmpty();
}

@Test
public void testMatch(){
boolean b = isMatch(“[[([]([])()[])]]”);
System.out.println(b);
}
}
http://blog.csdn.net/jiutianhe/article/list/4