C_栈和队列(ADT)-队列的非循环(带头指针)顺序表示和实现

来源:互联网 发布:百姓网发帖软件 编辑:程序博客网 时间:2024/05/22 00:45

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


顺序队列一次性要分配大量保证够用的空间,效率较高,因为是基于数组的,长度也是固定的。可以实现变长,但是一般代价较高。

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




出列元素时不移动元素,只改变队头元素的位置

优点:带头指针非循环队列,在出队元素时,只改变头指针的位置,不移动元素,可以简化操作,节约时间

缺点:队列的每个存储空间自始自终只能存储一个队列元素。即使这个队列元素出列后,存储空间浪费较大


队列的定义:

struct SqQueue2{QElemType *base;//初始化的动态分配内存空间int front;//头指针,若队列不空,指向队列的头元素int rear;//尾指针, 若队列不空,指向队列尾元素的下一个位置int queuesize;//当前分配的存储容量(以sizeof(QElemType)为单位) };


基本操作的函数定义:

/*操作结果:构造一个空队列Q*/void InitQueue(SqQueue2 &Q)/*初始条件:队列Q存在*//*操作结果:销毁队列Q,Q不再存在*/void DestroyQueue(SqQueue2 &Q)/*初始条件:队列Q存在*/ /*操作结果:将Q清为空队列*/Status ClearQueue(SqQueue2 &Q)/*初始条件:队列Q存在*//*操作结果:若队列为空队列,则返回TRUE,否则返回FALSE*/Status QueueEmpty(SqQueue2 Q)/*初始条件:队列Q存在*//*操作结果:若队列不为空,则用e返回Q的队头元素,并返回OK,否则返回FALSE*/Status GetHead(SqQueue2 Q,QElemType &e)/*初始条件:队列Q存在*//*操作结果:返回队列的长度*/int QueueLength(SqQueue2 Q)/*初始条件:队列Q存在*//*操作结果:插入元素e为Q的新的队尾元素*/void EnQueue(SqQueue2 &Q,QElemType e)/*初始条件:队列Q存在*//*操作结果:若队列不为空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERROR*/Status DeQueue(SqQueue2 &Q,QElemType &e)/*初始条件:队列Q存在*//*操作结果:从队头到队尾依次对队列中每个元素调用函数vi()*/void QueueTraverse(SqQueue2 Q,void(*vi)(QElemType))


下面是函数的实现


构造一个空队列Q

/*操作结果:构造一个空队列Q*/void InitQueue(SqQueue2 &Q){Q.base=(QElemType*)malloc(QUEUE_INIT_SIZE*sizeof(QElemType));if(!Q.base){printf("构造空队列失败!操作退出!\n");exit(0);}else{Q.front=Q.rear=0;Q.queuesize=QUEUE_INIT_SIZE;}}


销毁队列Q

/*初始条件:队列Q存在*//*操作结果:销毁队列Q,Q不再存在*/void DestroyQueue(SqQueue2 &Q){if(Q.base)free(Q.base);Q.base=NULL;Q.front=Q.rear=Q.queuesize=0;}

将Q清为空队列

/*初始条件:队列Q存在*/ /*操作结果:将Q清为空队列*/Status ClearQueue(SqQueue2 &Q){Q.front=Q.rear=0;return OK;}

队队列进行判空

/*初始条件:队列Q存在*//*操作结果:若队列为空队列,则返回TRUE,否则返回FALSE*/Status QueueEmpty(SqQueue2 Q){if(Q.front==Q.rear)//队列为空的标志return TRUE;elsereturn FALSE; } 

返回队头元素

/*初始条件:队列Q存在*//*操作结果:若队列不为空,则用e返回Q的队头元素,并返回OK,否则返回FALSE*/Status GetHead(SqQueue2 Q,QElemType &e){if(Q.front==Q.rear)//队列空return ERROR;e=Q.base[Q.front];return OK; } 

返回队列长度

/*初始条件:队列Q存在*//*操作结果:返回队列的长度*/int QueueLength(SqQueue2 Q){return (Q.rear-Q.front);}

插入新的队尾元素

/*初始条件:队列Q存在*//*操作结果:插入元素e为Q的新的队尾元素*/void EnQueue(SqQueue2 &Q,QElemType e){if(Q.rear==Q.queuesize){//队列满,增加存储单元 Q.base=(QElemType*)realloc(Q.base,(Q.queuesize+QUEUE_INIT_SIZE)*sizeof(QElemType)); if(!Q.base)//增加单元失败exit(0);}Q.base[Q.rear++]=e; }

删除队列的队头元素

/*初始条件:队列Q存在*//*操作结果:若队列不为空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERROR*/Status DeQueue(SqQueue2 &Q,QElemType &e){if(Q.front==Q.rear)//队列空return ERROR;e=Q.base[Q.front++];return OK; } 

正序遍历队列

/*初始条件:队列Q存在*//*操作结果:从队头到队尾依次对队列中每个元素调用函数vi()*/void QueueTraverse(SqQueue2 Q,void(*vi)(QElemType)){int i=Q.front;while(i!=Q.rear)vi(Q.base[i++]);printf("\n");}



嗯下面就是在VC中的测试:

#include<stdio.h>#include<stdlib.h>#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0#define QUEUE_INIT_SIZE 10//队列存储空间的初始化分配量#define QUEUE_INCREMENT 2//队列存储空间的分配增量typedef int QElemType;typedef int Status;struct SqQueue2{QElemType *base;//初始化的动态分配内存空间int front;//头指针,若队列不空,指向队列的头元素int rear;//尾指针, 若队列不空,指向队列尾元素的下一个位置int queuesize;//当前分配的存储容量(以sizeof(QElemType)为单位) };void vi(QElemType e){printf("%d \n",e);}void print(QElemType i){printf("%d ",i);}/*操作结果:构造一个空队列Q*/void InitQueue(SqQueue2 &Q){Q.base=(QElemType*)malloc(QUEUE_INIT_SIZE*sizeof(QElemType));if(!Q.base){printf("构造空队列失败!操作退出!\n");exit(0);}else{Q.front=Q.rear=0;Q.queuesize=QUEUE_INIT_SIZE;}}/*初始条件:队列Q存在*//*操作结果:销毁队列Q,Q不再存在*/void DestroyQueue(SqQueue2 &Q){if(Q.base)free(Q.base);Q.base=NULL;Q.front=Q.rear=Q.queuesize=0;}/*初始条件:队列Q存在*/ /*操作结果:将Q清为空队列*/Status ClearQueue(SqQueue2 &Q){Q.front=Q.rear=0;return OK;}/*初始条件:队列Q存在*//*操作结果:若队列为空队列,则返回TRUE,否则返回FALSE*/Status QueueEmpty(SqQueue2 Q){if(Q.front==Q.rear)//队列为空的标志return TRUE;elsereturn FALSE; } /*初始条件:队列Q存在*//*操作结果:若队列不为空,则用e返回Q的队头元素,并返回OK,否则返回FALSE*/Status GetHead(SqQueue2 Q,QElemType &e){if(Q.front==Q.rear)//队列空return ERROR;e=Q.base[Q.front];return OK; } /*初始条件:队列Q存在*//*操作结果:返回队列的长度*/int QueueLength(SqQueue2 Q){return (Q.rear-Q.front);}/*初始条件:队列Q存在*//*操作结果:插入元素e为Q的新的队尾元素*/void EnQueue(SqQueue2 &Q,QElemType e){if(Q.rear==Q.queuesize){//队列满,增加存储单元 Q.base=(QElemType*)realloc(Q.base,(Q.queuesize+QUEUE_INIT_SIZE)*sizeof(QElemType)); if(!Q.base)//增加单元失败exit(0);}Q.base[Q.rear++]=e; }/*初始条件:队列Q存在*//*操作结果:若队列不为空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERROR*/Status DeQueue(SqQueue2 &Q,QElemType &e){if(Q.front==Q.rear)//队列空return ERROR;e=Q.base[Q.front++];return OK; } /*初始条件:队列Q存在*//*操作结果:从队头到队尾依次对队列中每个元素调用函数vi()*/void QueueTraverse(SqQueue2 Q,void(*vi)(QElemType)){int i=Q.front;while(i!=Q.rear)vi(Q.base[i++]);printf("\n");}int main(){int i;int n;int ch;QElemType k;SqQueue2 Q;InitQueue(Q);printf("成功构造非循环队列Q!\n");printf("请输入队列中初始存在的个数:");scanf("%d",&n);printf("请依次输入数据元素:\n");for(i=1;i<=n;i++){scanf("%d",&k);EnQueue(Q,k);//依次入队k个元素 }printf("****************************\n");printf("1、增加元素\n2、判空队列\n3、队列长度\n");printf("4、队头元素\n5、队头出列\n6、清空队列\n");printf("7、打印队列\n8、销毁队列\n0、退出操作\n"); printf("****************************\n");printf("请选择要进行的操作:");while(scanf("%d",&ch)&&ch!=0){if(ch==1){printf("请输入要进队的元素:");scanf("%d",&k);EnQueue(Q,k);printf("%d元素成功进入队头!\n");}if(ch==2){if(QueueEmpty(Q))printf("这是一个空队列!\n");elseprintf("这不是一个空队列!\n"); }if(ch==3){printf("队列的长度为:%d\n",QueueLength(Q));}if(ch==4){int d;if(GetHead(Q,d))printf("队头元素是%d\n",d);elseprintf("这是一个空队列!\n");}if(ch==5){int d;if(DeQueue(Q,d))printf("队头元素%d成功出列!\n",DeQueue(Q,d));elseprintf("操作失败!\n");}if(ch==6){if(ClearQueue(Q))printf("队列成功清空!\n");}if(ch==7){printf("队列中的元素为:");QueueTraverse(Q,print);}if(ch==8){DestroyQueue(Q);printf("队列成功销毁,操作退出!\n");exit(0);} printf("请选择要进行的操作:");}printf("成功退出操作!\n");return 0;}



原创粉丝点击