您的位置:首页 > 其它

C_栈和队列(ADT)-队列的链式表示和实现

2017-07-19 09:53 330 查看
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。

链表队列基于链表的,要动态创建和删除节点,效率较低,但是可以动态增长。


队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO—first
in first out)线性表



队列的定义:

typedef struct QNode{
ElemType data;
struct	QNode	*next;
}QNode,*QueuePtr;		//定义链表结点中的数据

typedef	struct{
QueuePtr	front;	//队头指针
QueuePtr	rear;	//队尾指针
}LinkQueue;
基本操作的函数原型:

/*操作结果:构造一个空队列Q*/
InitQueue(&Q);

/*初始条件:队列Q已存在。*/
/*操作结果:队列Q被销毁,不再存在。*/
DestroyQueue(&Q);

/*初始条件:队列Q已存在。*/
/*操作结果:将Q清为空队列。*/
ClearQueue(&Q);

/*初始条件:队列Q已存在。*/
/*操作结果:若Q为空队列,则返回TRUE,否则FALSE*/
QueueEmpty(Q);

/*初始条件:队列Q已存在。*/
/*操作结果:返回Q的元素个数,即队列的长度。*/
QueueLength(Q);

/*初始条件:Q为非空队列*/
/*操作结果:用e返回Q的队头元素。*/
GetHead(Q,&e);

/*初始条件:队列Q已存在*/
/*操作结果:插入元素e为Q的新的队尾元素。*/
EnQueue(&Q,e);

/*初始条件:Q为非空队列。*/
/*操作结果:删除Q的队头元素,并用e返回其值。*/
DeQueue(&Q,&e);

/*初始条件:Q已存在且非空。*/
/*操作结果:从队头到队尾,依次队Q的每个数据元素调用函数visit(),一旦visit()失败,则操作失败。*/
QueueTraverse(Q,visit());


构造一个空队列Q:

Status InitQueue(LinkQueue	&q)
{
q.front=q.rear=(QueuePtr)malloc(sizeof(QNode));	//创建头结点,头指针指向头结点
if(!q.front)	//创建失败
{
printf("构造队列失败!\n");
return ERROR;
}
q.front->next=NULL;		//头结点下一个指针指向NULL,避免出现野指针
printf("构造队列成功!\n");
return OK;
}


销毁队列Q,结果使得队列Q不存在:
Status  DestroyQueue(LinkQueue	&q)
{
while(q.front)
{
q.rear=q.front->next;
free(q.front);
q.front=q.rear;
}
q.front=NULL;	//避免出现野指针 \
q.rear=NULL;
return OK;
}
清空队列Q,队列Q依旧存在:
Status ClearQueue(LinkQueue &q)
{
q.front=q.rear=NULL;
return OK;
}

 队列进行判空 :

Status QueueEmpty(LinkQueue q)
{//若队列q为空队列,则返回TRUE,否则返回FALSE
if(q.front==q.rear)
return TRUE;	//头指针和尾指针指向同一块内存,队列为空
else
return FALSE;

}
返回队列q中元素个数,即队列的长度:

Status QueueLength(LinkQueue q)
{//返回队列q中元素个数,即队列的长度
int	count=0;		//count用来记录队列中元素的个数
QueuePtr p=q.front;	//p指向结点
while(p!=q.rear)		//p所指向的结点不是尾结点
{
count++;
p=p->next;
}
return count;
}

用e返回队头元素 :

Status GetHead(LinkQueue q,int &e)
{//用e返回队头元素
QueuePtr p;
if(q.front==q.rear)
{
printf("这是一个空队列!\n");
return ERROR;
}else{
p=q.front->next;	//此时p指向头结点
e=p->data;			//将队头元素的值赋给e
return OK;
}
}
插入元素e为队列的队尾元素 :

Status EnQueue(LinkQueue &q,int e)
{//插入元素e为队列的队尾元素
QueuePtr p;
p=(QueuePtr)malloc(sizeof(QNode));;//动态生成新的结点
if(!p){
printf("新结点动态创建失败!\n");
return ERROR;
}else{
p->data=e;	//将e的值先赋给新结点
p->next=NULL;	//新结点的指针指向空
q.rear->next=p;	//原队尾结点的指针域为指向新结点
q.rear=p;		//尾指针指向新结点
return 	OK;
}
}

若队列不为空,删除Q的队头元素,并用e返回其值 :

Status DeQueue(LinkQueue &q,ElemType &e)
{//若队列不为空,删除Q的队头元素,并用e返回其值
QueuePtr p;
if(q.front==q.rear)		//此时队列为空队列
{
printf("此时队列为空!\n");
return ERROR;
}else{
p=q.front->next;	//p指向队头结点
e=p->data;		//队头结点的值赋给e
q.front->next=p->next;//头结点指向下一个结点
if(q.rear==p)	//如果删除的队尾结点
q.rear=q.front;//修改队尾指针指向头结点
free(p);
return OK;
}
}

输出队列中的元素 :

void PrintQueue(LinkQueue q)
{//输出队列中的元素
if(q.front==q.rear)
{
printf("这是一个空队列!\n");
}
q.front=q.front->next;
while(q.front!=NULL)
{
printf("%d ",q.front->data);
q.front=q.front->next;
}
printf("\n");
}

