欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数据结构与算法_03队列

程序员文章站 2024-03-18 11:38:10
...

队列

0、章节重点整理

  • 队列和堆栈都是有序表,抽象型数据类型,所有的加入删除都在不同的两端,符合FIFO特性
  • 何为多重队列?定义及目的
    双向队列就是一种二重队列。只是队列的首端可在队列的左右两端。多重队列的原则是只要遵循数据的插入在rear 端,删除在front 端的原则,并将多重堆栈的T(i) 改成rear(i)、B(i) 改成front(i)即可。多重队列也可以改成多重环形队列。主要目的是让数组的有效使用率提高,因为数组的大小必须事先声明。
  • 何为优先队列
    是一种不必遵守队列特性FIFO 的有序表,其中每一个元素都赋予了优先权,加入元素时可任意加入。但是拥有最高优先权的数据优先输出。

1、认识队列

1.1、 队列的工作运算

  • 先进先出
  • 两种基本操作,加入和删除,使用front 和rear 两个指针来分别指向队列的前端和尾端

1.2、队列的数组实现

//默认front 从-1开始,数组的索引是0开始。
    public static int front = -1,rear = -1,max = 20;
    public static int val;
    public static char ch;
    public static int queue[] = new int[max];//创建容量20的数组
    public static void main(String args[]) throws IOException {
        String strM;
        int M=0;
        BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
        while(rear < max-1 && M != 3)
        {
            System.out.print("[1]存入一个数值[2]取出一个数值[3]结束: ");
            strM=keyin.readLine();
            M=Integer.parseInt(strM);
            switch(M)
            {
                case 1:
                    System.out.print("\n[请输入数值]: ");
                    strM=keyin.readLine();
                    val=Integer.parseInt(strM);
                    rear++;
                    queue[rear]=val;
                    break;
                case 2:
                    if(rear>front)
                    {
                        front++;
                        System.out.print("\n[取出数值为]: ["+queue[front]+"]"+"\n");
                        queue[front]=0;
                    }
                    else
                    {
                        System.out.print("\n[队列已经空了]\n");
                        break;
                    }
                    break;
                default:
                    System.out.print("\n");
                    break;
            }
        }
        if(rear == max-1) System.out.print("队列已经满了]\n");
        System.out.print("\n[目前队列中的数据]:");
        if (front >= rear) {
            System.out.print("没有\n");
            System.out.print("[队列已经空了]\n");
        }
        else {
            while (rear > front) {
                front++;
                System.out.print("["+queue[front]+"]");
            }
            System.out.print("\n");
        }
    }

1.3、队列的链表实现

class QueueNode {
    // 队列节点类
    int data;                    // 节点数据
    QueueNode next;              // 指向下一个节点
    //构造函数
   public QueueNode(int data){
        this.data = data;
        next = null;
    }
}

class Linked_List_Queue {//队列类
    public QueueNode front; //队列的前端指针
    public QueueNode rear;  //队列的尾端指针

    //构造函数
    public Linked_List_Queue() { front=null; rear=null; }

    //方法enqueue:队列数据的存入
    public boolean enqueue(int value) {
        QueueNode node= new QueueNode(value); //建立节点
        //检查是否为空队列
        if (rear==null)
            front=node; //新建立的节点成为第一个节点
        else
            rear.next=node; //将节点加入到队列的尾端
        rear=node; //将队列的尾端指针指向新加入的节点
        return true;
    }

    //方法dequeue:队列数据的取出
    public int dequeue() {
        int value;
        //检查队列是否为空队列
        if (!(front==null)) {
            if(front==rear) rear=null;
            value=front.data; //将队列数据取出
            front=front.next; //将队列的前端指针指向下一个
            return value;
        }
        else return -1;
    }
} //队列类声明结束

public class  Test02{
    // 主程序
    public static void main(String args[]) throws IOException {
        Linked_List_Queue queue =new Linked_List_Queue(); //建立队列对象
        int temp;
        System.out.println("以链表来实现队列");
        System.out.println("====================================");
        System.out.println("在队列前端加入第1个数据,此数据值为1");
        queue.enqueue(1);
        System.out.println("在队列前端加入第2个数据,此数据值为3");
        queue.enqueue(3);
        System.out.println("在队列前端加入第3个数据,此数据值为5");
        queue.enqueue(5);
        System.out.println("在队列前端加入第4个数据,此数据值为7");
        queue.enqueue(7);
        System.out.println("在队列前端加入第5个数据,此数据值为9");
        queue.enqueue(9);
        System.out.println("====================================");
        while (true) {
            if (!(queue.front==null)) {
                temp=queue.dequeue();
                System.out.println("从队列前端依序取出的元素数据值为:"+temp);
            }
            else
                break;
        }
        System.out.println();
    }
}

2、队列的应用

  • 图形遍历的先广后深搜索法BFS,就是利用队列
  • 计算机的模拟;模拟过程由于各种事件的输入时间不一定,利用队列反映真实情况
  • CPU工作调度利用队列处理,可以达到先到先做的要求

