栈和队列

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

java数据结构语法 java 数据结构算法_java数据结构语法

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

java数据结构语法 java 数据结构算法_java数据结构语法

 

对这个类的解释:

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

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

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

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

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

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

下面是分隔符匹配程序的代码:

java数据结构语法 java 数据结构算法_java数据结构语法

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

java数据结构语法 java 数据结构算法_java数据结构语法

 

解释:

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

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

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

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

java数据结构语法 java 数据结构算法_java数据结构语法

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

java数据结构语法 java 数据结构算法_java数据结构语法

 

说明:

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