队列的基本运算实现

队列(queue)

队列是一种先进先出(first in first out,FIFO)的线性表。它只允许在表的一端(队尾/rear)插入元素,而在另一端(队头/front)删除元素。插入操作称为入队或进队,删除操作称为出队或离队。队列示意图如下:

1、 顺序队

队列的顺序存储结构需要使用一个数组和两个整型变量来实现,数组用于存储队列中的所有元素,两个整型变量分别用于存储队头元素和队尾元素的下标位置,分别称为队头指针和队尾指针。

假定队列的元素个数不超过MaxSize,所有的元素的数据类型都是ElemType,则顺序队列类型SqQueue定义如下:

typedefstruct

{

ElemType data[MaxSize];

Int front,rear;

}SqQueue;

在顺序队列*q中,队空的条件是q->front==q->rear;队满的条件是q->rear==MaxSize-1;元素e入队的操作是先将队尾指针加1,然后将元素e放入队尾;出队操作是先将队头指针加1,然后取出队头处的元素;队尾指针总是指向当前队列中的队尾元素,而队头指针总是指向当前队列中队头元素的前一个位置。

顺序队的基本运算实现如下:

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

#define MaxSize 20	//队列元素最大个数
typedef char ElemType;		//队列元素类型
typedef struct	//顺序队
{
	ElemType data[MaxSize];	//数据元素
	int front;	//对头指针
	int rear;	//队尾指针
}SqQueue;

void InitQueue(SqQueue *&q)	//初始化队列
{
	q=(SqQueue *)malloc(sizeof(SqQueue));
	q->front=q->rear=-1;
}

void DestoryQueue(SqQueue *&q)	//销毁队列
{
	free(q);
}

bool QueueEmpty(SqQueue *q)		//判断队列是否为空
{
	return (q->front==q->rear);
}

bool QueueFull(SqQueue *q)	//判断队列是否已满
{
	return (q->rear==MaxSize-1);
}

bool EnQueue(SqQueue *&q, ElemType e)	//入队(插入元素)
{
	if(q->rear==MaxSize-1)	//队列已满,不能再插入
		return false;
	q->rear++;
	q->data[q->rear]=e;
	return true;
}

bool DeQueue(SqQueue *&q, ElemType &e)	//出队(删除元素)
{
	if(q->front==q->rear)	//队列为空,无法删除
		return false;
	q->front++;
	e=q->data[q->front];
	return true;
}

int main()
{
	...;
	return 0;
}

2、 环形队列

将数组的前端和后端连接起来,形成环形的顺序表——环形队列。

环形队列的基本运算实现如下:

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

#define MaxSize 10	//队列元素最大个数
typedef char ElemType;		//队列元素类型
typedef struct	//环形队列
{
	ElemType data[MaxSize];	//数据元素
	int front;	//对头指针
	int rear;	//队尾指针
}QuType;

void InitQueue(QuType *&qu)		//初始化队列
{
	qu=(QuType *)malloc(sizeof(QuType));
	qu->front=qu->rear=0;
}

void DestoryQueue(QuType *&qu)	//销毁队列
{
	free(qu);
}

bool QueueEmpty(QuType *&qu)	//判断队列是否为空
{
	return (qu->front==qu->rear);
}

bool QueueFull(QuType *&qu)		//判断队列是否已满
{
	return (qu->front==(qu->rear+1)%MaxSize);
}

bool EnQueue(QuType *&qu, ElemType e)	//入队
{
	if(qu->front==(qu->rear+1)%MaxSize)	//注意!
		return false;
	qu->rear=(qu->rear+1)%MaxSize;
	qu->data[qu->rear]=e;
	return true;
}

bool DeQueue(QuType *&qu, ElemType &e)	//出队
{
	if(qu->front==qu->rear)
		return false;
	qu->front=(qu->front+1)%MaxSize;
	e=qu->data[qu->front];
	return true;
}

int main()
{
	...;
	return 0;
}

3、 链队

队列的链式存储结构通过由结点构成的单链表实现,此时只允许在单链表的表头进行删除操作和在单链表的表尾进行插入操作,因此需要两个指针:队首指针front和队尾指针rear。用front指向队首结点,用rear指向队尾结点。用于存储队列的单链表成为链队。

链队(带头结点)中数据结点的类型QNode定义如下:

typedefstruct qnode

{

ElemType data;

struct qnode *next;

}QNode;         //链队数据结点类型定义

