C语言实现动态队列

                队列作为线性表的一种,它和普通的顺序表和链表不同的是,它和栈一样,有着特定的取放数据的规定。

        队列与栈不同的是,队列只能在两端存取数据,存数据的那端称为队尾,取数据的那端称为队头,因此队列满足先进先出——FIFO(先进先出)的特性。

        因为队列需要在两端进行操作,所以用数组来实现的效率比较低,所以这里用链表的形式来实现队列。

        首先我们要定义每一个队列节点的结构体

typedef struct QNode 
{
	struct QNode* next;
	QDataType val;
}QNode;

        因为要在队列的两端进行数据的操作,如果只有一个头结点的话,那每次入栈操作的效率都很低,因此可以再定义一个结构,这个结构体用来保存队头结点和队尾节点的信息,以及队列中有几个数据。

typedef struct Queue
{
	QNode* head;
	QNode* tail;
	int size;
}Queue;

        有了队列的结构体以后就要对这个队列进行初始化,刚开始时,队列中没有数据,所以队头指针和队尾指针都指向空,size的大小为0;

void QueueInit(Queue* pq)
{
	assert(pq);

	pq->head = pq->tail = NULL;
	pq->size=0;
}

         有了队列以后就可以在队列中插入数据了,因为采用的是链表的形式实现的队列,所以在每次插入新的数据时,都要申请一个新的节点;插入数据的操作和链表插入数据的操作是类似的,如果队列中已有数据,那就把新的节点直接插入到队尾节点之后即可,如果队列为空,那就需要把队头和队尾都指向这第一个节点。

void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);

	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->val = x;
	newnode->next = NULL;

	if (pq->head == NULL)
	{
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
	pq->size++;
}

        出栈的操作和无头单向链表中的头删操作类似:先把保存下一个节点的信息,再free队头位置的节点,再把队头指针指向之前保存的那个节点。这里需要主要的是,需要额外处理的情况是当队列中只有一个数据的情况,此时队头和队尾指针都指向这一个节点,如果和队列中有多个节点的处理方式一样处理,虽然并不会造成内存泄漏的问题,但此时的队尾指针还指向这个节点所在内存的位置,但是这个节点已经被我们释放了,这块内存空间已经被操作系统回收了,此时队尾指针就变成了野指针。

void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->size != 0);

	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode* next = pq->head->next;
		free(pq->head);
		pq->head = next;
	}
	pq->size--;
}

        取队头元素的数据和队尾元素的数据就只需要返回相应的指针所指向的节点的值即可。

QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->head);

	return pq->head->val;
}

QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->tail);

	return pq->tail->val;
}

        队列内数据的个数我们在构造队列的结构体时已经有了,直接返回即可。

int QueueSize(Queue* pq)
{
	assert(pq);

	return pq->size;
}

        判断队列是否为空,也只需要判断size是否为0即可。

bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->size == 0;
}

        这里也是类似链表的销毁,从队头位置开始释放内存空间到队尾结束。

void QueueDestory(Queue* pq)
{
	assert(pq);

	QNode* cur = pq->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = pq->tail = NULL;
	pq->size = 0;
}

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值