【队列的理解及Java实现】

1. 队列的基本概念

队列是一种先进先出的线性数据结构。你可以把它想象成排队买票,最先排队的人最先买到票并离开队列。它主要有两个操作端:队首和队尾。元素从队尾添加,从队首移除。

2. 队列的基本操作

  • 入队(enqueue):在队列的末尾添加一个元素。
  • 出队(dequeue):从队列的开头移除一个元素。
  • 查看队首(peek):查看队列的第一个元素。
  • 检查队列是否为空(isEmpty):判断队列是否没有元素。

3. 队列的Java实现

在Java中,我们可以使用链表来实现队列。下面是一个简单的队列实现:

import java.util.LinkedList;

public class MyQueue {
    private LinkedList<Integer> list;

    public MyQueue() {
        list = new LinkedList<>();
    }

    // 入队操作
    public void enqueue(int data) {
        list.addLast(data);
    }

    // 出队操作
    public int dequeue() {
        if (isEmpty()) {
            System.out.println("Queue is empty, unable to dequeue.");
            return -1; // 返回-1作为错误提示
        }
        return list.removeFirst();
    }

    // 查看队首元素
    public int peek() {
        if (isEmpty()) {
            System.out.println("Queue is empty, no elements to peek.");
            return -1; // 返回-1作为错误提示
        }
        return list.getFirst();
    }

    // 检查队列是否为空
    public boolean isEmpty() {
        return list.isEmpty();
    }
}

4. 使用队列

下面是如何使用这个队列类来执行基本操作的例子:

public class QueueDemo {
    public static void main(String[] args) {
        MyQueue queue = new MyQueue();
        
        // 入队操作
        queue.enqueue(10);
        queue.enqueue(20);
        queue.enqueue(30);
        
        // 查看队首元素
        System.out.println("队首元素: " + queue.peek());  // 输出队首元素: 10
        
        // 出队操作并打印
        System.out.println("出队元素: " + queue.dequeue());  // 输出出队元素: 10
        System.out.println("出队元素: " + queue.dequeue());  // 输出出队元素: 20
        
        // 继续操作
        queue.enqueue(40);
        System.out.println("出队元素: " + queue.dequeue());  // 输出出队元素: 30
        System.out.println("出队元素: " + queue.dequeue());  // 输出出队元素: 40
        
        // 检查队列是否为空
        System.out.println("队列是否为空: " + queue.isEmpty());  // 输出队列是否为空: true
    }
}

5.基本操作

如果你想要将队列中的一个值赋给另一个变量,但不希望从队列中移除这个值,你应该使用 peek() 方法。这个方法会返回队列头部的元素,但不会从队列中移除这个元素。

以下是如何实现的示例:

import java.util.LinkedList;
import java.util.Queue;

public class Example {
    public static void main(String[] args) {
        // 创建一个队列并添加元素
        Queue<Integer> queue = new LinkedList<>();
        queue.add(10);
        queue.add(20);
        queue.add(30);

        // 使用peek()方法获取队列头部的元素但不移除它
        Integer topElement = queue.peek();

        // 输出赋值后的变量
        System.out.println("队列头部的元素赋给变量: " + topElement);
        
        // 输出队列确保队列头部元素未被移除
        System.out.println("队列的当前状态: " + queue);
    }
}

输出

队列头部的元素赋给变量: 10
队列的当前状态: [10, 20, 30]

注意

  • 使用 peek() 方法时,如果队列为空,则该方法返回 null
  • 如果你想要从队列中移除并获取元素,则应使用 poll() 方法。poll() 方法在移除并返回队列的头部元素后,队列的状态将更新。
    在实际应用中,选择 peek()poll() 取决于你是否需要从队列中移除元素。

要计算队列中所有数的和,你可以遍历队列并累加每个元素的值。在Java中,可以使用增强型for循环或者迭代器来遍历队列。以下是使用增强型for循环计算队列中所有数之和的示例:

import java.util.LinkedList;
import java.util.Queue;

public class Example {
    public static void main(String[] args) {
        // 创建一个队列并添加元素
        Queue<Integer> queue = new LinkedList<>();
        queue.add(10);
        queue.add(20);
        queue.add(30);

        // 计算队列中所有数之和
        int sum = 0;
        for (int num : queue) {
            sum += num;
        }

        // 输出总和
        System.out.println("队列中所有数之和: " + sum);
    }
}

输出

队列中所有数之和: 60

另一种方法:使用迭代器

如果你更倾向于使用迭代器,这里也提供了一个示例代码:

import java.util.LinkedList;
import java.util.Queue;
import java.util.Iterator;

public class Example {
    public static void main(String[] args) {
        // 创建一个队列并添加元素
        Queue<Integer> queue = new LinkedList<>();
        queue.add(10);
        queue.add(20);
        queue.add(30);

        // 使用迭代器计算队列中所有数之和
        int sum = 0;
        Iterator<Integer> iterator = queue.iterator();
        while (iterator.hasNext()) {
            sum += iterator.next();
        }

        // 输出总和
        System.out.println("队列中所有数之和: " + sum);
    }
}

这两种方法都能达到相同的目的,你可以根据自己的偏好选择使用。

要让队列中的元素从大到小排列,你需要将队列中的元素排序。由于Queue接口在Java中没有直接提供排序功能,你通常需要将队列元素转移到一个可以排序的中间数据结构中,比如ArrayList或者数组,使用这些数据结构提供的排序函数,然后再将排序后的元素重新放回队列。

