Java数据结构和算法(五)——队列

队列,queqe,就是现实生活中的排队。

1、简单队列:

public class Queqe {
    private int array[];
    private int front;
    private int end;
    private int number;
    private int max;

    private Queqe(int maxsize){
        array = new int[maxsize];
        max = maxsize;
        front = 0;
        end = 0;
        number = 0;
    }

    private void insert(int item){
        if(isFull()){
            System.out.println("is full,can not insert");
            return;
        }
        array[end++] = item;
        number++;
    }

    private int remove(){
        if(isEmpty()){
            System.out.println("is empty,can not remove");
            return -1;
        }
        number--;
        return array[front++];
    }

    private boolean isFull(){
        return number == max;
    }
    private boolean isEmpty(){
        return number == 0;
    }

    private int size(){
        return number;
    }

    private int peekFront(){
        return array[front];
    }

    public static void main(String[] args) {
        Queqe q = new Queqe(4);
        System.out.println("queqe is empty:"+q.isEmpty());

        q.insert(1);
        q.insert(2);
        q.insert(3);
        q.insert(4);
        q.insert(5);

        System.out.println(q.size());
        System.out.println("front is "+q.peekFront());

        while(!q.isEmpty())
            System.out.println(q.remove());
    }
}

result:
queqe is empty:true
is full,can not insert
4
front is 1
1
2
3
4

还是通过数组实现,但是和栈不同的是,队列的话有队头队尾,队头指向队列的首部,而队尾指向队列的尾部,number为队列中数的个数,每当插入一个新元素,队尾后移,每当移除一个新元素,队首后移,插入和移除的同时根据队列是否为空或者是满,才进行插入和移除。

先进的元素排在前面,那么移除的时候就是先移除队头,达到先进先出的效果,·插入和移除并不用移动整个数组,只需改变队头和队列的指向,所以时间复杂度和栈一样都是O(1)。

2、不用number之后的方法改变

前面用了number统计队列中元素个数,其实不用这个变量,单靠队头和队尾也是可以实现队列。

    private boolean isFull(){
        return end == max;
    }
    private boolean isEmpty(){
        return (front ==0&&end ==0)||front == max;
    }

    private int size(){
        return end -front;
    }

队尾减去队头就是元素的个数,因为一旦插入,end是增加1的。

而判断是不是满了更简单,队尾移到数组尾部即是满了。

空的话会复杂一些,一种是一开始front为零,但是有元素插入,此时end不为零,如果两者为零那就是空了,还有就是不停remove之后,front移到最后,证明之前的元素全部remove掉了,此时也为空。

作者根据的是front和end的变化,然后再insert和remove中直接改变front和end的值,在isEmpty和isFull中,例如在isFull()中:

    private boolean isFull(){
        return end+2 == front||(front+max-2==end);
    }

作者的end一开始设为-1,然后一旦end超过max会变成-1,所以当中有着很复杂的位置关系。

这样更复杂。因为这样类似循环队列,超出之后又重头开始插入。

其实在isEmpty和isFull中直接进行判断就可以了。然后真的超出的时候直接打印错误后return。

3、优先级队列

银行办业务当然要排队,但是,银行的vip用户不需要,因为他存的钱比你多,银行重视这种客户,优先级高,所以他虽然比你晚来到银行,但是排号的时候拿到的号比你还前。

那这样的话,优先级队列就像是一开始就根据优先级排列好顺序的队列。

private void insert(int item){
    if(isFull()){
        System.out.println("is full,can not insert");
        return;
    }
    if(end == 0){
        array[end++] = item;
    }else{
        int i;
        for ( i = number-1; i >=0; i--) {
            if(item > array[i]){
                array[i+1] = array[i];
            }
        }
        array[i+1]= item;
        end++;
    }
    number++;
}

result:
queqe is empty:true
size:0
is full,can not insert
queqe is empty:false
size:4
front is 4
4
3
2
1

