【数据结构】队列

一、介绍

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

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

二、队列的实现方法

1、队列的数组实现

1.在实例化队列时确定数组大小并初始化数组。

2.队列功能:

① 插入元素(元素在队尾入队)push(int num)

② 删除元素(在队头元素出队)pop()

③ 查看队头元素(只查看,不删除)front()

④ 判空 isEmpty()

⑤ 判满 isFull()

⑥ 查看队列长度 length()

⑦ 清空队列 clear()

3.代码实现

(1)定长数组实现

#include <iostream>
#include <string>
using namespace std;

class Myqueue
{
private:
    int head,tail;//队头指针,对尾指针
    int count;//记录队列元素数量
    int size;//队列容量(数组初始化大小)
    int* data;//数组
public:
    Myqueue(int capacity);
    ~Myqueue();
    void push(int num);
    void front();
    void pop();
    bool isEmpty();
    bool isFull();
    int length();
};

Myqueue::Myqueue(int capacity)
{
    head=0,tail=0;
    count=0;
    size=capacity;
    data=new int[capacity];
    
}

Myqueue::~Myqueue()
{
    delete []data;
}

void Myqueue::push(int num)
{
    if(isFull())
    {
        std::cout<<"error"<<std::endl;
        return;
    }
    data[tail]=num;
    tail=(tail+1)%size;
    count++;
    
}

void Myqueue::front()
{
    if(isEmpty())
    {
        std::cout<<"error"<<std::endl;
    }
    else
    {
        std::cout<<data[head]<<std::endl;
    }
    
}

void Myqueue::pop()
{
    if(isEmpty())
    {
        std::cout<<"error"<<std::endl;
    }
    else
    {
        std::cout<<data[head]<<std::endl;
        head=(head+1)%size;
        count--;
    }
}

bool Myqueue::isEmpty()
{
   return count==0;
}

bool Myqueue::isFull()
{
    return count==size;
}

bool Myqueue::length()
{
    return count;
}

void Myqueue::clear()
{
    while(head!=tail)
    {
        pop();
    }
}

(2)环形数组实现

#include <iostream>
#include <vector>
using namespace std;

/* 基于环形数组实现的队列 */
class ArrayQueue {
public:
    ArrayQueue(int capacity);
    ~ArrayQueue();
    int capacity();//获取队列容量
    int size();//获取队列长度
    bool isEmpty();  //队列判空
    void push(int num);//元素入队
    int peek();     //返回队首元素
    int pop();      //元素出队
    vector<int> toVector();

private:
    int* nums;       // 用于存储队列元素的数组
    int front;       // 队首指针,指向队首元素
    int queSize;     // 队列长度
    int queCapacity; // 队列容量

};

ArrayQueue::ArrayQueue(int capacity):queCapacity(capacity),queSize(0),front(0),nums(new int[capacity])
{
}

ArrayQueue::~ArrayQueue()
{
    delete[] nums;
}

/* 获取队列的容量 */
int ArrayQueue::capacity()
{
    return queCapacity;
}

/* 获取队列的长度 */
int ArrayQueue::size()
{
    return queSize;
}

/* 判断队列是否为空 */
bool ArrayQueue::isEmpty()
{
    return queSize == 0;
}

/* 入队 */
void ArrayQueue::push(int num)
{
    if (queSize == queCapacity)
    {
        std::cout << "队列已满" << std::endl;
        return;
    }
    //计算队尾指针,指向队尾索引+1
    //这是一个环形数组,通过取余操作实现rear越过数组尾部后回到头部
    int rear = (front + queSize) % queCapacity;
    
    nums[rear] = num;
    queSize++;

}

/* 访问队首元素 */
int ArrayQueue::peek()
{
    if (isEmpty())
    {
        throw out_of_range("队列为空");
    }
    return nums[front];
}

/* 出队 */
int ArrayQueue::pop()
{
    int num = peek();
    //队首指针向后移动一位,若越过尾部,则返回到数组头部
    front = (front + 1) % queCapacity;
    --queSize;
    return num;
}

/* 将数组转化为 Vector 并返回 */
vector<int> ArrayQueue::toVector()
{
    vector<int> arr(queSize);
    //仅转换有效长度范围内的列表元素
    for (int i = 0, j = front; i < queSize; i++, j++)
    {
        arr[i] = nums[j % queCapacity];
    }
    return arr;
}

2、队列的链表实现

#include <iostream>
#include <vector>
using namespace std;

/* 链表节点结构体 */
struct ListNode
{
	int val;
	ListNode* next;
	ListNode(int x) : val(x), next(nullptr) {}  // 构造函数
};

class LinkedListQueue {
private:
    ListNode* front, *rear; // 头节点 front ,尾节点 rear
    int queSize;
public:
	LinkedListQueue();
	~LinkedListQueue();
	int size();			//获取队列长度
	bool isEmpty();		//判断队列是否为空
	void push(int num);	//入队
	int pop();			//出队
	int peek();			//访问队首元素
	vector<int> toVector(); //链表转换为vector
};

LinkedListQueue::LinkedListQueue():front(nullptr),rear(nullptr),queSize(0)
{

}


LinkedListQueue::~LinkedListQueue()
{
	// 遍历链表删除节点,释放内存
	while (front != nullptr)
	{
		ListNode* tmp = front;
		front = front->next;
		delete tmp;
	}
}

int LinkedListQueue::size()
{
	return queSize;
}

bool LinkedListQueue::isEmpty()
{
	return size() == 0;
}

/*尾插法*/
void LinkedListQueue::push(int num)
{
	ListNode* node = new ListNode(num);
	//如果队列为空,则令头、尾节点都指向该节点
	if (front == nullptr)
	{
		front = node;
		rear = node;
	}
	else//队列不为空,则将该节点添加到尾节点后
	{
		rear->next = node;
		rear = node;
	}
	++queSize;
}

int LinkedListQueue::peek()
{
	if (size() == 0)
	{
		throw out_of_range("队列为空");
	}	
	return front->val;
}

//队头出队
int LinkedListQueue::pop()
{
	//获取队首元素
	int num = peek();
	ListNode* tmp = front;
	front = front->next;
	//释放内存
	delete tmp;
	--queSize;

	return num;
}

vector<int> LinkedListQueue::toVector()
{
	vector<int> nums;
	ListNode* node = front;
	while (node != nullptr)
	{
		nums.push_back(node->val);
		node = node->next;
	}
	return nums;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值