当前位置: 代码网 > it编程>前端脚本>Python > 【数据结构】队列

【数据结构】队列

2024年07月31日 Python 我要评论
队列的解析,队列的顺序实现(循环队列),队列的链式实现


队列

队列是只允许在一端进行插入操作,而在另一端进行删除操作的线性表,一种先进先出的数据结构。
队尾:允许插入的一端。
队头:允许删除的一端。

队列的模拟实现

队列的底层可以是顺序表,可以是链表实现。

队列的链式实现

在实现队列前我们先思考使用什么样的链表来实现?
由于栈的特性是先入先出,如果使用单链表和双向链表都可以,
只要在单链表标记一下尾节点就行,
但是因为java提供的是双向链表实现的,所以我们使用双向链表。

接口实现

实现的接口如下:

public class myqueue {
	//入队列
    public void offer(int val) {}
	//出队列
    public int poll() {}
    //获取队头元素 但是不删除
    public int peek() { }
    //判空
    public boolean isempty() { } 
    //获取队列元素个数
    public int size(){}      
}

内部类

跟双向链表的内部类实现差不多。

static class listnode{
        public int val;
        public listnode prev;
        public listnode next;

        public listnode(int val) {
            this.val = val;
        }
    }
    public listnode head;
    public listnode last;

入队列

实现思路:

  1. 先看队列是否为空,为空,头尾指向入队节点。
  2. 不为空尾节点的后继next指向入队节点,入队节点前驱prev指向尾节点,尾节点变为入队节点。
public void offer(int val){
	listnode cur = new listnode(val);
	if(isempty()){
		head = last = cur;
		return;
	}
	last.next = newnode;
    newnode.prev = last;
    last = newnode;
}

出队列

实现思路:

  1. 先判断队列是否为空,队列为空抛异常。
  2. 队列不为空,将头节点记录下来,头节点后一个节点前驱prev置为空,头节点变为后一个节点。
public int poll() throws nullpointerexception{
	try{
		if(isempty()){
			throw new nullpointerexception;
		}
	}catch(nullpointerexception e){
		 e.printstacktrace();
	}
	listnode cur = head;
	head.next.prev = null;
	head = head.next;
	return cur.val;
}

获取队头元素 但是不删除

实现思路:

  1. 先判断队列是否为空,队列为空抛异常。
  2. 队列不为空,返回头节点。
 public int peek() throws nullpointerexception{
	try{
		if(isempty()){
			throw new nullpointerexception;
		}
	}catch(nullpointerexception e){
		 e.printstacktrace();
	}
	return head.val;
}

判空

直接返回头是否为空就行。

public boolean isempty(){
	return head == null;
}

获取队列元素个数

直接循环遍历即可。

    public int size(){
    	listnode cur = head;
    	int size = 0;
		while(cur != null){
			cur = cur.next;
			size++;
		}
		return size;
	} 

队列的顺序实现(循环队列)

直接使用顺序表的缺陷

当我们直接使用顺序表来放数据时,我们将元素入队列放在数组尾,出队列时将数组前面元素出去后,会使前面浪费的空间越来越大。
基于此我们就用循环队列来实现,还是数组作为底层,但我们将其想象成一个圆。
循环队列

接口实现

class mycircularqueue {
	//构造器,设置队列长度为 k
    public mycircularqueue(int k) {}
    // 向循环队列插入一个元素。如果成功插入则返回真。
    public boolean enqueue(int value) {}
    //从循环队列中删除一个元素。如果成功删除则返回真。
    public boolean dequeue() {}
    //从队首获取元素。如果队列为空,返回 -1 
    public int front() {}
    //获取队尾元素。如果队列为空,返回 -1 。
    public int rear() {}
    //检查循环队列是否为空。
    public boolean isempty() {}
    //检查循环队列是否已满。
    public boolean isfull() {}
};

成员变量

数组arr ,头下标front,尾节点下一个下标rear,数组长度size。

private int []arr;
private int front;
private int rear;
private int size;

构造器,设置队列长度为 k

因为我们使用的判空方法(下文讲)会造成一个空间的浪费,所以多申请一个空间。

public mycircularqueue(int k) {
        size = k+1;
        arr = new int[size];
        front = rear = 0;
    }

向循环队列插入一个元素 成功插入则返回真

实现思路:

  1. 判断队列是否已满,满了就返回false。
  2. 不满就在rear放。
  3. 因为是循环队列,所以rear的赋值要使用取余。
public boolean enqueue(int value) {
        if(isfull()){
            return false;
        }else{
            arr[rear] = value;
            rear = (rear + 1) % size;
            return true;
        }
    }

从循环队列中删除一个元素 成功删除则返回真

实现思路:

  1. 判断队列是否为空,空就返回false。
  2. 不空就直接将front指向下一个位置。
  3. 因为是循环队列,所以front的赋值要使用取余。
public boolean dequeue() {
        if(isempty()){
            return false;
        }else{
            front = (front + 1) % size;
            return true;
        }
    }

从队首获取元素。如果队列为空,返回 -1

实现思路:

  1. 先判断队列是否为空,为空返回-1。
  2. 不为空,返回front下标对应值。
public int front() {
        if(isempty()){
            return -1;
        }else{
            return arr[front];
        }
    }

获取队尾元素。如果队列为空,返回 -1

实现思路:

  1. 先判断队列是否为空,为空返回-1。
  2. 不为空,再判断rear是否为0,是0就返回数组最后一个元素。
  3. 不为0,就直接返回rear-1下标对应的元素。
public int rear() {
         if(isempty()){
            return -1;
        }else{
            if(rear == 0){
                return arr[size - 1];
            }else{
                return arr[rear - 1];
            }                    
        }
    }

检查循环队列是否为空

检查空根据循环队列的实现有两种方法:

  1. 使用usedsize记录队列元素个数,个数为0就是空。
  2. 空一个空间,如果front和rear相等那就是空。
public boolean isempty() {
        return rear == front;
    }

检查循环队列是否已满

检查满根据循环队列的实现有两种方法:

  1. 使用usedsize记录队列元素个数,个数和size相等就是满。
  2. 空一个空间,如果rear的下一个位置就是front那就是满。
public boolean isfull() {
        return front == (rear+1) % size;
    }

java中的queue

java中queue的底层是linkedlist实现的。
并且queue只是一个接口,必须new对象linkedlist才能使用。

实现的接口

实现的接口如下:
接口

常用方法

常用方法如下:
常用方法

队列练习

用队列实现栈

用栈实现队列

设计循环队列

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com