算法和数据结构(四)

队列

上一篇随笔记录了一个不单单用来记录数据的,更多的用来作为构思算法的辅助工具的一种数据结构 栈,今天我们来介绍另外一种 队列。

首先,介绍一下队列的基本概念

队列(queue)是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。

  队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO—first in first out)线性表。

  比如我们去电影院排队买票,第一个进入排队序列的都是第一个买到票离开队列的人,而最后进入排队序列排队的都是最后买到票的。

  在比如在计算机操作系统中,有各种队列在安静的工作着,比如打印机在打印列队中等待打印。

  队列分为:

  ①、单向队列(Queue):只能在一端插入数据,另一端删除数据。

  ②、双向队列(Deque):每一端都可以进行插入数据和删除数据操作。

  这里我们还会介绍一种队列——优先级队列,优先级队列是比栈和队列更专用的数据结构,在优先级队列中,数据项按照关键字进行排序,关键字最小(或者最大)的数据项往往在队列的最前面,而数据项在插入的时候都会插入到合适的位置以确保队列的有序。

 单向队列

 单向队列的实现,很大程度上是根据一种“循环队列”的原理进行操作。也就是说,如果我们的队尾指针指向队列最大值处,同时之前队列有过删除操作,那么此时的队列并不满,再进行插入操作时,队尾指针回指向队头,进行插入。

我们直接上代码:

package discovery;

/**
 * Author :zhanghong
 * Date   :2019-02-17 16:01.
 */
public class MyQueue {
    private Object[] queArray;
    //队列总大小
    private int maxSize;
    //前端
    private int front;
    //后端
    private int rear;
    //队列中元素的实际数目
    private int nItems;

    public MyQueue(int Size){
        maxSize=Size;
        queArray=new Object[maxSize];
        front=0;
        rear=-1;
        nItems=0;
    }

    //返回队列的大小
    public int getSize(){
        return nItems;
    }

    //判断队列是否为空
    public boolean isEmpty(){
        return (nItems ==0);
    }

    //判断队列是否满了
    public boolean isFull(){
        return (nItems == maxSize);
    }

    //查看队头数据
    public Object getFront(){
        return queArray[front];
    }

    //删除数据
    public Boolean delete(){
        if(!isEmpty()){
            queArray[front]=null;
            front++;
            if(front==maxSize){
                front=0;
            }
            nItems--;
        }
        return false;
    }


    //增加数据

    public void add(Object item){
        if(isFull()){
            System.out.println("队列已满");
        }else {
            if(rear==maxSize-1){
                rear=-1;
            }
            queArray[++rear]=item;
                nItems++;
        }
    }
}

测试一下:

package discovery;

import static discovery.ChoiceSort.display;
import static discovery.ChoiceSort.sort;

/**
 * Author :zhanghong
 * Date   :2018-08-13 15:00.
 */
public class Run {

    public static void main(String[] args) {
//        MyThread t1 = new MyThread();
//        MyThread t2 = new MyThread();
//        MyThread t3 = new MyThread();
//        t1.start();
//        t2.start();
//        t3.start();
        //region 数组
//        MyArray myArray=new MyArray(4);
//        myArray.add(1);
//        myArray.add(2);
//        myArray.add(3);
//        myArray.add(4);
//        myArray.display();
//        int i=myArray.getelement(0);
//        System.out.println(i);
//        myArray.delete(4);
//        myArray.display();
//        myArray.update(3,33);
//        myArray.display();
        //endregion
        //region 冒泡
//        int[] array = {4,2,8,9,5,7,6,1,3};
//        //未排序数组顺序为
//        System.out.println("未排序数组顺序为:");
//        display(array);
//        System.out.println("-----------------------");
//        array = sort(array);
//        System.out.println("-----------------------");
//        System.out.println("经过冒泡排序后的数组顺序为:");
//        display(array);
        //endregion
        //region 选择排序
//        int[] array = {4,2,8,9,5,7,6,1,3};
//        //未排序数组顺序为
//        System.out.println("未排序数组顺序为:");
//        display(array);
//        System.out.println("-----------------------");
//        array = sort(array);
//        System.out.println("-----------------------");
//        System.out.println("经过选择排序后的数组顺序为:");
//        display(array);
        //endregion
        //region 插入排序

        //endregion

        //region 栈1
//        ArrayStack stack = new ArrayStack(3);
//        stack.push(1);
//        //System.out.println(stack.peek());
//        stack.push(2);
//        stack.push(3);
//        stack.push("abc");
//        System.out.println(stack.getTop());
//        stack.pop();
//        stack.pop();
//        stack.pop();
//        System.out.println(stack.getTop());
        //endregion

        //region 栈2
//        ArrayStack stack = new ArrayStack();
//        String str = "how are you";
//        char[] cha = str.toCharArray();
//        for(char c : cha){
//            stack.push(c);
//        }
//        while(!stack.isEmpty()){
//            System.out.print(stack.pop());
//        }
        //endregion

        //region 栈3
//        ArrayStack stack = new ArrayStack(3);
//        String str = "12<a[b{c}]>";
//        char[] cha = str.toCharArray();
//        for(char c : cha){
//            switch (c) {
//                case '{':
//                case '[':
//                case '<':
//                    stack.push(c);
//                    break;
//                case '}':
//                case ']':
//                case '>':
//                    if(!stack.isEmpty()){
//                        char ch = stack.pop().toString().toCharArray()[0];
//                        if(c=='}' && ch != '{'
//                                || c==']' && ch != '['
//                                || c==')' && ch != '('){
//                            System.out.println("Error:"+ch+"-"+c);
//                        }
//                    }
//                    break;
//                default:
//                    break;
//            }
//        }
        //endregion

        //region 队列
        MyQueue queue = new MyQueue(3);
        queue.add(1);
        queue.add(2);
        queue.add(3);//queArray数组数据为[1,2,3]

        System.out.println(queue.getFront()); //1
        queue.delete();//queArray数组数据为[null,2,3]
        System.out.println(queue.getFront()); //2

        queue.add(4);//queArray数组数据为[4,2,3]
        queue.add(5);//队列已满,queArray数组数据为[4,2,3]
        //endregion
    }

}

