看数据结构写代码(16)顺序队列的实现(循环队列)

循环队列的基本结构如下:


front 属性 表示 队头,rear 属性表示 队尾。

在队空时 :q.rear 和 q.front 都为0 ,其余时刻q.rear 指向 队尾的后继节点,q.front指向 队头.

当在队尾插入元素时,q.rear + 1 ,在删除 队头元素时 ,q.front + 1,这样的操作 会造成 “假溢出”问题。

图(d) 就是一种 假溢出 问题,q.rear 指向 空间的边界,再插入 会造成 溢出,但是 实际上 空间 并未满。

为了解决假溢出,将 队列 看成 一个 环。下面上图:


当队列成为一个循环队列时 有两个问题:

1. 当队空 和 队满时, q.front 都等于 q.rear;这样就无法区分 队空 和 队满的 情况。解决这个问题 有两个方法:

(1) 设置 一个 标志位,来区分 是队空,还是队满。

(2) 少用一个元素空间(最高地址元素),判断 队头指针在 队尾指针的下一个位置上就是队满。

下面的代码用的是第一个方法,设置了一个 队列长度 len 属性 来 判断 队空,队满。

2. 当 队满时,不能像 顺序表一样 重新 分配 一个更大的 空间。所以 如果 不知道 队列的 最大空间,请 使用 链表,或者 非循环队列。非循环队列 在出队时, 队头位置不动,而是移动元素位置,并将 队尾位置减1.


下面贴出我的代码,欢迎指出代码不足

// SequenceQueue.cpp : 循环队列的算法实现。
//

#include "stdafx.h"
#include <stdlib.h>
队列最大分配数
#define QUEUE_MAX_SIZE	10//为了测试 故意将值设置很小

typedef int ElementType;
enum E_State
{
	E_State_Error = 0,
	E_State_Ok,
};

//循环队列数据结构
struct Queue
{
	ElementType * base;//堆分配基址
	int front;//队头索引,指向队头节点
	int rear;//队尾索引,指向队尾节点的后继结点
	int len;//队长
};

E_State queueInit(Queue * queue){
	queue->base = (ElementType *) malloc(sizeof(ElementType) * QUEUE_MAX_SIZE);
	if (queue->base != NULL)
	{
		queue->front = queue->rear = 0;
		queue->len = 0;
		return E_State_Ok;
	}
	else
	{
		return E_State_Error;
	}
}

void queueClear(Queue * q){
	q->front = q->rear = 0;
	q->len = 0;
}

void queueDestory(Queue * q){
	queueClear(q);
	free(q->base);
	q->base = NULL;
}

bool queuEmpty(Queue q){
	return q.len == 0 ? true : false;
}

int queueLen(Queue q){
	return q.len;
}

//入队
E_State enqueue(Queue * q,ElementType data){
	if (q->len >= QUEUE_MAX_SIZE)
	{
		printf("队满,插入无效\n");
		return E_State_Error;
	}
	q->base[q->rear] = data;
	q->rear = (q->rear +1)% QUEUE_MAX_SIZE;
	q->len++;
	return E_State_Ok;
}

//出队
E_State dequeue(Queue * q,ElementType * data){
	if (q->len > 0)//栈不为空
	{
		*data = q->base[q->front];
		q->front = (q->front + 1) % QUEUE_MAX_SIZE;
		q->len --;
		return E_State_Ok;
	}
	return E_State_Error;
}

void queueTraverse(Queue q){
	printf("--------队列遍历开始----------\n");
	if (q.len > 0)//队列非空
	{
		int index = q.front;
		//用do while 排除了 队满的情况。。。
		do
		{
			printf("----------%d-----------\n",q.base[index]);
			index = (index+1)%QUEUE_MAX_SIZE;
		} while (index != q.rear);
	}
	printf("--------队列遍历结束----------\n");
}


int _tmain(int argc, _TCHAR* argv[])
{
	Queue queue;
	queueInit(&queue);//初始化
	enqueue(&queue,1);//入队
	ElementType data;
	dequeue(&queue,&data);//出队
	for (int i = 1; i <= QUEUE_MAX_SIZE+1; i++)//故意入满,还入队
	{
		enqueue(&queue,i);
	}
	dequeue(&queue,&data);
	dequeue(&queue,&data);//出队
	queueTraverse(queue);
	char * s = queuEmpty(queue) ? "空" : "不为空";
	printf("队列长度为:%d\n队列是否为空:%s",queueLen(queue),s);
	queueDestory(&queue);
	return 0;
}


运行截图:










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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值