2.1、环形队列

  • 是一种环形结构的队列,是Q(0:n-1)的一维数组,同时Q(0) 也是Q(n-1)的下一个元素
  • 指针front 永远以逆时针方向指向队列中第一个元素的前一个位置,rear 则指向队列当前的最后位置。一开始二者都设置为-1,表示空队列,当front = rear则为空队列。
public static int front = -1,rear = -1,val;
    public static int queue[] = new int[5];
    public static void main(String args[]) throws IOException

    {
        String strM;
        BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
        while(rear < 5 && val != -1)
        {
            System.out.print("请输入一个值以存入队列,要取出值请输入0。(结束输入-1):");
            strM = keyin.readLine();
            val = Integer.parseInt(strM);
            if(val == 0)
            {
                if(front==rear)
                {
                    System.out.print("[队列已经空了]\n");
                    break;
                }
                front++;
                if (front == 5)
                    front = 0;
                System.out.print("取出队列值["+queue[front]+"]\n");
                queue[front] = 0;
            }
            else if(val != -1 && rear < 5)
            {
                if(rear+1 == front||rear == 4&&front <= 0)
                {
                    System.out.print("[队列已经满了]\n");
                    break;
                }
                rear++;
                if(rear == 5)
                    rear = 0;
                queue[rear] = val;
            }
        }
        System.out.print("\n队列剩余数据:\n");
        if (front == rear)
            System.out.print("队列已空!!\n");
        else
        {
            while(front != rear)
            {
                front++;
                if (front == 5)
                    front = 0;
                System.out.print("["+queue[front]+"]");
                queue[front] = 0;
            }
        }
        System.out.print("\n");

    }

2.2、双向队列

class QueueNode {              // 队列节点类
    int data;                    // 节点数据
    QueueNode next;              // 指向下一个节点

    //构造函数
    public QueueNode(int data) {
        this.data = data;
        next = null;
    }
}

public class Linked_List_Queue { //队列类
    public QueueNode front; //队列的前端指针
    public QueueNode rear;  //队列的尾端指针

    //构造函数
    public Linked_List_Queue() {
        front = null;
        rear = null;
    }

    //方法enqueue:队列数据的存入
    public boolean enqueue(int value) {
        QueueNode node = new QueueNode(value); //建立节点
        //检查是否为空队列
        if (rear == null)
            front = node; //新建立的节点成为第一个节点
        else
            rear.next = node; //将节点加入到队列的尾端
        rear = node; //将队列的尾端指针指向新加入的节点
        return true;
    }

    //方法dequeue:队列数据的取出
    public int dequeue(int action) {
        int value;
        QueueNode tempNode, startNode;
        //从前端取出数据
        if (!(front == null) && action == 1) {
            if (front == rear) rear = null;
            value = front.data; //将队列数据从前端取出
            front = front.next; //将队列的前端指针指向下一个
            return value;
        }
        //从尾端取出数据
        else if (!(rear == null) && action == 2) {
            startNode = front;  //先记下前端的指针值
            value = rear.data;  //取出目前尾端的数据
            //找寻最尾端节点的前一个节点
            tempNode = front;
            while (front.next != rear && front.next != null) {
                front = front.next;
                tempNode = front;
            }
            front = startNode;  //记录从尾端取出数据后的队列前端指针
            rear = tempNode;    //记录从尾端取出数据后的队列尾端指针
            //下一行程序是指当队列中仅剩下最后节点时,取出数据后便将front及rear指向null
            if ((front.next == null) || (rear.next == null)) {
                front = null;
                rear = null;
            }
            return value;
        } else return -1;
    }
} //队列类声明结束

public class DoublyQueue {
    // 主程序
    public static void main(String args[]) throws IOException {
        Linked_List_Queue queue =new Linked_List_Queue(); //建立队列对象
        int temp;
        System.out.println("以链表来实现双向队列");
        System.out.println("====================================");
        System.out.println("在双向队列前端加入第1个数据,此数据值为1");
        queue.enqueue(1);
        System.out.println("在双向队列前端加入第2个数据,此数据值为3");
        queue.enqueue(3);
        System.out.println("在双向队列前端加入第3个数据,此数据值为5");
        queue.enqueue(5);
        System.out.println("在双向队列前端加入第4个数据,此数据值为7");
        queue.enqueue(7);
        System.out.println("在双向队列前端加入第5个数据,此数据值为9");
        queue.enqueue(9);
        System.out.println("====================================");
        temp=queue.dequeue(1);
        System.out.println("从双向队列前端依序取出的元素数据值为:"+temp);
        temp=queue.dequeue(2);
        System.out.println("从双向队列尾端依序取出的元素数据值为:"+temp);
        temp=queue.dequeue(1);
        System.out.println("从双向队列前端依序取出的元素数据值为:"+temp);
        temp=queue.dequeue(2);
        System.out.println("从双向队列尾端依序取出的元素数据值为:"+temp);
        temp=queue.dequeue(1);
        System.out.println("从双向队列前端依序取出的元素数据值为:"+temp);
        System.out.println();
    }
}