1、栈的创建:
我们接下来通过链表的形式来创建栈,方便扩充。
代码实现:
栈和队列是两种特殊的线性表,它们的逻辑结构和线性表相同,只是其运算规则较线性表有更多的限制,故又称它们为运算受限的线性表。
LinkedList数据结构是一种双向的链式结构,每一个对象除了数据本身外,还有两个引用,分别指向前一个元素和后一个元素,和数组的顺序存储结构(如:ArrayList)相比,插入和删除比较方便,但速度会慢一些。
栈的实现,有两个方法:一个是用java本身的集合类型Stack类型;另一个是借用LinkedList来间接实现Stack。
1.Stack实现
直接用Stack来实现非常方便,常用的api函数如下:
boolean isEmpty() // 判断当前栈是否为空
synchronizedE peek() //获得当前栈顶元素
synchronizedE pop() //获得当前栈顶元素并删除
E push(E object) //将元素加入栈顶
synchronizedint search(Object o) //查找元素在栈中的位置,由栈低向栈顶方向数2.LinkedList实现
LinkedList是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。
LinkedList实现 List 接口,能对它进行队列操作。
LinkedList实现 Deque 接口,即能将LinkedList当作双端队列使用。
当LinkedList被当做栈来使用时,常用api及对应关系如下:
栈方法 等效方法
push(e) addFirst(e)
pop() removeFirst()
peek() peekFirst() isEmpty() //判断是否为空
使用LinkedList实现
import java.util.*;
public class MyStack {
private LinkedList ll=new LinkedList();
public void push(Object o){
ll.addFirst(o);
}
public Object pop(){
return ll.removeFirst();
}
public Object peek(){
return ll.getFirst();
}
public boolean empty(){
return ll.isEmpty();
}
public static void main(String[] args){
MyStack ms=newMyStack();
ms.push("1");
ms.push("2");
ms.push("3");
System.out.println(ms.pop());
System.out.println(ms.peek());
System.out.println(ms.pop());
System.out.println(ms.empty());
}
}
队列定义
队列(Queue)是只允许在一端进行插入,而在另一端进行删除的运算受限的线性表
(1)允许删除的一端称为队头(Front)。
(2)允许插入的一端称为队尾(Rear)。
(3)当队列中没有元素时称为空队列。
(4)队列亦称作先进先出(FirstIn First Out)的线性表,简称为FIFO表。
//使用removeFirst()方法,返回队列中第一个数据,然后将它从队列中删除
借用LinkedList实现
import java.util.*;
public class MyQueue {
private LinkedList ll=new LinkedList();
public void put(Object o){
ll.addLast(o);
}
//使用removeFirst()方法,返回队列中第一个数据,然后将它从队列中删除
public Object get(){
return ll.removeFirst();
}
public boolean empty(){
return ll.isEmpty();
}
public static void main(String[] args){
MyQueue mq=newMyQueue();
mq.put("1");
mq.put("2");
mq.put("3");
System.out.println(mq.get());
System.out.println(mq.get());
System.out.println(mq.get());
System.out.println(mq.empty());
}
}
我们以下面的图来说明栈和队列如何存储元素和获取元素
用java本身的集合类型Stack类型
public interface Stack<T> { //栈接口,描述栈抽象数据类型,T表示数据元素的数据类型
public abstract booleanisEmpty(); //判断栈是否空
public abstract voidpush(T x); //元素x入栈
public abstract Tpeek(); //返回栈顶元素,未出栈
public abstract Tpop(); //出栈,返回栈顶元素
}
public final classLinkedStack<T>implementsStack<T> {
//
1. 定义成员变量
privateSinglyList<T> list; //使用单链表(第2章)存储栈元素
//
2.定义构造方法
/**
* 无参构造方法
*/
public LinkedStack(){ //构造空栈
this.list = newSinglyList<T>(); //构造空单链表
}
//
3.定义普通方法
/**
* 判断栈是否空,若空返回true
*/
public booleanisEmpty() { //判断栈是否空,若空返回true
return this.list.isEmpty();
}
/**
* 元素x入栈,空对象不能入栈
*/
public void push(T x) { //元素x入栈,空对象不能入栈
this.list.insert(0, x); //单链表头插入元素x
}
/**
* 返回栈顶元素(未出栈);若栈空返回null
*/
public T peek(){ //返回栈顶元素(未出栈);若栈空返回null
return this.list.get(0);
}
/**
* 出栈,返回栈顶元素;若栈空返回null<br>
* 若栈不空,单链表头删除,返回删除元素
*/
public T pop() { //出栈,返回栈顶元素;若栈空返回null
return this.list.remove(0); //若栈不空,单链表头删除,返回删除元素
}
/**
* 返回栈所有元素的描述字符串,形式为“(,)”
*/
public StringtoString() { //返回栈所有元素的描述字符串,形式为“(,)”
return this.getClass().getName()+" "+this.list.toString();
}
}
public interface Queue<T> { //队列接口,描述队列抽象数据类型,T表示数据元素的数据类型
public abstract booleanisEmpty(); //判断队列是否空
public abstract boolean add(Tx); //元素x入队,若添加成功,则返回true;否则返回false
public abstract Tpeek(); //返回队头元素,没有删除。若队列空,则返回null
public abstract Tpoll(); //出队,返回队头元素。若队列空,则返回null
}
public final classSeqQueue<T> implementsQueue<T> {
//
1. 定义成员变量
private Object element[]; //存储队列数据元素的数组
private int front, rear; //front、rear分别为队列头尾下标
private final static int LENGTH = 1024;//队列的初始容量
//
2.定义构造方法
/**
* 构造容量为length的空队列
*@param length
*/
public SeqQueue(int length){ //构造容量为length的空队列
if (length < SeqQueue.LENGTH) {
length = SeqQueue.LENGTH; //设置队列数组容量最小值
}
this.element = new Object[length];
this.front = this.rear = 0; //设置空队列
}
/**
* 构造默认容量的空队列
*/
public SeqQueue(){ //构造默认容量的空队列
this(SeqQueue.LENGTH);
}
/**
* 判断队列是否空,若空返回true
*@return 队列为空则返回true,否则返回false。
*/
public booleanisEmpty() { //判断队列是否空,若空返回true
return this.front == this.rear;
}
/**
* 元素x入队,空对象不能入队
*@param x 入队元素
*@return 若元素为null,则不能入队返回false,否则入队成功返回true。
*/
public boolean add(Tx) { //元素x入队,空对象不能入队
if (x == null){
returnfalse;
}// throw newNullPointerException("x==null"); //抛出空对象异常
if (this.front== (this.rear + 1) %this.element.length) {//若队列满,则扩充数组
Object[]temp= this.element;
this.element = new Object[temp.length * 2]; //重新申请一个容量更大的数组
intj = 0;
for(int i =this.front; i!= this.rear; i =(i + 1) % temp.length) { //按照队列元素次序复制数组元素
this.element[j++] =temp[i];
}
this.front = 0;
this.rear = j;
}
this.element[this.rear] =x;
this.rear = (this.rear+1) %this.element.length;
return true;
}
/**
* 返回队头元素,没有删除。若队列空,则返回null
*@return 返回队头元素,没有删除。若队列空,则返回null
*/
@SuppressWarnings("unchecked")
public T peek() { //返回队头元素,没有删除。若队列空,则返回null
return this.isEmpty()? null : (T)this.element[this.front];
}
/**
* 出队,返回队头元素,若队列空返回null
*@return 出队,返回队头元素,若队列空返回null
*/
@SuppressWarnings("unchecked")
public T poll() { //出队,返回队头元素,若队列空返回null
if (this.isEmpty())
returnnull;
T temp = (T)this.element[this.front];
this.front = (this.front + 1) %this.element.length;
return temp;
}
/**
* 返回队列所有元素的描述字符串,形式为“(,)”,按照队列元素次序
*/
public StringtoString() { //返回队列所有元素的描述字符串,形式为“(,)”,按照队列元素次序
StringBufferstrBuffer= new StringBuffer(this.getClass().getName() +"(");
for (int i=this.front;i != this.rear;i = (i +1) %this.element.length){
strBuffer.append(this.element[i].toString() +",");//按照队列元素次序复制数组元素
}
if(!this.isEmpty()) {
strBuffer.setCharAt(strBuffer.length() - 1,')'); //将串最后多余的一个字符','改为')'
} else{
strBuffer.append(")");
}
return newString(strBuffer); //由StringBuffer对象构造String对象
}
}