一、 队列定义
队列是一种先入先出(FIFO——first in first out)线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。
二、队列实现
实现队列,我们可以使用动态数组以及指向队列头部的索引和指向队列尾部的索引
例如我们分配一个最长长度为6的数组,我们最多只能添加6个元素,在第6次元素22入队后,因为队列已满,队列不能接受更多的入队请求。
但是如果我们将一个元素出队后,应该可以再接受一个元素,这就要考虑循环队列,可以重用被浪费的空间。
三、 循环队列设计
循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
C 语言实现
功能如下
- Create(k):构造器,动态创建K大小的数组
- Push(value) : 向循环队列中插入一个元素,成功返回true
- pop():从循环队列中删除一个元素,成功返回true
- Front():从队列头部获取元素,如果队列是空,返回-1
- Rear():从队列尾部获取元素,如果队列为空,返回-1
- Empty(): 检测队列是否为空
- Full() : 检测队列是否已满
- Destroy:销毁队列
typedef struct {
int *data;//数组指针
int mTail;//尾部索引
int mHead;//头部索引
int mSize;//数组大小
} MyQueue;
bool Empty(MyQueue* obj);
bool Full(MyQueue* obj);
//构造器,动态创建K大小的数组
MyQueue* Create(int k)
{
MyQueue *mMyQueue = ( MyQueue *)malloc(sizeof(MyQueue));
mMyQueue->data = (int*)malloc( sizeof(int)*(k));
mMyQueue->mTail = -1;
mMyQueue->mHead = -1;
mMyQueue->mSize = k;
return mMyQueue;
}
//向循环队列中插入一个元素,成功返回true
bool Push(MyQueue* obj, int value) {
if(obj == 0 )
return false;
if(Full(obj))
return false;
if (Empty(obj))
obj->mHead = 0;
obj->mTail = (obj->mTail + 1) % obj->mSize;
obj->data[obj->mTail] = value;
return true;
}
//从循环队列中删除一个元素,成功返回true
bool pop(MyQueue* obj) {
if(obj == 0 )
return false;
if (Empty(obj))
return false;
if(obj->mHead == obj->mTail)
{
obj->mTail = -1;
obj->mHead = -1;
return true;
}
obj->mHead = (obj->mHead +1) % obj->mSize;
return true;
}
//从队列头部获取元素,如果队列是空,返回-1
int Front(MyQueue* obj)
{
if(obj == 0 )
return -1;
if (Empty(obj))
return -1;
return obj->data[obj->mHead];
}
//从队列尾部获取元素,如果队列为空,返回-1
int Rear(MyQueue* obj)
{
if(obj == 0 )
return -1;
if (Empty(obj))
return -1;
return obj->data[obj->mTail];
}
//检测队列是否已空
bool Empty(MyQueue* obj)
{
if (obj==0)
return false;
if ((obj->mHead == -1) &&(obj->mTail == -1))
return true;
return false;
}
//检测队列是否已满
bool Full(MyQueue* obj) {
if (obj==0)
return false;
if ((obj->mHead == ((obj->mTail +1)%obj->mSize)) && (obj->mHead != -1))
return true;
return false;
}
//:销毁队列
void Destroy(MyQueue* obj) {
if(obj==0)
return ;
if (obj->data != 0)
free(obj->data);
if (obj != 0)
free(obj);
}
Codesys 实现
- 编程软件: Codesys V3.5 SP17
- 运行设备:PC电脑
- 编程语言: ST 掌握如何创建动态数组 之New的使用;以及指针的灵活使用
定义结构体
//队列操作的数据
TYPE QueueElement :
STRUCT
pData : POINTER TO BaseElement;//数组指针
mHead : INT;//头部索引
mTail : INT;//尾部索引
mSize : INT;//数组大小
END_STRUCT
END_TYPE
其中 BaseElement 是一个别名,其定义如下,这里BaseElement 是用户自定义数据(比如结构体),采用别名是方便替换。
TYPE BaseElement : INT; END_TYPE
定义功能块 CircularQueue,实现如下函数
- Create(k):构造器,动态创建K大小的数组
- Push(value) : 向循环队列中插入一个元素,成功返回true
- Pop():从循环队列中删除一个元素,成功返回true
- Front():从队列头部获取元素,如果队列是空,返回-1
- Rear():从队列尾部获取元素,如果队列为空,返回-1
- Empty(): 检测队列是否为空
- Full() : 检测队列是否已满
- Destroy:销毁队列
- Size:获取队列数组大小
示例如下
PROGRAM PLC_PRG
VAR
myCircularQueue : CircularQueue;
END_VAR
VAR
bInit :BOOL:= FALSE;
isize : INT;
ivar1: ARRAY[0..10] OF BaseElement;
END_VAR
IF bInit = FALSE THEN
bInit := TRUE;
myCircularQueue.Create(10);//动态创建数组 大小位10
isize := myCircularQueue.Size();//获得队列数组大小 为10
myCircularQueue.Push(11);//入队 ,返回TRUE
myCircularQueue.Push(22);//入队 ,返回TRUE
myCircularQueue.Push(33);//入队 ,返回TRUE
myCircularQueue.Push(44);//入队 ,返回TRUE
ivar1[0] := myCircularQueue.Front();//返回11
myCircularQueue.Pop(); //从循环队列中删除一个元素,成功返回true
ivar1[1] := myCircularQueue.Front();//返回22
END_IF