队列的读写顺序为先入先出,根据结构可以分为单向队列、双向队列、循环队列、双向循环队列等
这里以循环的顺序队列和单向链队列为例:
循环的顺序队列定义:
typedef struct QUEUE {
int iData[ARRAY_SIZE];
int iFront;
int iRear;
}T_Queue, *PT_Queue;
iData是数据域
iFront、iRear是首尾标志变量,作为指针域
单向链队列定义:
typedef struct NODE {
int iData;
struct NODE *ptNext;
}T_Node, *PT_Node;
队列节点同链表节点定义
typedef struct QUEUE {
PT_Node ptFront;
PT_Node ptRear;
}T_Queue, *PT_Queue;
队列结构包含一个头指针、一个尾指针
队列的主要操作有:
1、判空 / 判满:int isEmpty(PT_Queue ptQueue); / int isFull(PT_Queue ptQueue);
对于循环的顺序队列,为了区分判空和判满,要么另设一个标志位,要么在数据域空出一个位置(这样队满时尾指针总在头指针的前一个位置),这里采用第二种方法,因此,判空条件为首尾指针相同,判满条件为 (iRear + 1) % ARRAY_SIZE == iFront,
对于单向链队列,判空条件为头指针与尾指针指向头节点(标志作用,不是数据节点),判满条件为空间不足
2、创建空队列:PT_Queue createQueue(void);
对于循环的顺序队列,创建空队列就是分配一块数据域和头尾指针
对于单向链队列,创建空队列只需分配一个头节点(指针域为NULL)和头尾指针,并让头尾指针指向头节点即可
3、入队:int queue(int iEle, PT_Queue ptQueue);
对于循环的顺序队列,入队时先判满,不满则尾指针加1并对ARRAY_SIZE求余,写入数据
对于单向链队列,入队时创建一个新节点,创建成功则修改数据域,并将新节点作为第一个数据节点插入链表
4、出队:int dequeue(PT_Queue ptQueue);
对于循环的顺序队列,出队时先判空,不空则头指针加1并对ARRAY_SIZE求余,读出数据
对于单向链队列,出队时先判空,不空则读出第一个数据节点的数据域,头指针指向第二个数据节点,并将第一个数据节点删除,若删除后队列为空,需要将尾指针也指向头节点(标志作用)
循环的顺序队列代码:
#include <stdio.h>
#include <stdlib.h>
#define MENU_EXIT 0
#define MENU_QUEUE 1
#define MENU_DEQUEUE 2
#define MENU_PRINT 3
#define ERR -100
typedef struct QUEUE {
int iData[ARRAY_SIZE];
int iFront;
int iRear;
}T_Queue, *PT_Queue;
int isEmpty(PT_Queue ptQueue)
{
return (ptQueue->iFront == ptQueue->iRear) ? 1 : 0 ;
}
int isFull(PT_Queue ptQueue)
{
return ((ptQueue->iRear + 1) % ARRAY_SIZE == ptQueue->iFront) ? 1 : 0 ;
}
void printQueue(PT_Queue ptQueue)
{
int i = ptQueue->iFront;
if (isEmpty(ptQueue))
{
printf("Queue is empty\r\n");
return;
}
printf("\r\n\r\n"
"Queue: ");
while ( i != ptQueue->iRear)
{
i = (i + 1) % ARRAY_SIZE;
printf("%d ", ptQueue->iData[i]);
}
printf("\r\n\r\n");
}
int queue(int iEle, PT_Queue ptQueue)
{
if (isFull(ptQueue))
{
printf("Queue is full\r\n");
return ERR;
}
ptQueue->iRear = (ptQueue->iRear + 1) % ARRAY_SIZE;
ptQueue->iData[ptQueue->iRear] = iEle;
//printf("Queue: %d\r\n", ptQueue->iData[ptQueue->iRear]);
return iEle;
}
int dequeue(PT_Queue ptQueue)
{
if (isEmpty(ptQueue))
{
printf("Queue is empty\r\n");
return ERR;
}
ptQueue->iFront = (ptQueue->iFront + 1) % ARRAY_SIZE;
//printf("Dequeue: %d\r\n", ptQueue->iData[ptQueue->iFront]);
return ptQueue->iData[ptQueue->iFront];
}
PT_Queue createQueue(void)
{
int iNum, i, iEle;
PT_Queue ptQueue = NULL;
printf("Enter num of data: ");
scanf_s("%d", &iNum);
if (iNum > ARRAY_SIZE - 1 || iNum < 0)
goto done;
ptQueue = (PT_Queue)malloc(sizeof T_Queue);
ptQueue->iFront = ptQueue->iRear = 0;
printf("Enter your data: ");
for (i = 0; i < iNum; i++)
{
scanf_s("%d", &iEle);
queue(iEle, ptQueue);
}
done:
return ptQueue;
}
int menu(PT_Queue ptQueue)
{
int iNum, iEle;
printf("0 to exit\r\n"
"1 to queue\r\n"
"2 to dequeue\r\n"
"3 to print\r\n");
scanf_s("%d", &iNum);
switch (iNum)
{
case MENU_EXIT:
return -1;
case MENU_QUEUE:
printf("Enter the one to be push\r\n");
scanf_s("%d", &iEle);
queue(iEle, ptQueue);
break;
case MENU_DEQUEUE:
dequeue(ptQueue);
break;
case MENU_PRINT:
printQueue(ptQueue);
break;
}
return 0;
}
int main(void)
{
PT_Queue ptQueue;
ptQueue = createQueue();
if (!ptQueue)
return -1;
while (1)
{
if (menu(ptQueue) == -1)
break;
}
return 0;
}
单向链队列代码:
#include <stdio.h>
#include <stdlib.h>
#define MENU_EXIT 0
#define MENU_QUEUE 1
#define MENU_DEQUEUE 2
#define MENU_PRINT 3
#define ERR -100
typedef struct NODE {
int iData;
struct NODE *ptNext;
}T_Node, *PT_Node;
typedef struct QUEUE {
PT_Node ptFront;
PT_Node ptRear;
}T_Queue, *PT_Queue;
int isEmpty(PT_Queue ptQueue)
{
return (ptQueue->ptRear == ptQueue->ptFront) ? 1 : 0;
}
void printQueue(PT_Queue ptQueue)
{
PT_Node ptTmp;
if (isEmpty(ptQueue))
{
printf("Queue is empty\r\n");
return;
}
printf("\r\n\r\n"
"Queue: ");
ptTmp = ptQueue->ptFront;
while (ptTmp->ptNext && ptTmp != ptQueue->ptRear)
{
ptTmp = ptTmp->ptNext;
printf("%d ", ptTmp->iData);
}
printf("\r\n\r\n");
}
int queue(int iEle, PT_Queue ptQueue)
{
PT_Node ptNew;
ptNew = (PT_Node)malloc(sizeof T_Node);
if (!ptNew)
{
printf("Err in memory\r\n");
return ERR;
}
ptNew->iData = iEle;
ptNew->ptNext = NULL;
ptQueue->ptRear->ptNext = ptNew;
ptQueue->ptRear = ptNew;
//printf("Queue: %d\r\n", ptQueue->iData[ptQueue->iRear]);
return iEle;
}
int dequeue(PT_Queue ptQueue)
{
PT_Node ptOld, ptTmp;
int iEle;
if (isEmpty(ptQueue))
{
printf("Queue is empty\r\n");
return ERR;
}
ptTmp = ptQueue->ptFront;
ptOld = ptTmp->ptNext;
iEle = ptOld->iData;
ptTmp->ptNext = ptOld->ptNext;
if (!ptTmp->ptNext)
ptQueue->ptRear = ptQueue->ptFront;
free(ptOld);
//printf("Dequeue: %d\r\n", ptQueue->iData[ptQueue->iFront]);
return iEle;
}
PT_Queue createQueue(void)
{
int iNum, i, iEle;
PT_Queue ptQueue;
PT_Node ptNew;
ptQueue = (PT_Queue)malloc(sizeof T_Queue);
if (!ptQueue)
{
printf("Err in memory\r\n");
return NULL;
}
ptNew = (PT_Node)malloc(sizeof T_Node);
if (!ptQueue)
{
free(ptQueue);
printf("Err in memory\r\n");
return NULL;
}
ptQueue->ptFront = ptQueue->ptRear = ptNew;
ptNew->ptNext = NULL;
#if 0
printf("Enter num of data: ");
scanf_s("%d", &iNum);
if (iNum < 0)
goto done;
printf("Enter your data: ");
for (i = 0; i < iNum; i++)
{
scanf_s("%d", &iEle);
if (!queue(iEle, ptQueue))
{
printf("Create successfully %d nodes\r\n", i+1);
goto done;
}
}
#endif
done:
return ptQueue;
}
int menu(PT_Queue ptQueue)
{
int iNum, iEle;
printf("0 to exit\r\n"
"1 to queue\r\n"
"2 to dequeue\r\n"
"3 to print\r\n");
scanf_s("%d", &iNum);
switch (iNum)
{
case MENU_EXIT:
return -1;
case MENU_QUEUE:
printf("Enter the one to be push\r\n");
scanf_s("%d", &iEle);
queue(iEle, ptQueue);
break;
case MENU_DEQUEUE:
dequeue(ptQueue);
break;
case MENU_PRINT:
printQueue(ptQueue);
break;
}
return 0;
}
int main(void)
{
PT_Queue ptQueue;
ptQueue = createQueue();
if (!ptQueue)
return -1;
while (1)
{
if (menu(ptQueue) == -1)
break;
}
return 0;
}