Java数据结构与算法(第四章栈和队列)


本章涉及的三种数据存储类型:栈、队列和优先级队列。java

不一样类型的结构程序员

程序员的工具
算法

        数组是已经介绍过的数据存储结构,和其余结构(链表、树等等)同样,都适用于数据应用中做数据记录。数据库

        然而,本章要讲解的是数据结构和算法更多的是做为程序员的工具来运用。它们组要做为构思算法的辅助工具,而不是彻底的数据存储工具。这些数据结构的生命周期比那些数据库类型的结构要短的多。在程序操做执行期间它们才被建立,一般它们去执行某项特殊的任务,当完成以后,它们就被销毁。
数组

受限访问数据结构

        在数组中,只要知道下标就能够访问数据项。或顺序访问等。数据结构和算法

        而本章的数据结构中,访问时受限制的,即在特定时刻只有一个数据项能够被读取或者被删除(除非“做弊”);
工具

        这些结构接口的设计加强了这种受限访问。访问其余数据项(理论上)是不容许的。
spa

更加抽象设计

        栈、队列和优先级队列是比数组和其余数据存储结构更为抽象的结构。主要经过接口对栈、队列和优先级队列进行定义,这些接口代表经过他们能够完成的操做,而它们的主要实现机制对用户来讲是不可见的。

        例如,栈的主要机制能够用数组来实现,但它也能够用链表了实现。优先级队列的内部实现能够用数组或一种特别的书———堆来实现。


        栈只容许访问一个数据项:即最后插入的数据项。移除这个数据项后才能访问倒数第二个插入的数据,以此类推。

栈的Java代码

public class Stack {
    private int maxSize;
    private long[] stackArray;
    private int top;
    public Stack(int s){
        maxSize = s;
        stackArray = new long[maxSize];
        top=-1;
    }
    public void push(long j){
        stackArray[++top] = j;
    }
    public long pop(){
        return stackArray[top--];
    }
    public long peek(){
        return stackArray[top];
    }
    public boolean isEmpty(){
        return (top==-1);
    }
    public boolean isFull(){
        return top==maxSize-1;
    }
}
public static void main(String[] args) {
    Stack theStack = new Stack(10);
    theStack.push(10);
    theStack.push(20);
    theStack.push(30);
    theStack.push(40);
    while(!theStack.isEmpty()){
        long value = theStack.pop();
        System.out.print(value);
        System.out.print("    ");
    }
}
//输出:
40	30	20	10

栈的效率

        栈操做所耗的时间不依赖与栈中数据项的个数,所以操做时间很短。栈不须要比较和移动操做。

队     列

        “队列”(queue)这个单词是英国人说的“排”(line)(一种等待服务的方式)。

        队列是一种数据结构,有点相似栈,只是在队列中第一个插入的数据项也会最早被移除(先进先出,FIFO),而在栈中,最后插入的数据项最早移除。

队列的Java代码

public class Queue {
    private int maxSize;
    private long[] queueArray;
    private int front;
    private int rear;
    private int nItems;
    
    public Queue(int s){
        maxSize = s;
        queueArray = new long[maxSize];
        front = 0;
        rear = -1;
        nItems = 0;
    }
    public void insert(long j){
        if(rear == maxSize-1)
            rear = -1;
        queueArray[++rear]=j;
        nItems++;
    }
    public long remove(){
        long temp = queueArray[front++];
        if(front==maxSize)
            front = 0;
        nItems--;
        return temp;
    }
    public long peekfront(){
        return queueArray[front];
    }
    public boolean isEmpty(){
        return nItems ==0;
    }
    public boolean isFull(){
        return nItems == maxSize;
    }
    public int size(){
        return nItems;
    }
}
public static void main(String[] args) {
    Queue theQueue = new Queue(5);
    
    theQueue.insert(10);
    theQueue.insert(20);
    theQueue.insert(30);
    theQueue.insert(40);
    
    theQueue.remove();
    theQueue.remove();
    theQueue.remove();
    
    theQueue.insert(50);
    theQueue.insert(60);
    theQueue.insert(70);
    theQueue.insert(80);
    theQueue.insert(90);
    theQueue.insert(100);
    
    while(!theQueue.isEmpty()){
        long n = theQueue.remove();
        System.out.print(n);
        System.out.print(" ");
    }
    System.out.println("");
}

队列的效率

        和栈同样,队列中插入数据项和移除数据项的时间复杂度均为O(1)。

