使用c语言定义队列

数据结构 同时被 2 个专栏收录
6 篇文章 0 订阅
6 篇文章 0 订阅

       上一篇实现了栈,底层使用的是数组,但是实现队列的话,数组就不太方便了,因为入队和出队不是在同一个位置进行的。可以想象一下用数组实现队列的话,我们需要定义一个多长的数组呢?所以显然对于一般的队列而言,使用链表来实现一个基本的队列是可行的。实际上也可以用数组来实现队列,请见下一篇“环形队列”。

        同样的,实现基本队列需要做两个工作:1.定义队列的节点 2.基本操作接口。关于测试用例,是一个非常简单的接口测试,如果想要找到一个更加切实的场景,可以去寻找一下广度优先搜索的案例,广度优先搜索就需要维护一个数据队列来完成广度优先搜索。

上代码:

myqueue.h

/*用链表实现队列*/

#ifndef MYQUEUE_H
#define MYQUEUE_H
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>

typedef int Item_Queue;

#define QUEUESIZE 20

typedef struct Node_Queue {
	Item_Queue item;
	struct Node* next;
}QueueNode;

typedef struct Queue {
	QueueNode* front;
	QueueNode* rear;
	int items;
}Queue;

/*初始化队列*/
extern void InitQueue(Queue* pq);
/*检查队列已满*/
extern bool QueueIsFull(Queue * pq);
/*检查队列为空*/
extern bool QueueIsEmpty(Queue* pq);
/*队列中节点数目*/
extern int QueueItemCnt(Queue * pq);
/*向队尾添加节点*/
extern bool EnQueue(Queue* pq,Item_Queue item);
/*从队首删除节点*/
extern bool DeQueue(Queue* pq, Item_Queue* item);
/*清空队列*/
extern void ClearQueue(Queue* pq);
/*遍历队列*/
extern void TraverseQueue(Queue* pq, void(*pfun)(Item_Queue* item));

#endif // !MYQUEUE_H

myqueue.c(关于删除队首节点,需要强调一点,一定要记得释放节点资源,别给整内存泄漏了)

#include"myqueue.h"
#include <stdio.h>

/*初始化队列*/
void InitQueue(Queue* pq) {
	pq->front = pq->rear = NULL;
	pq->items = 0;
}
/*检查队列已满*/
bool QueueIsFull(Queue * pq) {
	return pq->items == QUEUESIZE;
}
/*检查队列为空*/
bool QueueIsEmpty(Queue* pq) {
	return pq->items == 0;
}
/*队列中节点数目*/
int QueueItemCnt(Queue * pq) {
	return pq->items;
}
/*向队尾添加节点*/
bool EnQueue(Queue* pq, Item_Queue item) {
	QueueNode *pnew;
	if (QueueIsFull(pq)) {
		return false;
	}
	pnew = (QueueNode *)malloc(sizeof(QueueNode));
	if (pnew == NULL) {
		printf("@liu@ ERROR unable to allocate memary\n");
		return false;
	}
	pnew->item = item;
	pnew->next = NULL;
	if (QueueIsEmpty(pq)) {
		pq->front = pnew;
		pq->rear = pnew;
		pq->items++;
	}else {
		pq->rear->next = pnew;
		pq->rear = pq->rear->next;
		pq->items++;
	}
	return true;
}
/*从队首删除节点*/
 bool DeQueue(Queue* pq, Item_Queue* item) {
	QueueNode* pos;
	if (QueueIsEmpty(pq)) {
		printf("@liu@ERROR tring to dequeue an empty queue\n");
		return false;
	}
	*item = pq->front->item;
	pos = pq->front;
	pq->front = pq->front->next;
	free(pos);
	pq->items--;
	return true;
}
/*清空队列*/
void ClearQueue(Queue* pq) {
	Item_Queue dummy = 0;
	while (!QueueIsEmpty(pq))
		DeQueue(pq,dummy);
}
/*遍历队列*/
void TraverseQueue(Queue* pq, void(*pfun)(Item_Queue* item)) {
	if (QueueIsEmpty(pq)) {
		printf("@liu@ ERROR trying to operate empty queue\n");
		return false;
	}
	Queue* pos;
	pos = pq;
	do {
		(*pfun)(pos->front->item);
		pos->front = pos->front->next;
	} while (pos->front != pos->rear);
		
}

测试用例:(测试用例没有使用遍历和清空接口,大家可以试一下我写的,因为我也不知道是不是有bug,尝试debug啦~)

main.c

int main()
{
#if QUEUE_TEST
	Queue* queueA = (Queue*)malloc(sizeof(Queue));
	InitQueue(queueA);
	cout << QueueIsFull(queueA) << endl;
	cout << QueueIsEmpty(queueA) << endl;
	cout << QueueItemCnt(queueA) << endl;
	Item_Queue a[] = {1,2,3,8,9,0};
	for (int i = 0; i < 6;i++) {
		EnQueue(queueA,a[i]);
		cout << "push" << a[i]<<" ";
	}
	Item_Queue tmp;
	cout << endl << QueueItemCnt(queueA) << endl;
	for (int i = 0; i < 3; i++) {
		DeQueue(queueA, &tmp);
		cout << "pop" << tmp << " ";
	}
	cout << endl << QueueItemCnt(queueA) << endl;

#endif
	system("pause");
	return 0;
}

测试结果:

  • 1
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

#include #include #include //队列最大长度 #define MAX_QUEUE 1024 //偷懒,就用静态队列了 static int mQueue[MAX_QUEUE]; //队列插入 void InsertData(int **Front, int **Rear) { if (*Rear + 1 == *Front && (*Rear + 1 - MAX_QUEUE != *Front)) { //当队列数据已满,返回 puts("Queue Size Overflow!\n"); return; } else if (*Rear - mQueue > MAX_QUEUE) { //实现的是类似循环队列,但由于是静态线性队列(数组) //而不是用链表来实现的,所以到静态队列(数组)尾部,尾指针自动指向(数组)头部 *Rear = mQueue; } puts("Input Data:"); scanf("%d", *Rear); //输入数据后,尾指针后移 *Rear += 1; } //从头指针删除一个队列中的数据 void DeleteData(int **Front, int **Rear) { if (*Front == *Rear) { //头指针尾指针重合,队列空,不能删除,返回 puts("Queue Empty!\n"); return; } else if (*Front - mQueue > MAX_QUEUE) { //参考 Rear *Front = mQueue; } //从头指针删除一个数据 *Front += 1; } //显示队列数据 void ShowData(int **Front, int **Rear) { int *temp; for (temp=*Front; temp!=*Rear; temp++) { printf("%d --> ", *temp); } puts("\n"); } void usage(void) { puts("1. Insert Data"); puts("2. Delete Data"); puts("3. Show Data"); } int main(int argc, char **argv) { //头指针,尾指针 //队列的一个特性 First in first out FIFO int *pFront, *pRear; int op_code; //初始化队列,头指针和尾指针此时指向的地址相同 pFront = pRear = mQueue; while (1) { usage(); scanf("%d", &op_code); switch (op_code) { case 1: printf("%p\n", pFront); printf("%d\n", *pFront); InsertData(&pFront, &pRear); break; case 2: DeleteData(&pFront, &pRear); break; case 3: ShowData(&pFront, &pRear); break; default: break; } } return 0; }
©️2021 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值