数据结构学习--队列
队列与栈类似,也同样基于线性表.
他的特点是:先进先出.
如我们日常说的队列一样,后来的人后走,先来的人先走.下面用图片形象的展示一下:
队列有队头和队尾,队头是先进入的元素,队尾是后进入的元素
他同样有两种存储模式,分别实现一下:
链式:
/************************************************************************* > File Name: 队列的实现.c > Author: zhanghaoran > Mail: chilumanxi@gmail.com > Created Time: 2015年07月22日 星期三 20时35分35秒 ************************************************************************/ #include <stdio.h> #include <string.h> #include <stdlib.h> #define OVERFLOW -2 #define OK 1 #define ERROR 0 //链表 //队列元素的数据 typedef struct cQueue{ int data; struct cQueue *next; }QNode, *QueuePtr; typedef struct{ QueuePtr front; QueuePtr rear; }LinkQueue; int InitQueue(LinkQueue &Q){ Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode)); if(Q.front == NULL) exit(OVERFLOW); Q.front -> next = NULL; return OK; } int DestroyQueue(LinkQueue &Q){ while(Q.front != NULL){ Q.rear = Q.front -> next; free(Q.front); Q.front = Q.rear; } return OK; } int EnQueue(LinkQueue &Q, int e){ QueuePtr q; q = (QueuePtr)malloc(sizeof(QNode)); q -> data = e; q -> next = NULL; Q.rear -> next = q; Q.rear = q; return OK; } int DeQueue(LinkQueue &Q){ QueuePtr q; int e; if(Q.front == Q.rear) return ERROR; q = Q.front -> next; e = q -> data; Q.front -> next = q -> next; if(Q.rear == q) Q.rear = Q.front; free(q); return e; } int ClearQueue(LinkQueue &Q){ QueuePtr q; q = Q.front; while(q -> next != NULL){ Q.front = Q.front -> next; free(q); q = Q.front; } Q.rear = NULL; return OK; } int QueueEmpty(LinkQueue Q){ if(Q.front -> next == NULL) return OK; else return ERROR; } int GetHead(LinkQueue Q){ if(!QueueEmpty(Q)) return Q.front -> next -> data; else return ERROR; } int main(void){ LinkQueue Queue; int a[8] = {3, 8, 5, 17, 9, 30, 15, 22}; int i; InitQueue(Queue); for(i = 0; i < 8; i ++){ EnQueue(Queue, a[i]); } printf("%d ", DeQueue(Queue)); printf("%d ", DeQueue(Queue)); EnQueue(Queue, 68); printf("%d ", GetHead(Queue)); printf("%d ", GetHead(Queue)); while(!QueueEmpty(Queue)){ printf("%d ", DeQueue(Queue)); } printf(" "); ClearQueue(Queue); return 0; }
当然需要注意一点就是出队的时候如果恰好出队的是队尾元素的话,那就要让队尾元素指向头结点,否则队尾指针将会丢失.
好的,下面我们给出一个经常使用的数据结构的数组实现:
#include <stdio.h> #include <stdlib.h> #define OVERFLOW -2 #define OK 1 #define ERROR 0 #define INIT_QUEUE_SIZE 100 int Queue[INIT_QUEUE_SIZE]; int flag = 0; int front = 0, rear = 0; int len = 0; void CreatQueue(){ if(flag == 1) printf("队列已经存在。"); else { for(int i = 0; i < 6; i ++){ printf("输入初始化的第%d个数", i); scanf("%d", &(Queue[i])); len ++; } rear = 5; flag = 1; } } void EnQueue(){ if( !flag ) printf("当前无队列,请创建队列!\n"); else { printf("请输入入队列的元素:"); scanf("%d", &Queue[rear + 1]); rear ++; len ++; } } void DeQueue(){ if( !flag ) printf("当前无队列,请创建队列!\n"); else { printf("出队列的元素%d", Queue[front]); front ++; len --; printf("出队列后的队列为:\n"); for(int i = front; i <= rear; i ++) printf("%d", Queue[i]); } } void print(){ printf("\n当前队列为:"); for(int i = front; i < len; i ++) printf("%d ",Queue[i]); }
在数组的情况下,我们只需要定义两个整型作为队尾和队头就可以了,非常的简便,在ACM以及各种算法题目中,这种形式是最长用的,比如BFS.详情使用见我的博客的另外两篇文章:http://blog.csdn.net/chilumanxi/article/details/46363361
http://blog.csdn.net/chilumanxi/article/details/46317013
当然,队列也有自己的循环队列.在初始化建空队列的时候,我们令front = rear = 0,每当插入新的队列尾元素的时候,尾指针加一.每当删除头元素的时候,头指针加一,这样一来,头指针就可以始终指向第最先入队的元素.
那么问题最后就是如果队列已满的话,尾指针的下一位置就是头指针.下面写一下循环队列:
//-----------------循环队列---队列的顺序存储结构------- #define MAXQSIZE 100 //最大队列长度 #define Status int typedef struct{ QElemType *base; //初始化的动态分配存储空间 int front; //头指针,若队列不空,指向队列头元素 int rear; //尾指针,若队列不空,指向队列尾元素的下一个元素 }SqQueue; //-----------------循环队列的基本操作的算法描述--------- Status InitQueue(SqQueue &Q){ //构造一个空队列Q Q.base = (QElemType *)malloc(MAXQSIZE * sizeof(QElemType)); if(!Q.base) exit(OVERFLOW); Q.front = Q.rear = 0; return OK; } int QueueLength(SqQueue Q){ //返回Q的元素个数,也就是队列的长度 return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE //循环队列,所以求余 } Status EnQueue(SqQueue &Q, QElemType e){ //输入元素e为Q的新的队尾元素 if((Q.rear + 1) % MAXQSIZE == Q.front) return ERROR; //队列满 Q.base[Q.rear] = e; Q.rear = (Q.rear + 1) % MAXQSIZE; return OK; } Status DeQueue(SqQueue &Q, QElemType &e){ //若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERROR if(Q.front == Q.rear) return ERROR; e = Q.base[Q.front]; Q.front = (Q.front + 1) % MAXQSIZE; return OK; }