嗯下面就是在VC中的实现:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define LIST_SIZE 100
#define LISTINCREMENT 10
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -2
typedef int ElemType;
typedef int Status;
typedef struct QNode{ ElemType data; struct QNode *next; }QNode,*QueuePtr; //定义链表结点中的数据 typedef struct{ QueuePtr front; //队头指针 QueuePtr rear; //队尾指针 }LinkQueue;

//构造一个空队列Q
Status InitQueue(LinkQueue &q)
{
q.front=q.rear=(QueuePtr)malloc(sizeof(QNode)); //创建头结点,头指针指向头结点
if(!q.front) //创建失败
{
printf("构造队列失败!\n");
return ERROR;
}
q.front->next=NULL; //头结点下一个指针指向NULL,避免出现野指针
printf("构造队列成功!\n");
return OK;
}

//销毁队列Q,队列Q不存在
Status DestroyQueue(LinkQueue &q) { while(q.front) { q.rear=q.front->next; free(q.front); q.front=q.rear; } q.front=NULL; //避免出现野指针 \ q.rear=NULL; return OK; }

//清空队列Q,队列Q存在
Status ClearQueue(LinkQueue &q) { q.front=q.rear=NULL; return OK; }

//对队列进行判空
Status QueueEmpty(LinkQueue q) {//若队列q为空队列,则返回TRUE,否则返回FALSE if(q.front==q.rear) return TRUE; //头指针和尾指针指向同一块内存,队列为空 else return FALSE; }

Status QueueLength(LinkQueue q) {//返回队列q中元素个数,即队列的长度 int count=0; //count用来记录队列中元素的个数 QueuePtr p=q.front; //p指向结点 while(p!=q.rear) //p所指向的结点不是尾结点 { count++; p=p->next; } return count; }

Status GetHead(LinkQueue q,int &e) {//用e返回队头元素 QueuePtr p; if(q.front==q.rear) { printf("这是一个空队列!\n"); return ERROR; }else{ p=q.front->next; //此时p指向头结点 e=p->data; //将队头元素的值赋给e return OK; } }

Status EnQueue(LinkQueue &q,int e) {//插入元素e为队列的队尾元素 QueuePtr p; p=(QueuePtr)malloc(sizeof(QNode));;//动态生成新的结点 if(!p){ printf("新结点动态创建失败!\n"); return ERROR; }else{ p->data=e; //将e的值先赋给新结点 p->next=NULL; //新结点的指针指向空 q.rear->next=p; //原队尾结点的指针域为指向新结点 q.rear=p; //尾指针指向新结点 return OK; } }

Status DeQueue(LinkQueue &q,ElemType &e) {//若队列不为空,删除Q的队头元素,并用e返回其值 QueuePtr p; if(q.front==q.rear) //此时队列为空队列 { printf("此时队列为空!\n"); return ERROR; }else{ p=q.front->next; //p指向队头结点 e=p->data; //队头结点的值赋给e q.front->next=p->next;//头结点指向下一个结点 if(q.rear==p) //如果删除的队尾结点 q.rear=q.front;//修改队尾指针指向头结点 free(p); return OK; } }

void PrintQueue(LinkQueue q) {//输出队列中的元素 if(q.front==q.rear) { printf("这是一个空队列!\n"); } q.front=q.front->next; while(q.front!=NULL) { printf("%d ",q.front->data); q.front=q.front->next; } printf("\n"); }
int main()
{
int e;
int ch;
ElemType n;
LinkQueue q;
InitQueue(q); //构造一个空队列;
printf("******************************\n");
printf("1、队尾插入元素\n2、队头删除元素\n3、返回列头元素\n");
printf("4、返回队列中元素的个数\n5、队列进行判空\n6、清空队列元素\n");
printf("7、销毁队列\n8、输出队列元素\n9、退出操作\n");
printf("******************************\n");
printf("请选择接下来要进行的操作:");
while(scanf("%d",&ch)&&ch!=9)
{
if(ch==1){
printf(
b881
"请输入队尾插入的元素");
scanf("%d",&e);
if(EnQueue(q,e)){
printf("队尾插入元素%d成功!\n",e);
}else{
printf("操作失败!\n");
}
}
if(ch==2){
if(DeQueue(q,e)){
printf("队头删除元素%d成功!\n",e);
}else{
printf("操作失败");
}
}
if(ch==3){
if(GetHead(q,e)){
printf("队列的头元素是%d\n",e);
}else{
printf("返回队列头元素失败!\n");
}
}
if(ch==4){
printf("队列里面的元素个数有%d\n",QueueLength(q));
}
if(ch==5){
if(QueueEmpty(q))
printf("这是一个空队列!\n");
else
printf("这是一个非空队列!\n");
}
if(ch==6){
if(ClearQueue(q))
printf("队列已经清空!\n");
else
printf("操作失败!");
}
if(ch==7){
if(DestroyQueue(q))
printf("队列已经销毁!\n");
else
printf("操作失败!\n");
}
if(ch==8){
PrintQueue(q);
}
printf("请选择接下来要进行的操作:");
}
printf("退出成功!\n");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: