Day11-队列的链表实现(C/Java)

队列

概念解释

队列(Queue)是一种常见的数据结构,它按照先进先出(FIFO)的原则存储元素。队列有两个主要操作,即入队(enqueue)和出队(dequeue)。入队操作将一个元素添加到队列的末尾,而出队操作则从队列的前端移除并返回队列中的第一个元素。

队列可以比喻成排队等待服务的人群,新来的人加入队尾,而被服务结束的人从队头离开。这种结构在很多实际场景中都有应用,比如计算机执行任务的排队调度、网络数据传输的缓存控制等。

常见的操作

image-20230922165210670

循环队列(链表实现)

  • 队列顺序存储的假溢出问题

队列也可以进行顺序存储,但这会造成队列假溢出的现象:

队列的假溢出(False Overflow)是一种特殊情况,在队列的实现中可能会出现。它发生在队列的尾端被占满时,仍有空闲位置在队列的头部。通常,队列有一个固定的容量,当队列元素达到容量上限时,继续执行入队操作会导致溢出。然而,在某些情况下,由于队列元素的出队操作,队列的头部会出现空闲位置,这意味着队列尾部实际上没有满员。假溢出的原因可能是由于队列的容量的设置不合理,导致队列尾部实际上不能填满。例如,如果队列的容量设置为10个元素,但在某个时刻只有5个元素在队列中,那么队列的尾部会被占满,而队列的头部却有5个空闲位置。

假溢出可能会导致资源浪费或性能下降。在实际应用中,如果没有及时处理假溢出,可能会造成空间的浪费,而且后续的入队操作可能会因为错误的认为队列已满而被拒绝。所以解决假溢出的办法就是后面满了,就再从头开始,也就是头尾相接的循环。

  • 循环队列

image-20230922175116268

image-20230922202308673

链表实现

  • Java代码实现

方法接口

public interface Queue<E> {
    /**
     * 向队列尾插入值
     * @param value-待插入值
     * @return 插入成功返回true,插入失败返回false
     */
    boolean offer(E value);

    /**
     * 从队列头获取值,并移除
     * @return 如果队列非空返回对头值,否则返回null
     */
    E poll();

    /**
     * 从对头获取值,但不移除
     * @return 如果队列非空返回对头值,否则返回null
     */
    E peek();

    /**
     * 检查队列是否为空
     * @return 空返回true,否则返回false
     */
    boolean isEmpty();

    /**
     * 检验队列是否已满
     * @return 满返回true,否则返回false
     */
    boolean isFull();

}

代码实现

/**
 * 用链表实现队列:单项环形带哨兵的链表
 */
public class LinkedListQueue<E> implements Queue<E>, Iterable<E> {
    //1.创建内部节点类
    private static class Node<E>{
        E value;
        Node<E> next;
        public Node(E value, Node<E> next) {
            this.value = value;
            this.next = next;
        }
    }
    //2.创建LinkedListQueue中的属性
    //头指针:指向哨兵节点,即队头
    private Node<E> head = new Node<>(null, null);
    //尾指针:指向链表最后一个节点,即队尾
    private Node<E> tail = head;
    //队列大小:表示目前队列存储元素的多少
    private int size = 0;
    //队列的容量:表示队列所能容纳的最大数量
    private int capacity = Integer.MAX_VALUE;
    //构造方法:将队尾指向对头,实现循环
    public LinkedListQueue() {
        tail.next = head;
    }
    public LinkedListQueue(int capacity) {
        this.capacity = capacity;
        tail.next = head;
    }

    @Override
    public boolean offer(E value) {
        //判断队列是否已满
        if (isFull()) return false;
        //向队列添加元素
        Node<E> addElem = new Node<>(value, head);
        tail.next = addElem;
        tail = addElem;
        size++;
        return true;
    }

    @Override
    public E poll() {

        if (isEmpty()) return null;
        //当队列只有一个节点,将tail指向head
        if (tail == head.next) tail = head;
        //进行删除操作
        E removed = head.next.value;
        head.next = head.next.next;
        size--;
        return removed;
    }

    @Override
    public E peek() {
        //如果队列为空,返回null
        if (isEmpty()) return null;
        return head.next.value;
    }

    @Override
    public boolean isEmpty() {
        return head == tail;
    }

    @Override
    public boolean isFull() {
        return size == capacity;
    }

    @Override
    public Iterator<E> iterator() {
        return new Iterator<E>() {
            Node<E> p = head.next;
            @Override
            public boolean hasNext() {
                return p != head;
            }
            @Override
            public E next() {
                E value = p.value;
                p = p.next;
                return value;
            }
        };
    }
}
  • C代码实现
#include <stdio.h>
#include <stdlib.h>

//节点类的创建
typedef struct Node{
	int value;
	Node *next;
}Node; 

//创建队列
typedef struct Queue{
	//头指针:指向哨兵节点,即队头
	Node *head;
	//尾指针:指向链表最后一个节点,即队尾
	Node *tail;
	//队列的容量:表示队列所能容纳的最大数量
	int capacity;
	//目前队列的容量 
	int size;
}Queue; 

//函数方法声明——————————-————— 
Queue* initQueue(int capacity); 
bool isEmpty(Queue *queue);
bool isFull(Queue *queue);
bool offer(Queue *queue, int value);
int poll(Queue *queue);
int peek(Queue *queue);
//—————————————————————— 
int main(){
 	Queue *queue = initQueue(5);
    offer(queue, 1);
    offer(queue, 2);
    offer(queue, 3);
    printf("Front element: %d\n", peek(queue)); // 应输出1
    printf("Popped element: %d\n", poll(queue)); // 应输出1
    printf("Front element: %d\n", peek(queue)); // 应输出2
    return 0;
}

/*初始化队列*/
Queue* initQueue(int capacity){
	Queue* queue = (Queue*)malloc(sizeof(Queue));
    queue->capacity = capacity;
    queue->size = 0;
    Node* sentinel = (Node*)malloc(sizeof(Node));
    sentinel->value = -1; // 设置哨兵节点的值为特定值
    sentinel->next = sentinel; // 哨兵节点的next指针指向自身
    queue->head = sentinel;
    queue->tail = sentinel;
    return queue;
}

/*判断队列是否为空*/
bool isEmpty(Queue *queue){
	return queue->head == queue->tail;
}

/*判断队列是否为满*/
bool isFull(Queue *queue){
	return queue->size == queue->capacity;
}

/*入队操作*/
bool offer(Queue *queue, int value){
	if(isFull(queue)) return false;
	//创建一个新节点 
	Node *added = (Node *)malloc(sizeof(Node));
	added->value = value;
	added->next = queue->head; 
	//对节点指针的操作
	queue->tail->next = added;
	queue->tail = added;
	queue->size++;
	return true; 
}

/*出队操作*/
int poll(Queue *queue){
	if(isEmpty(queue)) return -1;
	if(queue->head->next == queue->tail) queue->tail = queue->head;
	//删除操作
	Node* removed = queue->head->next;
	int val = removed->value;
	queue->head->next = removed->next;
	free(removed);
	queue->size--;
	return val; 
}

/*从对头获取值,但不移除*/
int peek(Queue *queue){
	if(isEmpty(queue)) return -1;
	return queue->head->next->value;
} 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值