链队结点的类型LinkQueue定义如下:

typedefstruct

{

QNode *front;

QNode *rear;

}LinkQueue;  //链队类型定义

链队的基本运算实现如下:

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

typedef char ElemType;
typedef struct qNode
{
	ElemType data;
	struct qNode *next;
}QNode;	//数据结点
typedef struct
{
	QNode *front;	//队头指针
	QNode *rear;	//队尾指针
}LinkQueue;	//链队结点

void InitQueue(LinkQueue *&q)	//初始化链队
{
	QNode *p=(QNode *)malloc(sizeof(QNode));	//创建头结点
	if(!p)
	{
		printf("内存分配失败\n");
		exit(1);
	}
	p->next=NULL;
	q=(LinkQueue *)malloc(sizeof(LinkQueue));	//分配链队结点空间
	if(!q)
	{
		printf("内存分配失败\n");
		exit(1);
	}
	q->front=q->rear=p;
}

void DestoryQueue(LinkQueue *&q)	//销毁链队
{
	QNode *p;
	while(q->front!=NULL)
	{
		p=q->front;
		q->front=p->next;
	}
	free(p);
}

bool QueueEmpty(LinkQueue *q)	//判断队列是否为空
{
	return (q->front->next==NULL);
}

void EnQueue(LinkQueue *&q, ElemType e)	//入队
{
	QNode *p;
	p=(QNode *)malloc(sizeof(QNode));	//创建新结点
	if(!p)
	{
		printf("内存分配失败!\n");
		exit(1);
	}
	p->data=e;
	p->next=NULL;
	q->rear->next=p;
	q->rear=p;
}

bool DeQueue(LinkQueue *&q, ElemType &e)	//出队
{
	QNode *p;
	if(q->front->next==NULL)	//队列为空,操作无效
		return false;
	p=q->front->next;
	e=p->data;
	q->front->next=p->next;
	if(p->next==NULL)	//删除最后一个结点后,将尾指针指向头结点
		q->rear=q->front;
	free(p);
	return true;
}

int main()
{
	...;
	return 0;
}

几个注意点:

1、顺序队和环形队列的队空条件均是q->front==q->rear;顺序队的队满条件是p->rear==MaxSize-1,而环形队列的队满条件是q->front==(q->rear+1)%MaxSize;

2、顺序队和环形队列初始化的不同,导致最后存储空间上的元素不一样。顺序队的初始化:q->front=q->rear=-1,所以元素从q->data[0]开始存储;而环形队列的初始化:q->front=q->rear=0,所以元素从q->data[1]开始存储,q->data[0]空闲;

3、顺序队列满足队满条件时可能是假溢出(如p->rear==MaxSize-1,此时即使出队几个数据仍然满足了队满条件,但已经腾出了若干个空间,此时就是假溢出),而环形队列满足队满条件就是没有多余的存储空间了;

4、顺序队中的元素个数是rear-front,环形队列中的元素个数是(rear-front+MaxSize)%MaxSize;

5、链队的初始化,创建头结点的同时,为链队结点分配内存空间;

6、出队时,当删除最后一个结点后,尾指针也随之释放,所以应该将尾指针重新赋值,指向头结点。

2014年7月29日星期二

队列的基本运算实现

时间: 2024-10-16 05:55:10

队列的基本运算实现的相关文章

C语言——循环队列的基本运算

#include <stdio.h> #include "SeqQue.h" // 循环队列的基本运算 /* const int maxsize = 20; typedef struct cycque { int data[maxsize]; int front, rear; }CycQue; */ // 1. 初始化 void InitQueue(CycQue CQ) { CQ.front = 0; CQ.rear = 0; } // 2. 判断队空 int EmptyQ

[转]队列及其基本运算

一.队列的定义及其运算 1.定义     队列(Queue)是只允许在一端进行插入,而在另一端进行删除的运算受限的线性表.   (1)允许删除的一端称为队头(Front). (2)允许插入的一端称为队尾(Rear). (3)当队列中没有元素时称为空队列. (4)队列亦称作先进先出(First In First Out)的线性表,简称为FIFO表. 队列的结构特点是先进队的元素先出队.假设有队列Q=(a1,a2,...,an),则队列Q中的元素是按a1,a2,...,an的次序进队,而第一个出队的

C 数据结构之栈和队列