返回结果:

1
2
队列已满

 

双向队列:

顾名思义,就是一个两端都可以进行删除和插入操作的队列,例如,在定义的时候,我们可以定义insertRight()、insertLeft()、removeLeft()、removeRight()等方法,

如果严格禁止调用insertLeft()和removeLeft()(或禁用右端操作),那么双端队列的功能就和前面讲的栈功能一样。

  如果严格禁止调用insertLeft()和removeRight(或相反的另一对方法),那么双端队列的功能就和单向队列一样了。

 

优先级队列:

优先级队列(priority queue)是比栈和队列更专用的数据结构,在优先级队列中,数据项按照关键字进行排序,关键字最小(或者最大)的数据项往往在队列的最前面,而数据项在插入的时候都会插入到合适的位置以确保队列的有序。

我们先用数组来实现一个简单的优先级队列,这样的队列插入数据速度并不快,在数据量不大的情况下是可以的,之后我们学习了堆,用堆来实现优先级队列的插入操作效率会更高,查询时的优先级队列会根据优先权

 

我们这里先用数组实现一个简单的优先级队列,这里的优先级是值越小,优先级越高,查找和删除都是对优先级高的数据进行

 

上代码

 

package discovery;

/**
 * Author :zhanghong
 * Date   :2019-02-24 20:46.
 */
public class PriorityQue {
    private int maxsize;
    private int length;
    private int[] array;


    public PriorityQue(int s){
        maxsize=s;
        array=new int[maxsize];
        length=0;
    }
    //获取优先级最高的元素
    public int getTop(){
        return array[length-1];
    }
    //判断是否为空
    public boolean isEmpty(){
        if(length==0){
            return true;
        }
        return false;
    }
    //判断是否已满
    public boolean isFull(){
        if(length==maxsize){
            return true;
        }
        return false;
    }

    public void insert(int value){
        int j;
        if(length==0){
            array[length]=value;
            length++;
        }else {
            //数组下标
            j=length-1;
            while (j>=0&&value>array[j]){
                array[j+1]=array[j];
                j--;
            }
            array[j+1] = value;
            length++;

        }
    }

    //删除遵循先进先出原则
    public int remove(){
        int k = length -1;
        int value = array[k];
        array[k] = -1;//-1表示这个位置的数据被移除了
        length--;
        return value;
    }
}

 

 

总结:

1、栈、队列等通常是对数据访问的优化,而不是作为数据的存储

2、栈、队列每次只能访问单个对象

3、栈允许在栈顶压入数据,在栈顶弹出数据;也只能访问栈顶数据。

4、队列(单向队列)只能在队尾插入数据,对头删除数据,并且只能访问对头的数据。而且队列还可以实现循环队列,它基于数组,数组下标可以从数组末端绕回到数组的开始位置。

5、优先级队列是有序的插入数据,并且只能访问当前元素中优先级别最大(或最小)的元素。

转载于:https://www.cnblogs.com/zhhouse/p/10427710.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值