栈和队列

栈和队列不适合作为数据的记录工具,它们更多地是作为程序员的工具来运用。主要作为构思算法的辅助工具,而不是完全的数据存储工具。这些数据结构的生命周期比数组、链表等数据库类型的结构要短的多。在程序操作执行期间他们才被创建,通常用它们去执行某项特殊的任务;当完成任务后,它们就被销毁。
       下面的StackX类,实现一个栈的功能:

class  StackX
{
    
private int maxSize;
    
private char[] stackArray;
    
private int top;

    
public StackX(int max)
    
{
        maxSize 
= max;
        stackArray 
= new char[maxSize];
        top
=-1;
    }


    
public void push(char j)    //入栈,注意要先将top指针上移,然后将数据赋给新的top位置
    {
        stackArray[
++top] = j;
    }


    
public char pop()    //出栈,先取得数据,然后将top下移
    {
        
return stackArray[top--];
    }


    
public char peek()    //只查看栈顶的元素,top指针不动
    {
        
return stackArray[top];
    }


    
public boolean isEmpty()
    
{
        
return (top == -1);
    }

}
// end class StackX

 

对这个类的解释:

StackX是构造方法,根据参数规定的容量创建一个新栈。栈的域包括表示最大容量的变量、数组本身以及变量top,它存储栈顶元素的下标。

Push方法中将top值增加一,使它指向原顶端数据项的上面的一个位置,并在在这个位置上存储一个数据项,再次提醒,top是在插入数据项之前递增的。

Pop方法返回top标识的数据项值,然后top减一。这个方法有效地从栈中移除了数据项;虽然数据项仍然存在数组中,直到有新的数据项压入栈中覆盖这个数据项。但是它不能再被访问了。

Peek方法仅返回top所指的数据项的值,不对栈做任何改动。

IsEmpty方法在栈空时返回true,栈空时top值为-1

一种典型的应用是栈用于解析某种类型的文本串。通常,文本串是计算机语言写的代码行,而解析它们的程序就是编译器。一个典型的例子是分隔符匹配程序,它从字符串中不断读取字符,每次读取一个字符。若发现它是一个左分隔符,将它压入栈中。当从输入中读到一个右分隔符时,弹出栈顶的左分隔符,并且查看它是否合右分隔符相匹配。如果它们不匹配,则程序报错。如果栈中没有左分隔符和右分隔符匹配,或者一直存在着没有被匹配的分隔符,程序也报错。这个方法的可行性在于,最后出现的左边分隔符需要最先匹配,这个规律符合栈的后进先出的特点。
下面是分隔符匹配程序的代码:

import  java.io. * ;

class  StackX {}  这个类的定义前面已经给出
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++)//get chars in turn
        {
            
char ch = input.charAt(j);
            
switch(ch)
            
{
                
case '{':    //opening symbols
                case '[':
                
case '(':
                    theStack.push(ch);    
//push them
                    break;
                
                
case '}':    //closing symbols
                case ']':
                
case ')':
                    
if(!theStack.isEmpty())    //stack not empty
                    {
                        
char chx=theStack.pop();    //pop and check
                        if((ch=='}' && chx!='{')||(ch==']' && chx!='[')||(ch==')' && chx!='('))
                            System.out.println(
"ERROR: "+ch+" at "+j);
                    }

                    
else    //prematurely empty
                        System.out.println("Error:"+ch+" at "+j);
                    
break;
                
default:
                    
break;
            }
//end switch
        }
//end for
        
//at this point, all characters have been processed
        if(!theStack.isEmpty())
            System.out.println(
"Error: missing right delimiter");
    }
//end check
}
// end class Bracketchecker
//

class   BracketsApp
{
    
public static void main(String[] args) throws IOException
    
{
        
//System.out.println("Hello World!");
        String input;
        
while(true)
        
{
            System.out.print(
"Enter string containing delimiters:");
            System.out.flush();
            input 
= getString();//read a string from kbd
            if(input.equals(""))//quit if [Enter]
                break;

            BracketChecker theChecker 
= new BracketChecker(input);
            theChecker.check();
        }

    }
//end main

    
public static String getString() throws IOException
    
{
        InputStreamReader isr 
= new InputStreamReader(System.in);
        BufferedReader br 
= new BufferedReader(isr);
        String s 
= br.readLine();
        
return s;
    }

}
// end class BracketsApp

下面是一个队列的实现代码:

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


    
public void insert(long j) throws Exception    //put item at rear of queue
    {
        
if(this.isFull())    //throw Exception if queue is full
            throw new Exception("Can't insert because queue is Full");
        
if(rear == maxSize-1)    //deal with wraparound
            rear = -1;
        queArray[
++rear] = j;    //increment rear and insert
        nItems++;    //one more item
    }

    
    
public long remove() throws Exception    //take item fron front of queue
    {
        
if(this.isEmpty())    //throw Exception if queue is empty
            throw new Exception("Can't remove because queue is empty!");
        
long temp = queArray[front++];    //get value and incr front
        if(front == maxSize)    //deal with wraparound
            front = 0;
        nItems
--;    //one less item
        return temp;
    }


    
