栈和队列
栈和队列不适合作为数据的记录工具,它们更多地是作为程序员的工具来运用。主要作为构思算法的辅助工具,而不是完全的数据存储工具。这些数据结构的生命周期比数组、链表等数据库类型的结构要短的多。在程序操作执行期间他们才被创建,通常用它们去执行某项特殊的任务;当完成任务后,它们就被销毁。
下面的StackX类,实现一个栈的功能:
package com.js.ai.modules.pointwall.testxfz;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
*
* @ClassName: StackX
* @Description: 堆栈类
* @author: xfzhong
* @date: 2017年5月24日
*/
class StackX{
private int maxSize;
private char[] stackArray;
private int top;
/**
*
* @Title:StackX
* @Description:StackX是构造方法,根据参数规定的容量创建一个新栈。
* 栈的域包括表示最大容量的变量、数组本身以及变量top,它存储栈顶元素的下标。
* @param max
*/
public StackX(int max) {
maxSize=max;
stackArray=new char[maxSize];
top=-1;
}
/**
*
* @Title: push
* @Description: Push(入栈)方法中将top值增加一,
* 使它指向原顶端数据项的上面的一个位置,
* 并在在这个位置上存储一个数据项,
* 再次提醒,top是在插入数据项之前递增的。
* 入栈,注意要先将top指针上移,然后将数据赋值给新的top位置
* @param j
* @return: void
*/
public void push(char j){
stackArray[++top]=j;
}
/**
*
* @Title: pop
* @Description: Pop方法返回top标识的数据项值,然后top减一。
* 这个方法有效地从栈中移除了数据项;虽然数据项仍然存在数组中,
* 直到有新的数据项压入栈中覆盖这个数据项。但是它不能再被访问了。
* 出栈,先取得数据,然后将top下移
* @return
* @return: char
*/
public char pop(){
return stackArray[top--];
}
/**
*
* @Title: peek
* @Description: Peek方法仅返回top所指的数据项的值,不对栈做任何改动。
只查看栈顶的元素,top指针不动。
* @return
* @return: char
*/
public char peek(){
return stackArray[top];
}
/**
*
* @Title: isEmpty
* @Description: IsEmpty方法在栈空时返回true,栈空时top值为-1。
* @return
* @return: boolean
*/
public boolean isEmpty(){
return (top==-1);
}
}
/**
*
* @ClassName: BracketChecker
* @Description: 分隔符匹配(检查)
* 一种典型的应用是栈用于解析某种类型的文本串。通常,文本串是计算机语言写的代码行,
* 而解析它们的程序就是编译器。一个典型的例子是分隔符匹配程序,它从字符串中不断读取字符,
* 每次读取一个字符。若发现它是一个左分隔符,将它压入栈中。当从输入中读到一个右分隔符时,
* 弹出栈顶的左分隔符,并且查看它是否合右分隔符相匹配。如果它们不匹配,则程序报错。
* 如果栈中没有左分隔符和右分隔符匹配,或者一直存在着没有被匹配的分隔符,程序也报错。
* 这个方法的可行性在于,最后出现的左边分隔符需要最先匹配,这个规律符合栈的后进先出的特点。
下面是分隔符匹配程序的代码:
* @author: xfzhong
* @date: 2017年5月24日
*/
class BracketChecker{
private String input;
public BracketChecker(String in) {
input=in;
}
public void check(){
int stackSize=input.length();
StackX theStack=new StackX(stackSize);
for(int j=0;j<input.length();j++){
char ch=input.charAt(j);
switch (ch) {
case '{':
case '[':
case '(':
theStack.push(ch);
break;
case '}':
case ']':
case ')':
if(!theStack.isEmpty()){
char chx=theStack.pop();
if((ch=='}' && chx!='{')||(ch==']' && chx!='[')||(ch==')' && chx!='(')){
System.out.println("error:"+ch+"at"+j);
}
}
else {
System.out.println("error:"+ch+"at"+j);
}
break;
default:
break;
}
}
if(!theStack.isEmpty())
System.out.println("error:missing right delimiter!");
}
}
/**
*
* @ClassName: BracketsApp
* @Description: 括号类BracketsApp
* @author: xfzhong
* @date: 2017年5月24日
*/
class BracketsApp{
public static String getString() throws IOException{
InputStreamReader isr=new InputStreamReader(System.in);
BufferedReader br=new BufferedReader(isr);
String s=br.readLine();
return s;
}
public static void main(String[] args) throws IOException {
String input;
while(true){
System.out.println("error:string containing delimiter!");
System.out.flush();
input=getString();
if(input.equals(""))
break;
BracketChecker theChecker=new BracketChecker(input);
theChecker.check();
}
}
}
/**
*
* @ClassName: Queue
* @Description: 队列实现代码
* @author: xfzhong
* @date: 2017年5月24日
*/
class Queue{
private int maxSize;
private long[] queArray;
private int front;
private int rear;
private int nItems;
public Queue(int s) {
maxSize=s;
queArray=new long[maxSize];
front=0;
rear=-1;
nItems=0;
}
/**
*
* @Title: insert
* @Description: insert()方法:运行的前提条件是队列未满,
* 若插入已满队列时,会抛出异常。若可以插入,则是将rear(队尾指针)加一后,
* 在队尾指针所指的位置处插入新的数据项。但是当rear指针指向数组的顶端,
* 即maxSize-1位置的时候,在插入数据之前,它必须回绕到数组的底端。
* 回绕操作把rear设置为-1,
* 因此当rear加1后,它等于0,是数组底端的下标值。最后年Items加1。
* @param j
* @throws Exception
* @return: void
*/
public void insert(long j) throws Exception{
if(this.isFull())
throw new Exception("can not insert because queue is full!");
if(rear==maxSize)//deal with wraparound
rear=-1;
queArray[++rear]=j;//increment rear and insert增量后插
nItems++;//one more item
}
/**
*
* @Title: remove
* @Description: remove()方法:前提是队列不空,若对空队列执行此操作时,
* 会抛出异常提示。若不空,由front指针得到队头数据项的值,
* 然后将front加1。但是如果这样做是front的值超过数组的顶端,
* front就必须绕回到数组下标为0的位置上。
* 作这个检验之前,先将返回值临时村到,最后年Items减1。
* @return
* @throws Exception
* @return: long
*/
public long remove() throws Exception{
if(this.isEmpty())
throw new Exception("can not remove because queue is empty!");
long temp=queArray[front++];
if(front==maxSize)
front=0;
nItems--;
return temp;
}
public boolean isFull(){
return (nItems==maxSize);
}
public boolean isEmpty(){
return (nItems==0);
}
public int size(){
return nItems;
}
/**
*
* @Title: peekFront
* @Description: peek()方法:返回front指针所指数据项的值。isFull()、
* isEmpty()、size()都依赖于nItems字段。
* @return
* @return: long
*/
public long peekFront(){
return queArray[front];
}
public static void main(String[] args) {
Queue theQueue=new Queue(5);
try {
theQueue.insert(10);
theQueue.insert(20);
theQueue.insert(30);
theQueue.insert(40);
} catch (Exception e) {
e.printStackTrace();
}
try {
theQueue.remove();
theQueue.remove();
theQueue.remove();
} catch (Exception e) {
e.printStackTrace();
}
try {
theQueue.insert(50);
theQueue.insert(60);
theQueue.insert(70);
theQueue.insert(80);
} catch (Exception e) {
e.printStackTrace();
}
while(!theQueue.isEmpty()){
long n=0;
try {
n=theQueue.remove();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("n="+n);
System.out.println(" ");
}
System.out.println("");
}
}
public class TestClass {
}
优先级队列是比栈和队列更专用的数据结构。它也有队头和队尾指针,也是从队头移除数据项。不过在优先级队列中,数据项按关键字的值有序,这样关键字最小的数据项总是在队头。数据插入的时候会按照顺序插入到合适的位置以确保队列的有序性。下面给出一种使用简单的数组实现优先级队列。这种实现方法插入比较慢,但是它比较简单,适用于数据量比较小,并且不是很注重插入速度的情况。代码如下:




浙公网安备 33010602011771号