现在我们将数值大的看成是优先级高的,第一个插入直接插入数组第一位,后面插入的开始比较,如果比前面的数都小,那么就放在队列最后面,如果大的话,就将整个队列后推,然后找到适当的位置插入,和插入排序是类似的。这样插入元素的同时,就已经按照优先级从大到小的顺序排好序了(前:prefix expression 中:infix expression 后:postfix expression)。

4、算术表达式的解析

1+2+3=?

由于我们从小接受的教育就是从左到右,有括号计算括号里面,先乘除后加减这样的思路,然后看到上面那个算式的时候一下子就得出结果,这是中缀表达式。也就是我们脑里面计算算式的方式。

从左到右,1+2看后面,是+号,那可以直接算1+2的值为3,3+3后面是=号了,直接计算3+3=6。

1+2*3=?

从左到右,1+2看后面,是*号,那不能直接算1+2的值,先计算2*3=6,再看后面为=,所以计算1+6=7。

1*(2+3)=?

从左到右,1后面是*,所以本来先计算的,但是后面是(所以先看括号,括号里面是2+3=5后面是=,所以直接计算1*5=5。

但是计算机并不像人脑这么聪明。一眼看过去基本可以心算。计算机认后缀表达式比较容易,如果我们从小就接受的是后缀表达式的方式的话,那对于我们来说一样可以。

后缀表达式的话就用符号a,b,c表示了,因为多位数字的话,写成1242132+,根本就不知道是那两个数字相加,那么就要有分隔符,但是无疑会增加难度。

a+b-c转后缀:

读a,读到+,继续读到b,写成ab,再读到-号可以将+放在ab后面,即ab+,读入c,后面结束了则ab+c-。

a+b*c转后缀:

读a,读+,读b,放置为ab,再读后面,*优先级大于+号,暂时不能放+,再读c,c后面结束,所以可以放入*,在放+,即abc*+。

a*(b+c)转后缀:

读a,读*,后面发现(不能放置*,(里比*优先级高,读b+c,后面为),可变为bc+,再和a*合,即abc+*。

这篇虽然讲得是队列,但是要用到的结构是栈,因为进来进去的。这里的算数不用压入栈,直接输出。

a+b-c转后缀:

直接输出a,读+,栈空压入栈,再输出b,栈非空,弹出+,读到-,+优先级>= -,输出+,压-入栈,输出c,结束了,弹出-。

最后结果:ab+c-。

a+b*c转后缀:

直接输出a,读+,栈空压入栈,再输出b,栈非空,弹出+,读到*,+优先级< -,所以先+压入栈,再压*,输出c,结束了,弹出*,再弹+。

最后结果:abc*+。

a*(b+c)转后缀:

直接输出a,读*,栈空压入栈,读到(压(入栈,输出b,读+,压入栈,输出c,读),发现后面结束可以弹出+并输出,弹出(不输出,弹出*。

最后结果:abc+*。

看了这个分析过程之后,就是利用栈,对操作符进行栈的压入和弹出。

如果纯粹用高级语言写计算器,直接使用中缀表达式即可,但是到了底层的编译器,就是需要后缀表达式实现,还要考虑到位数和其他操作符,可想代码远远比上面的复杂。

整体的思路就是这样,代码的实现就是通过栈和条件判断进行入栈和出栈即可。

时间: 2024-10-11 06:00:03

Java数据结构和算法(五)——队列的相关文章

【Java数据结构学习笔记之二】Java数据结构与算法之队列(Queue)实现

  本篇是数据结构与算法的第三篇,本篇我们将来了解一下知识点: 队列的抽象数据类型 顺序队列的设计与实现 链式队列的设计与实现 队列应用的简单举例 优先队列的设置与实现双链表实现 队列的抽象数据类型   队列同样是一种特殊的线性表,其插入和删除的操作分别在表的两端进行,队列的特点就是先进先出(First In First Out).我们把向队列中插入元素的过程称为入队(Enqueue),删除元素的过程称为出队(Dequeue)并把允许入队的一端称为队尾,允许出的的一端称为队头,没有任何元素的队列

Java数据结构与算法(4) - 队列(Queue和PriorityQ)

队列: 先进先出(FIFO). 优先级队列: 在优先级队列中,数据项按照关键字的值有序,关键字最小的数据项总在对头,数据项插入的时候会按照顺序插入到合适的位置以确保队列的顺序,从后往前将小于插入项的数据项后移.在图的最小生成树算法中应用优先级队列. 示例代码: package chap04.Queue; class Queue { private int maxSize; private long[] queArray; private int front; private int rear;

Java数据结构与算法(3):队列

队列也是一种表,不同的是队列在一端进行插入而在另一端进行删除. 队列模型 队列的基本操作包括入队.出队操作.在表的末端插入元素,在表的开头删除元素,即先进先出(FIFO). 队列的数组实现 对于每一个队列数据结构,保留一个数组items以及位置front和back,分别表示队列的两端,还要记录元素的个数size.操作过程应该是:当一个元素x入队,size和back增1,置items[back]=x:出队时,返回items[front],size减1,然后front增1. 初始队列: 入队: 出队

java数据结构与算法之(Queue)队列设计与实现

[版权申明]转载请注明出处(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/53375004 出自[zejian的博客] 关联文章: java数据结构与算法之顺序表与链表设计与实现分析 java数据结构与算法之双链表设计与实现 java数据结构与算法之改良顺序表与双链表类似ArrayList和LinkedList(带Iterator迭代器与fast-fail机制) java数据结构与算法之栈设计与实现 java数据结构

java数据结构与算法之平衡二叉树(AVL树)的设计与实现

[版权申明]未经博主同意,不允许转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/53892797 出自[zejian的博客] 关联文章: java数据结构与算法之顺序表与链表设计与实现分析 java数据结构与算法之双链表设计与实现 java数据结构与算法之改良顺序表与双链表类似ArrayList和LinkedList(带Iterator迭代器与fast-fail机制) java数据结构与算法之栈(Stack)设

java数据结构与算法之树基本概念及二叉树(BinaryTree)的设计与实现

[版权申明]未经博主同意,不允许转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/53727333 出自[zejian的博客] 关联文章: java数据结构与算法之顺序表与链表设计与实现分析 java数据结构与算法之双链表设计与实现 java数据结构与算法之改良顺序表与双链表类似ArrayList和LinkedList(带Iterator迭代器与fast-fail机制) java数据结构与算法之栈(Stack)设

java数据结构与算法之递归思维(让我们更通俗地理解递归)

[版权申明]转载请注明出处(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/53452971 出自[zejian的博客] 关联文章: java数据结构与算法之顺序表与链表设计与实现分析 java数据结构与算法之双链表设计与实现 java数据结构与算法之改良顺序表与双链表类似ArrayList和LinkedList(带Iterator迭代器与fast-fail机制) java数据结构与算法之栈(Stack)设计与实现 j

Java数据结构和算法之栈与队列

二.栈与队列 1.栈的定义 栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表. (1)通常称插入.删除的这一端为栈顶(Top),另一端称为栈底(Bottom). (2)当表中没有元素时称为空栈. (3)栈为后进先出(Last In First Out)的线性表,简称为LIFO表. 栈的修改是按后进先出的原则进行. 每次删除(退栈)的总是当前栈中"最新"的元素,即最后插入(进栈)的元素,而最先插入的是被放在栈的底部,要到最后才能删除. 图1 [示例]元素是以a1,a2,-,a

Java数据结构与算法之集合

线性表.链表.哈希表是常用的数据结构,在进行Java开发时,SDK已经为我们提供了一系列相应的类来实现基本的数据结构.这些类均在java.util包中. 一.Collection接口 Collection是最基本的集合接口,一个Collection代表一组Object.一些Collection允许相同元素而另一些不行.一些能排序而另一些不行.Java  SDK不提供直接继承自Collection的类,Java  SDK提供的类都是继承自Collection的"子接口"如List和Set