一、 队列定义
队列是一种先入先出(FIFO——first in first out)线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。
二、队列实现
实现队列,我们可以使用链表,链表中的每个结点不仅包含值,还包含链接到下一个结点的引用字段。通过这种方式,单链表将所有结点按顺序组织起来。蓝色箭头显示单个链接列表中的结点是如何组合在一起的
用链表实现队列相对数组实现队列的优点是能节约空间,没有浪费的空间节点。
三、 队列设计
我们分别采用c++和codesys中st语言进行实现链表队列
(1) C++ 语言实现
功能如下
- Push(value) : 向队列中插入一个元素,成功返回true
- pop():从队列中删除一个元素,成功返回true
- Front():从队列头部获取元素,如果队列是空,返回false
- Rear():从队列尾部获取元素,如果队列为空,返回false
- Empty(): 检测队列是否为空,为空返回true
- Size():获得队列节点个数,返回个数
typedef int DataElement;//用户自定义的数据
typedef struct QueueElement//队列元素
{
DataElement mdata;//用户自定义的数据
QueueElement* next;//指向下一个节点
}QueueElement;
//通过链表实现队列
class ListCircleQueue
{
public:
ListCircleQueue() {};
~ListCircleQueue() {};
private:
QueueElement* pHead = 0;//
QueueElement* pTail = 0;//队尾指针
public:
bool push(DataElement _data)
{
// 申请一个结点空间
QueueElement* pTemp = (QueueElement*)malloc(sizeof(QueueElement));
pTemp->mdata = _data;// 申请一个结点空间
pTemp->next = 0;// 结点的next设为NULL
if (Empty()) // 判断队头和队尾是否为空,用于第一次入队
{
pHead = pTemp; // 判断队头和队尾是否为空,用于第一次入队
pTail = pTemp;
}
else
{
pTail->next = pTemp;// 让pTemp成为当前尾部的下一结
pTail = pTemp;// 尾部指针指向pTemp
}
return true;
}
bool pop()
{
if (Empty())
return false;
if (pHead->next == 0)// 判断队列是否就1个,如果只有一个 ,移除后队列为空
{
pHead = 0;
pTail = 0;
}
else
{
QueueElement* pTemp = pHead;
pHead = pHead->next;//移动头部指针
delete(pTemp);//清除移除的内存空前
}
return true;
};
bool Front(DataElement &_data)
{
if (pHead != 0)
{
_data = pHead->mdata;//返回头部数据
return true;
}
else
return false;
}
bool Rear(DataElement& _data)
{
if (pTail != 0)
{
_data = pTail->mdata;//返回尾部数据
return true;
}
else
return false;
}
//返回节点个数
int Size()
{
int iSize = 0;
QueueElement* pTemp = pHead;
while (pTemp != 0)
{
iSize = iSize + 1;
pTemp = pTemp->next;
}
return iSize;
}
//判断队列是否为空
bool Empty()
{
if ((pHead == 0) && (pTail == 0))
return true;
else
return false;
}
}
示例如下
(2) Codesys 实现
- 编程软件: Codesys V3.5 SP17
- 运行设备:PC电脑
- 编程语言: ST ST 掌握如何创建动态数组 之New的使用;以及指针的灵活使用
定义结构体
//队列操作的数据
TYPE ListQueueElement :
STRUCT
mData : BaseElement;
pNext : POINTER TO ListQueueElement;
END_STRUCT
END_TYPE
其中 BaseElement 是一个别名,其定义如下,这里BaseElement 是用户自定义数据(比如结构体),采用别名是方便替换。
TYPE BaseElement : INT; END_TYPE
定义功能块(FUNCTION_BLOCK): ListQueue,实现如下函数
- Push(value) : 向队列中插入一个元素,成功返回true
- pop():从队列中删除一个元素,成功返回true
- Front():从队列头部获取元素,如果队列是空,返回false
- Rear():从队列尾部获取元素,如果队列为空,返回false
- Empty(): 检测队列是否为空,为空返回true
- Size():获得队列节点个数,返回个数
示例如下
PROGRAM PLC_PRG
VAR
t : ListQueue;
END_VAR
VAR
bInit :BOOL:= FALSE;
isize : INT;
ivar1: ARRAY[0..10] OF BaseElement;
END_VAR
IF bInit = FALSE THEN
bInit := TRUE;
t.Push(11);//入队 ,返回TRUE
t.Push(22);//入队 ,返回TRUE
t.Push(33);//入队 ,返回TRUE
isize := t.Size();//返回3
t.Front(_data =>ivar1[0]);//返回11
t.Pop(); //从循环队列中删除一个元素,成功返回true
t.Front(_data =>ivar1[1]);//返回22
END_IF