队列的简单c语言实现(链表式和循环队列)

对于队列来说,从队尾进,队尾出,要设置一个结点类型的指针q->front,和q->rear,q->front指向的结点是一个特殊的结点,不存放值,next指针域指向的是第一个有效的结点,实际上就是队首结点,而q->rear开始时与q->front相同,随着不断的入列,永远指向最后一个有效结点,q->rear->next为NULL,其它结点的next域不为NULL。

LinkNode p = (LinkNode)malloc(sizeof(NODE));

之所以要对指针类型的p进行malloc是因为仅有指针实际上没有在内存中开辟空间,所以要用malloc为指针指向的结点进行实际内存的分配,而如果是NODE进行定义则不需分配在定义时就完成了分配。在删除结点时,要进行free并且防止野指针:

free(p);
p = NULL;

向下面演示简单的代码,有队列的初始化,判断队列是否为空,入队和出队的操作:

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>

typedef struct Node {
	int val;
	Node *next;
}NODE, *LinkNode;

typedef struct QNode {
	LinkNode front, rear;
}Queue, *LinkQueue;

void InitQueue(LinkQueue queue)
{
	queue->front = queue->rear = (LinkNode)malloc(sizeof(NODE));
	if (!queue->front)
		printf("error!\n");
	queue->front->next = NULL;
}

bool IsEmpty(LinkQueue queue)
{
	if (queue->front == queue->rear)
		return true;
	else
		return false;
}

void EnQueue(LinkQueue queue, int value)
{
	LinkNode p = (LinkNode)malloc(sizeof(NODE));
	if (!p)
		printf("error!\n");
	p->val = value;
	p->next = NULL;
	queue->rear->next = p;
	queue->rear = p;
}
//头结点next域指向第一个有效结点
void DeQueue(LinkQueue queue)
{
	if (IsEmpty(queue))
	{
		printf("error!队列为空");
	}
	LinkNode p = queue->front->next;
	queue->front->next = p->next;
	if (queue->rear == p)
		queue->front = queue->rear;	//当只有一个结点时,p->next为NULL
	free(p);
	p = NULL;
}

void Traverse(LinkQueue queue)
{
	if (IsEmpty(queue))
	{
		printf("error!队列为空");
		exit(0);
	}
	printf("遍历队列的结果是: ");
	LinkNode p = queue->front->next;
	while (p != NULL)
	{
		printf("%d ", p->val);
		p = p->next;
	}
	printf("\n");
}

int main()
{
	Queue queue;
	InitQueue(&queue);
	EnQueue(&queue, 1);
	EnQueue(&queue, 2);
	EnQueue(&queue, 3);
	Traverse(&queue);
	DeQueue(&queue);
	Traverse(&queue);
	DeQueue(&queue);
	DeQueue(&queue);
	if (IsEmpty(&queue))
		printf("此时栈为空\n");		
	return 0;
}

输出结果为:

 

2. 再来介绍一下循环队列,这里的循环队列要有一个front,rear指针,当然这里的指针是名义上的,由于这里的循环队列使用的是顺序结构,就是开辟了一个数组,而不是上面那种链表,所以指针可以用数组下标int类型来表示,要注意的是,初始化循环链表时,q.front 和q.rear = 0相等,但q.front只随着出队前进,q.rear则随着入队前进,q.rear指向的是填有实际元素的结点的下一位,即开辟的MaxSize数组有一个单位不能使用,判断队满的方法就是q.rear的下一位就是q.front,此时q.rear指向的是没有存值的结点,代码为:

 有一个问题时在函数定义时,参数只能用(SqQueue &queue)省去&会报错,这里暂时有点不够理解:

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>

#define MaxSize 4 //多一个单元方便判断队满

typedef struct {
	int Block[4];
	int front, rear;
}SqQueue;



void InitQueue(SqQueue &queue)
{
	queue.front = queue.rear = 0;
}

bool IsEmpty(SqQueue &queue)
{
	if (queue.front == queue.rear)
		return true;
	else
		return false;
}

bool IsFull(SqQueue &queue)
{
	if ((queue.rear + 1) % MaxSize == queue.front)
		return true;
	else
		return false;
}

void EnQueue(SqQueue &queue, int value)
{
	if (IsFull(queue))
	{
		printf("队满!\n");
	}
	else
	{
		queue.Block[queue.rear] = value;
		queue.rear = (queue.rear + 1) % MaxSize;
	}
}
//头结点next域指向第一个有效结点
void DeQueue(SqQueue &queue)
{
	if (IsEmpty(queue))
	{
		printf("error!队列为空");
	}
	queue.front = (queue.front + 1) % MaxSize;
}

void Traverse(SqQueue &queue)
{
	if (IsEmpty(queue))
	{
		printf("error!队列为空");
		exit(0);
	}
	printf("遍历队列的结果是: ");
	int p = queue.front;
	while (p != queue.rear)
	{
		printf("%d ", queue.Block[p]);
		p = (p + 1) % MaxSize;
	}
	printf("\n");
}

int main()
{
	SqQueue queue;
	InitQueue(queue);
	EnQueue(queue, 1);
	EnQueue(queue, 2);
	EnQueue(queue, 3);
	if (IsFull(queue))
		printf("队满!\n");
	Traverse(queue);
	DeQueue(queue);
	Traverse(queue);
	EnQueue(queue, 1);
	Traverse(queue);
	DeQueue(queue);
	Traverse(queue);
	DeQueue(queue);
	DeQueue(queue);
	if (IsEmpty(queue))
		printf("此时队为空\n");
	return 0;
}

运行结果:

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值