以下是使用ArrayList来对队列元素进行排序的示例:

import java.util.LinkedList;
import java.util.Queue;
import java.util.ArrayList;
import java.util.Collections;

public class Example {
    public static void main(String[] args) {
        // 创建一个队列并添加元素
        Queue<Integer> queue = new LinkedList<>();
        queue.add(10);
        queue.add(20);
        queue.add(30);

        // 将队列元素转移到ArrayList中
        ArrayList<Integer> list = new ArrayList<>(queue);

        // 对ArrayList中的元素进行排序,然后反转以满足从大到小的要求
        Collections.sort(list);
        Collections.reverse(list);

        // 清空原队列
        queue.clear();

        // 将排序后的元素重新放回队列
        queue.addAll(list);

        // 输出排序后的队列
        System.out.println("从大到小排序后的队列: " + queue);
    }
}

输出

从大到小排序后的队列: [30, 20, 10]

注意

  • 这种方法会改变原队列的元素顺序。如果你不想改变原队列,可以先克隆原队列,然后对克隆进行操作。
  • 对于大数据集,这种排序方法可能不是最高效的,因为它涉及到多次数据结构之间的转换。如果性能是关键考虑因素,可能需要考虑使用更适合大量数据排序的算法或数据结构。
  • Collections.sort() 默认按照升序排序,所以在排序后需要使用Collections.reverse()来反转列表,以达到从大到小的顺序。

6.优先队列

优先队列学习笔记

1. 什么是优先队列?

优先队列(Priority Queue)是一种特殊的队列,其中每个元素都有一个优先级。优先级最高的元素总是位于队列的前端,并且每次出队操作都会移除优先级最高的元素。

2. 优先队列的特点
  • 优先级:元素按照优先级排序,而不是按照入队的顺序。
  • 出队顺序:总是优先级最高的元素先出队。
  • 实现方式:通常使用堆(Heap)数据结构来实现。
3. 优先队列的应用场景
  • 任务调度:操作系统中的任务调度,优先级高的任务先执行。
  • 数据压缩:如Huffman编码。
4. Java中的优先队列

Java中提供了PriorityQueue类,位于java.util包中。PriorityQueue默认是一个最小堆(即优先级最小的元素在队列前端),但可以通过提供自定义的比较器(Comparator)来实现最大堆。

5. 代码示例

以下是一个简单的Java代码示例,展示了如何使用PriorityQueue

import java.util.PriorityQueue;
import java.util.Comparator;

public class PriorityQueueExample {
    public static void main(String[] args) {
        // 默认是最小堆
        PriorityQueue<Integer> minHeap = new PriorityQueue<>();

        // 添加元素
        minHeap.add(10);
        minHeap.add(30);
        minHeap.add(20);
        minHeap.add(5);

        // 输出元素(注意:这里不会按优先级顺序输出)
        System.out.println("Min Heap elements (not sorted): " + minHeap);

        // 出队操作
        System.out.println("Dequeue elements from Min Heap:");
        while (!minHeap.isEmpty()) {
            System.out.println(minHeap.poll());
        }

        // 创建一个最大堆
        PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Comparator.reverseOrder());

        // 添加元素
        maxHeap.add(10);
        maxHeap.add(30);
        maxHeap.add(20);
        maxHeap.add(5);

        // 输出元素(注意:这里不会按优先级顺序输出)
        System.out.println("Max Heap elements (not sorted): " + maxHeap);

        // 出队操作
        System.out.println("Dequeue elements from Max Heap:");
        while (!maxHeap.isEmpty()) {
            System.out.println(maxHeap.poll());
        }
    }
}
6. 自定义比较器

如果你需要根据自定义的规则来确定优先级,可以实现一个Comparator接口。

import java.util.PriorityQueue;
import java.util.Comparator;

class Task {
    String name;
    int priority;

    Task(String name, int priority) {
        this.name = name;
        this.priority = priority;
    }

    @Override
    public String toString() {
        return name + " (" + priority + ")";
    }
}

public class CustomPriorityQueueExample {
    public static void main(String[] args) {
        // 自定义比较器
        Comparator<Task> taskComparator = new Comparator<Task>() {
            @Override
            public int compare(Task t1, Task t2) {
                return t2.priority - t1.priority; // 优先级高的在前
            }
        };

        PriorityQueue<Task> taskQueue = new PriorityQueue<>(taskComparator);

        // 添加任务
        taskQueue.add(new Task("Task 1", 3));
        taskQueue.add(new Task("Task 2", 1));
        taskQueue.add(new Task("Task 3", 2));

        // 出队操作
        System.out.println("Dequeue tasks:");
        while (!taskQueue.isEmpty()) {
            System.out.println(taskQueue.poll());
        }
    }
}

7. 总结

队列是一个非常实用的数据结构,适用于多种需要按照元素进入顺序处理数据的场景。了解队列的基本操作和实现可以帮助你更好地理解数据结构的应用,为解决更复杂的问题打下基础。在Java中实现队列的方法很多,这里我们使用了简单直观的LinkedList来完成我们的队列。优先队列是一种非常有用的数据结构,适用于需要按照优先级处理元素的场景。Java中的PriorityQueue类提供了方便的接口来实现优先队列,并且可以通过自定义比较器来灵活地控制元素的优先级。。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值