栈:又叫后进先出表,简称为LIFO线性表. 栈的基本运算有六种: 构造空栈:initStack(). 判断栈空:isEmpty(). 判断栈满:isFull(). 进栈: Push().将元素压入栈顶. 出栈: Pop() . 将元素从栈顶弹出. 取栈顶元素:getTop().不同与弹出,只是使用栈顶元素的值,该元素仍在栈顶不会改变.栈由其内核的不同,可以分为:顺序栈和链栈      顺序栈的内核是:数组      链栈的内核是:链表 队列 1.1 队列定义  队列(Queue)也是一种运算受限

栈与队列

栈是一种只能在一端进行插入或者删除操作的线性表,其中允许进行插入或删除的一端称为栈顶. 顺序栈 typedef struct { int data[MaxSize]; int top; }SqStack; 对于一个顺序栈st,一共有 4个要素,包括两个特殊的状态和两个操作: 两个状态 栈空状态 st.top==-1; 栈满状态 st.top==MaxSize-1; 两个操作 元素x进栈 ++(st.top); st.data[top]=x; 元素x出栈 x=st.data[top]; --(st

数据结构习题之栈和队列

第三章  栈和队列 一.    基本要求.重点.难点 本章的目的是介绍栈和队列的逻辑结构定义及在两种存储结构上如何实现栈和队列的基本运算.要求在掌握栈和队列的特点的基础上,懂得在什么样的情况下能够使用栈或队列.本章重点是掌握栈和队列在两种存储结构上实现的基本运算,难点是循环队列中对边界条件的处理. 二.    考核目标和考核要求 要求达到识记层次的有:栈和队列的特点,什么样的情况下能够使用栈或队列 要达到综合应用层次的有:栈的逻辑结构特点,栈与线性表的异同:顺序栈和链栈上实现的进栈.退栈等基本算

数据结构(二)栈、队列和数组

栈 栈的定义 栈是限制在表的一端进行插入和删除的线性表.允许插入.删除的这一端称为栈顶,另 一个固定端称为栈底.当表中没有元素时称为空栈. 栈的存储实现和运算实现 栈是运算受限的线性表,线性表的存储结构对栈也是适用的,只是操作不同而已. 利用顺序存储方式实现的栈称为顺序栈. 与线性表类似,栈的动态分配顺序存储结构如 下: #define STACK_INIT_SIZE 100 //存储空间的初始分配量 #define STACKINCREMENT 10 //存储空间的分配增量 typedef s

数据结构与算法常见笔试题

一.算法的基本概念计算机解题的过程实际上是在实施某种算法,这种算法称为计算机算法.1.算法的基本特征:可行性,确定性,有穷性,拥有足够的情报.2.算法的基本要素:算法中对数据的运算和操作.算法的控制结构.3.算法设计的基本方法:列举法.归纳法.递推.递归.减半递推技术.回溯法.4.算法设计的要求:正确性.可读性.健壮性.效率与低存储量需求二.算法的复杂度1.算法的时间复杂度:指执行算法所需要的计算工作量2.算法的空间复杂度:执行这个算法所需要的内存空间三.数据结构的定义1.数据的逻辑结构:反映数

数据结构与算法面试总结

一.算法的基本概念计算机解题的过程实际上是在实施某种算法,这种算法称为计算机算法.1.算法的基本特征:可行性,确定性,有穷性,拥有足够的情报.2.算法的基本要素:算法中对数据的运算和操作.算法的控制结构.3.算法设计的基本方法:列举法.归纳法.递推.递归.减半递推技术.回溯法.4.算法设计的要求:正确性.可读性.健壮性.效率与低存储量需求二.算法的复杂度1.算法的时间复杂度:指执行算法所需要的计算工作量2.算法的空间复杂度:执行这个算法所需要的内存空间三.数据结构的定义1.数据的逻辑结构:反映数

数据结构简单总结

一.思维导图 二.重要概念 一.数据结构 1.逻辑结构 集合.线性结构.树形结构.图形结构. 2.存储结构 常用的存储结构有顺序存储.链式存储.索引存储和哈希存储等. 3.算法分析 1)目标:正确性.可使用性.可读性.健壮性.时间效率高与储存量低 2)方法:事后估计法.事前分析估算法 3)两个角度:时间复杂度.空间复杂度.二者不可能都为最低,需维持一个合适的平衡. 二.线性表 1.定义 具有相同特性的数据元素的一个有限序列. 其中每个元素都是一对一的相互关系. 2.普通线性表 1)顺序表 特点: