#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 8 // 最大队列长度
#define OVERFLOW -2 // 失败
#define OK 1 // 成功
typedef int QElemType; // 动态分配空间类型
typedef int Stutus; // 函数类型
// 定义顺序队列节点
typedef struct
{
QElemType *base; // 初始化动态分配空间
int front; // 头下标
int rear; // 尾下标
} SqQueue;
/* -------------------------------------------------------------------------- */
// 定义链队列节点
typedef struct QNode
{
QElemType data;
struct QNode *next;
}QNode, *QueuePtr;
// 定义头尾指针
typedef struct
{
QueuePtr front2;
QueuePtr rear2;
} LinkQueue;
/* 预定义函数 */
Stutus InitSqQueue(SqQueue *Q); // 初始化队列
Stutus SqQueueLength(SqQueue Q); // 获取队列长度
Stutus EnQueue(SqQueue *Q, QElemType e); // 循环队列入队
Stutus DeQueue(SqQueue *Q, QElemType *e); // 循环队列出队
QElemType GetHead(SqQueue Q); // 循环队列获取头元素
void print(SqQueue Q); // 遍历队列
/* --------------------------------------------------------------------------- */
Stutus InitQueue(LinkQueue *Q); // 初始化链队列
Stutus DestroyQueue(LinkQueue *Q); // 销毁链队列
Stutus EnLinkQueue(LinkQueue *Q, QElemType e); // 链队列入队
Stutus DeLinkQueue(LinkQueue *Q, QElemType *e); // 链队列出队
Stutus GetQueueHead(LinkQueue Q, QElemType *e); // 链队列获取头元素
void Linkprint(LinkQueue Q);
/* 预定义函数end */
int main(int argc, char const *argv[])
{
/* ------------------------------------循环队列-------------------------------- */
SqQueue Q; // 定义队列变量
int arr[] = {1, 3, 5, 7, 9, 2, 4, 6};
int arr_len = sizeof(arr)/sizeof(int); // 设置长度
int e, flag;
/* 初始化队列 */
InitSqQueue(&Q);
/* 获取队列长度 */
printf("当前队列长度Qlen = %d\n", SqQueueLength(Q));
/* 循环队列入队 */
printf("循环队列入队:");
for (int i = 0; i < arr_len; i++)
{
EnQueue(&Q, arr[i]);
}
print(Q);
printf("当前队列长度Qlen = %d\n", SqQueueLength(Q));
/* 循环队列出队 */
DeQueue(&Q, &e);
printf("当前队列出队元素e = %d\n", e);
printf("循环队列元素:");
print(Q);
printf("当前队列长度Qlen = %d\n", SqQueueLength(Q));
printf("---------------------------------------------------------\n");
/* ------------------------------------链队列------------------------------------- */
LinkQueue LQ;
/* 初始化链队列 */
flag = InitQueue(&LQ);
if (flag == 1) printf("初始化链队列!!!\n");
/* 链队列入队 */
printf("链队列入队:");
for (int i = 0; i < arr_len; i++)
{
EnLinkQueue(&LQ, arr[i]);
}
Linkprint(LQ);
/* 链队列获取头元素 */
GetQueueHead(LQ, &e);
printf("链队列获取头元素:%d\n", e);
/* 链队列出队 */
DeLinkQueue(&LQ, &e);
printf("链队列出队元素:%d\n", e);
Linkprint(LQ);
// DestroyQueue(&LQ); // 销毁队列
return 0;
}
/* 初始化队列 */
Stutus InitSqQueue(SqQueue *Q)
{
Q->base = malloc(MAXSIZE * sizeof(QElemType)); // 分配存储空间
if (!Q->base) exit(OVERFLOW); // 判断是否分配成功
Q->front = Q->rear = 0; // 头尾指针为0,队列空
return OK;
}
/* 获取队列长度 */
Stutus SqQueueLength(SqQueue Q)
{
return (Q.rear - Q.front + MAXSIZE % MAXSIZE); // 头-尾+最大值取余最大值
}
/* 循环队列入队 */
Stutus EnQueue(SqQueue *Q, QElemType e)
{
if ((Q->rear+1) % MAXSIZE == Q->front) return OVERFLOW; // 队满,入队失败
Q->base[Q->rear] = e; // 存入值
Q->rear = (int)(Q->rear+1) % MAXSIZE; // 尾下标+1,当尾下标是最大值时,最大值+1取余最大值实现循环插入
return OK;
}
/* 循环队列出队 */
Stutus DeQueue(SqQueue *Q, QElemType *e)
{
if (Q->rear == Q->front) return OVERFLOW; // 对空,入队失败
*e = Q->base[Q->front]; // 获取对头元素
Q->front = (Q->front+1) % MAXSIZE; // 对头+1
return OK;
}
/* 循环队列获取头元素 */
QElemType GetHead(SqQueue Q)
{
if (Q.front != Q.rear) return Q.base[Q.front]; // 队列非空直接获取
}
void print(SqQueue Q)
{
for (int i = Q.front; i < Q.rear; i++)
{
printf("%d\t", Q.base[i]);
}
printf("\n");
}
/* ------------------------------------链队列函数-------------------------------------------- */
/* 初始化链队列 */
Stutus InitQueue(LinkQueue *Q)
{
Q->front2 = Q->rear2 = (QueuePtr)malloc(sizeof(QNode)); // 创建存储空间,头尾指针同时指向
if (!Q->front2) exit(OVERFLOW); // 分配失败
Q->front2->next = NULL; // 头节点后置置空
return OK;
}
/* 销毁链队列:从头节点开始依次删除所有节点 */
Stutus DestroyQueue(LinkQueue *Q)
{
QNode *temp; // 定义临时指针, 记录删除节点后继地址
while (Q->front2) /* 循环头指针至空 */
{
temp = Q->front2->next; // 记录头节点后继地址
free(Q->front2); // 释放头节点
Q->front2 = temp; // 后一个节点变成头节点
}
return OK;
}
/* 链队列插入操作:尾节点插入新节点 */
Stutus EnLinkQueue(LinkQueue *Q, QElemType e)
{
QNode *temp; // 创建临时指针
temp = (QueuePtr)malloc(sizeof(QNode)); // 创建新节点
if (!temp) exit(OVERFLOW); // 判断是否创建成功
temp->data = e; // 添加元素
temp->next = NULL; // 置空后继节点
Q->rear2->next = temp; // 原末尾节点后继指向新节点
Q->rear2 = temp; // 尾指针指向新尾节点
return OK;
}
/* 链队列出队操作:删除首元节点,头节点后继指向下一节点,
* 特殊情况:只两个节点时,删除后要将头尾指针指向同一节点。
*/
Stutus DeLinkQueue(LinkQueue *Q, QElemType *e)
{
QNode *temp; // 创建临时指针
temp = Q->front2->next; // 记录节点地址
*e = temp->data; // 记录删除节点数据,QElemType为int需要转类型
Q->front2->next = temp->next; // 修改头节点后继指向下下节点
if (Q->front2->next == Q->rear2) Q->rear2 = Q->front2; // 头尾指针指向头节点
free(temp); // 释放
return OK;
}
/* 链队列获取头元素 */
Stutus GetQueueHead(LinkQueue Q, QElemType *e)
{
if (Q.front2 == Q.rear2) return OVERFLOW; // 判断是否为空队
*e = Q.front2->next->data; // 获取头元素
return OK;
}
/* 遍历链队列 */
void Linkprint(LinkQueue Q)
{
QNode *temp = Q.front2->next; // 创建指针指向首元节点
while (temp != NULL) // 循环直至空
{
printf("%d\t", temp->data);
temp = temp->next;
}
printf("\n");
}
C语言队列操作笔记
最新推荐文章于 2022-08-19 10:40:28 发布