循环队列
基于链式储存结构的队列优点和链式线性表一样,不需要依靠多次移动数组元素来保持数据结构的稳定性,但是缺点也很明显,就是每添加一个元素就需要申请一次内存。而基于顺序储存结构的队列可以预先申请一块内存,每添加一个元素时只需要把节点放在数组的末尾就可以了,但取队首元素时就比较复杂了,需要把从第二个元素开始,都向前移动一位。
循环队列可以在保证少移到数组元素的同时不需要频繁申请内存。说到底循环队列还是基于顺序储存结构实现的,但是却把数组的逻辑结构想象成一个环状结构,循环队列是没有绝对的队首和队尾之分的,只有两个指针分别指向逻辑的队首和队尾。像普通顺序储存结构的移动数组元素的过程用移动指针来实现,其他移动指针也并不是真正的移动,因为这两个指针就是两个变量,保存的是队首和队尾元素在数组中的真正下标,也许在某个时候,队首的下标比队尾下标还要大,这时候,队列真正使用的数组部分是数组的后半部分的一点和前半部分的一点,而数组的中间却是空着的。这样就结合基本顺序和链式储存结构的优点,但也是有其缺点的,缺点也很明显,就是循环队列的队列最大容量是固定的,在使用循环队列时,可以先稍微大一点估计所需要的容量,再申请一个需要的循环队列。
下面的代码就是实现循环队列
#pragma once
#ifndef SEQUEUE_H
#define SEQUEUE_H
#include "queue.h"
namespace dataStructure
{
template<typename T>
class SeQueue:public Queue<T>
{
public:
SeQueue();
SeQueue(const int size);
~SeQueue();
int Length()const;
bool Empty() const;
void Clear();
void Traverse(void(*visit)(T &t))const;
bool OutQueue(T &t);
bool GetHead(T &t);
bool InQueue(const T &t);
private :
const int DEFAULT_MAX_SIZE = 1000;
int maxSize;
int front, rear;//队首指针和队尾指针,front表示队首元素下标,rear表示首尾元素的后一个位置的下标
int size;
T *data;
};
template<typename T>
SeQueue<T>::SeQueue()
{
maxSize = DEFAULT_MAX_SIZE;
data = new T[MAX_SIZE];
front = rear = 0;
size = 0;
}
template<typename T>
SeQueue<T>::SeQueue(const int size)
{
maxSize = size;
data = new T[maxSize];
front = rear = 0;
this->size = 0;
}
template<typename T>
SeQueue<T>::~SeQueue()
{
delete data;
front = rear = 0;
size = 0;
}
template<typename T>
int SeQueue<T>::Length() const
{
return size;
}
template<typename T>
bool SeQueue<T>::Empty() const
{
return size == 0;
}
template<typename T>
void SeQueue<T>::Clear()
{
size = 0;
front = rear = 0;
}
template<typename T>
void SeQueue<T>::Traverse(void(*visit)(T &t))const
{
if (size != maxSize) {//如何队列满了,则rear肯定就等于front了
for (int pos = front;pos != rear;pos = (pos + 1) % maxSize)//解决队尾指针在队首指针的前面
{
visit(data[pos]);
}
}
else
{
int index = 0;//逻辑下标
for (int pos = front;index < size;pos = (pos + 1) % maxSize, index++)
{
visit(data[pos]);
}
}
}
template<typename T>
bool SeQueue<T>::OutQueue(T &t)
{
if (size > 0)
{
t = data[front];
front = (front + 1) % maxSize;
--size;
return true;
}
return false;
}
template<typename T>
bool SeQueue<T>::GetHead(T &t)
{
if (size > 0)
{
t = data[front];
return true;
}
return false;
}
template<typename T>
bool SeQueue<T>::InQueue(const T &t)
{
if (size < maxSize)
{
data[rear] = t;
rear = (rear + 1) % maxSize;
++size;
return true;
}
return false;
}
}
#endif
#include "stdafx.h"
#include "arrayqueue.h"
#include "linkqueue.h"
#include "sequeue.h"
#include <iostream>
using namespace std;
using namespace dataStructure;
void visit(int &t)
{
cout << t << ",";
}
int main()
{
Queue<int> * queue = new SeQueue<int>(3);
queue->InQueue(1);
queue->InQueue(2);
queue->InQueue(3);
queue->Traverse(visit);
cout << endl;
cout << queue->InQueue(4) << endl;
int i;
cout << queue->OutQueue(i) << endl;
cout << queue->InQueue(4) << endl;
queue->Traverse(visit);
system("pause");
return 0;
}

本文详细探讨了循环队列这一重要的数据结构,包括其基本概念、操作原理及应用场景,帮助读者深化对循环队列的理解。
610

被折叠的 条评论
为什么被折叠?