public long peekFront()    //peek at front of queue
    {
        
return queArray[front];
    }


    
public boolean isEmpty()
    
{
        
return (nItems == 0);
    }


    
public boolean isFull()
    
{
        
return (nItems == maxSize);
    }


    
public int size()
    
{
        
return nItems;
    }


    
//
    public static void main(String[] args) 
    
{
        
//System.out.println("Hello World!");
        Queue theQueue = new Queue(5);

        
try{
            theQueue.insert(
10);
            theQueue.insert(
20);
            theQueue.insert(
30);
            theQueue.insert(
40);
        }

        
catch(Exception ex)
        
{
            ex.printStackTrace();
        }


        
try{
            theQueue.remove();
            theQueue.remove();
            theQueue.remove();
            
//theQueue.remove();
            
//theQueue.remove();
        }

        
catch(Exception ex)
        
{
            ex.printStackTrace();
        }


        
try{
            theQueue.insert(
50);
            theQueue.insert(
60);
            theQueue.insert(
70);
            theQueue.insert(
80);
            
//theQueue.insert(90);
        }

        
catch(Exception ex)
        
{
            ex.printStackTrace();
        }


        
while(!theQueue.isEmpty())
        
{
            
long n = 0;
            
try{
                 n 
= theQueue.remove();
            }

            
catch(Exception ex)
            
{
                ex.printStackTrace();
            }

            System.out.print(n);
            System.out.print(
"  ");
        }

        System.out.println(
"");
    }
    //end main
}
    //end class Queue

 

解释:

insert()方法:运行的前提条件是队列未满,若插入已满队列时,会抛出异常。若可以插入,则是将rear(队尾指针)加一后,在队尾指针所指的位置处插入新的数据项。但是当rear指针指向数组的顶端,即maxSize-1位置的时候,在插入数据之前,它必须回绕到数组的底端。回绕操作把rear设置为-1,因此当rear1后,它等于0,是数组底端的下标值。最后年Items1

remove()方法:前提是队列不空,若对空队列执行此操作时,会抛出异常提示。若不空,由front指针得到队头数据项的值,然后将front1。但是如果这样做是front的值超过数组的顶端,front就必须绕回到数组下标为0的位置上。作这个检验之前,先将返回值临时村到,最后年Items1

peek()方法:返回front指针所指数据项的值。isFull()isEmpty()size()都依赖于nItems字段。

优先级队列是比栈和队列更专用的数据结构。它也有队头和队尾指针,也是从队头移除数据项。不过在优先级队列中,数据项按关键字的值有序,这样关键字最小的数据项总是在队头。数据插入的时候会按照顺序插入到合适的位置以确保队列的有序性。下面给出一种使用简单的数组实现优先级队列。这种实现方法插入比较慢,但是它比较简单,适用于数据量比较小,并且不是很注重插入速度的情况。代码如下:

class  PriorityQ 
{
    
//array in sorted order, from max at 0 to min at size-1
    private int maxSize;
    
private long[] queArray;
    
private int nItems;

    
public PriorityQ(int s)
    
{
        maxSize 
= s;
        queArray 
= new long[maxSize];
        nItems 
= 0;
    }


    
public void insert(long item)    //insert item
    {
        
int j;

        
if (nItems==0)    //if no items, insert at 0
        {
            queArray[nItems
++= item;
        }

        
else    //if items,
        {
            
for (j=nItems-1;j>=0 ;j-- )    //start at end,
            {
                
if (item>queArray[j])    //if new item larger,
                {
                    queArray[j
+1]=queArray[j];    //shift upward
                }

                
else    //if smaller,
                {
                    
break;    //done shifting
                }
    
            }
    //end for

            queArray[j
+1= item;    //insert it
            nItems++;
        }
    //end else
    }
    //end insert

    
public long remove()    //remove minimum item
    {
        
return queArray[--nItems];
    }


    
public long peekMin()    //peek at minimum item
    {
        
return queArray[nItems=1];
    }


    
public boolean isEmpty()    //true if queue is empty
    {
        
return (nItems == 0);
    }


    
public boolean isFull()    //true if full
    {
        
return (nItems == maxSize);
    }


    
///
    public static void main(String[] args) 
    
{
        
//System.out.println("Hello World!");
        PriorityQ thePQ = new PriorityQ(5);
        thePQ.insert(
30);
        thePQ.insert(
50);
        thePQ.insert(
10);
        thePQ.insert(
40);
        thePQ.insert(
20);

        
while (!thePQ.isEmpty())
        
{
            
long item = thePQ.remove();
            System.out.print(item 
+ " ");    //10,20,30,40,50
        }
    //end while

        System.out.println(
"");
    }
    //end main()
}
     // end class PriorityQ

 

说明:

优先级队列不像前面介绍的Queue类那样必须有frontrear字段,它的front总是nItems-1rear总是等于0。最复杂的就是insert()方法,它先检查队列中有没有数据项,如果没有,就插入到下标为0的单元里。否则,从数组顶部开始上移存在的比待插入数据还要小的数据项,直到找到第一个比待插入项大的数据项。然后将待插入项插入该项上面,并将nItems1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值