双端队列

        双端队列,就是一个两端都是结尾的队列。队列的 每一端均可以插入数据项和移除数据项。这些方法能够叫作insertLeft()和insertRight(),以及removeLeft()和removeRight()。

        双端队列与栈或队列相比,是一种多用途的数据结构,在容器类库中有时会用双端队列来提供栈和队列的两种功能。可是,双端队列不像栈和队列那么经常使用。。。。。。。

优先级队列

        优先级队列是比栈和队列更专用的数据结构。但它在不少的状况下都颇有用。像普通队列同样,优先级队列有一个对头和一个队尾,而且也是从头移除数据项。不过在优先级队列中,数据项按关键字的值有序,这样关键字最小的数据项(或者在某些实现中关键字最大的数据项)老是在队头。数据项插入的时候会按照顺序插入到合适的位置以确保队列的顺序。

优先级队列Java代码

public class PriorityQueue {
    private int maxSize;
    private long[] queueArray;
    private int nItems;
    
    public PriorityQueue(int s){
        maxSize = s;
        queueArray = new long[maxSize];
        nItems = 0;
    }
    
    public void inser(long item) {
        int i;
        if(nItems==0)
            queueArray[nItems++] = item;
        else
        {
            for (i = nItems-1; i>=0; i--) {
                if(item>queueArray[i])
                    queueArray[i+1] = queueArray[i];
                else
                    break;
            }
            queueArray[i+1] = item;
            nItems++;
        }
    }
    
    public long remove(){
        return queueArray[--nItems];
    }
    
    public long meekMin(){
        return queueArray[nItems-1];
    }
    
    public boolean isEmpty(){
        return nItems
            ==0;
    }

    public boolean isFull(){
        return nItems==maxSize;
    }
}
public static void main(String[] args) {
    PriorityQueue queue = new PriorityQueue(5);
    
    queue.inser(30);
    queue.inser(50);
    queue.inser(10);
    queue.inser(40);
    queue.inser(20);
    
    while(!queue.isEmpty()){
        long item = queue.remove();
        System.out.print(item);
        System.out.print(" ");
    }
    System.out.println("");
}
//输出:10 20 30 40 50

    在main()方法中随机插入5个数据项,随后移除并显示它们。最小的数据项老是最早移除,因此输出是:

10 20 30 40 50

优先级队列的效率

        在本章实现的优先级队列中,插入操做须要O(N)的时间,而删除则须要O(1)的时间。

解析算术表达式

后缀表达法

        平常算术表达式是将操做符(operator)(+,-,*,/)放在两个操做数(operands)(数字或表明数字的字母)之间的。由于操做符写在操做数的中间,因此把这表写法成为中缀表达法。

        在后缀表达式中【也称为波兰逆序表达式(Reverse Polish Natation),或者RPN】,它是由觉得波兰数学家发明的,操做符跟在两个操做数的后面。这样,A+B就成为AB+,A/B成为AB/。更复杂的以下表:

中缀表达式 后缀表达式
A+B-C AB+C-
A*B/C AB*C/
A+B*C ABC*+
A*B+C AB*C+
A*(B+C) ABC+*
A*B+C*D AB*CD*+
(A+B)*(C-D) AB+CD-*
((A+B)*C)-D AB+C*D-
A+B(C-D/(E+F)) ABCDEF+/-*+

后缀表达式求职。。。。。

小    结

  • 栈、队列和优先级队列是常常用于简化某些程序操做的数据结构。

  • 在这些数据结构中,只有一个数据项能够被访问。

  • 栈容许访问最后一个插入的数据项。

  • 栈中重要的操做是在栈顶插入(压入)一个数据项,以及从栈顶移除(弹出)一个数据项。

  • 队列只容许访问第一个插入的数据项。

  • 队列的重要操做是在队尾插入数据项和在队头移除数据项。

  • 队列能够实现为循环队列,它基于数组,数组下标能够从数组末端回绕到数组的开始位置。

  • 优先级队列容许访问最小(或者有时是最大)的数据项。

  • 优先级队列的重要操做是有序地插入新数据项和移除关键字最小的数据项。

  • 这些数据结构能够用数组实现,也能够用其余机制(例如链表)来实现。

  • 普通算术表达式是用中缀表达法表示的,这种命名的缘由是操做符写在两个操做的中间。

  • 在后缀表达法中,操做符跟在两个操做数的后面。

  • 算术表达式求值一般都是先转换成后缀表达式,而后再求后缀表达式的值。

  • 在中缀表达式转换到后缀表达式以及求后缀表达式的值过程里,栈都是颇有用的工具。

相关文章
相关标签/搜索