不读书则愚,不思考则浅;不多练则生,不巧用则钝。
一 .队列的概念:
只允许在一端插入数据操作,在另一端进行删除数据操作的特殊线性表;进行插入操作的一端称为队尾(入队列),进行删除操作的一端称为队头(出队列);队列具有 先进先出(FIFO)的特性。
二、顺序队列:
(1) 队头不动,出队列时队头后的所有元素向前移动
缺点: 操作是如果出队列比较多,要搬移大量元素,方法不可取。
(2)队头移动,出队列时队头向后移动一个位置
问题: 如果还有新元素进行入队列容易造成假溢出。
- 假溢出:顺序队列因多次入队列和出队列操作后出现的尚有存储空间但不能进行入队列操作的溢出。
- 真溢出:顺序队列的最大存储空间已经存满又要求进行入队列操作所引起的溢出。
(3)基本操作:
InitQueue ( ) : 初始化
IsEmpty ( ) : 判空
InQueue ( ) : 入队
OutQueue ( ): 出队
#include <stdio.h>
#include <windows.h>
//定义一个顺序队列
#define QUEUESIZE 100
typedef struct Squeue {
int queue[QUEUESIZE];
int front;
int rear;
}SeQueue;
//顺序队列的初始化
void InitQueue(SeQueue* S) {
S->front = S->rear = 0;
}
//判断队列是否为空
int IsEmpty(SeQueue S) {
if (S.front == S.rear) {
return 1;
}
return 0;
}
//入队操作
int InQueue(SeQueue* S, int e) {
//判断队列是否为满
if (S->rear >= QUEUESIZE) {
return 0;
}
S->queue[S->rear] = e;
++S->rear;
return 1;
}
//出队操作
int OutQueue(SeQueue* S, int* e) {
//判断队列是否为空
if (IsEmpty(*S)) {
return 0;
}
*e = S->queue[S->front];
++S->front;
return 1;
}
int main() {
SeQueue s1;
InitQueue(&s1);
printf("初始化完成\n");
printf("===================\n");
if (IsEmpty(s1)) printf("队列为空\n");
else printf("队列不为空\n");
printf("===================\n");
printf("入队 1,2,3,4,5 \n");
for (int i = 1; i < 5; ++i) {
if (!InQueue(&s1, i)) printf("入队失败!");
}
printf("===================\n");
printf("元素出队: ");
int e = 0;
for (int i = 0; i < 5; ++i) {
if (OutQueue(&s1, &e)) {
printf("%d ", e);
}
}
printf("\n");
return 0;
}
三、 循环队列:
我这里用的操作是第三种: 少用一个元素空间
循环队列的基本操作:
initLoopQueue ( ) : 初始化
lqEmpty ( ): 判空
lqFull ():判满
lqLength () : 队列长度
enterLq (): 入队
popLq (): 出队
getFrontEle (): 取队头元素
findEle () : 查找元素的位置
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 11 //初始容量
typedef int Status;
typedef int QElemType;//定义数据类型
//循环队列的顺序存储结构
typedef struct{
QElemType data[MAXSIZE];
int front;
int rear;
}loopQueue;
//初始化
loopQueue *initLoopQueue(){
loopQueue *lq = (loopQueue *)malloc(sizeof(loopQueue));
if (lq != NULL){
lq->front =0;
lq->rear = 0;
}
return lq;
}
//判队列空
Status lqEmpty(loopQueue *lq){
if (lq->front == lq->rear) return TRUE;
return FALSE;
}
//判断队列满
Status lqFull(loopQueue *lq){
if ((lq->rear+1) %MAXSIZE == lq->front) return TRUE;
return FALSE;
}
// 队列的长度
Status lqLength(loopQueue *lq){
return ((lq->rear-lq->front+MAXSIZE)%MAXSIZE);
}
//入队
Status enterLq(loopQueue *lq, QElemType e){
if (lqFull(lq)) return ERROR;
lq->data[lq->rear] = e;
lq->rear = (lq->rear+1)%MAXSIZE;
return OK;
}
//出队
Status popLq(loopQueue *lq){
if (lq->front == lq->rear) return ERROR;
printf("出队元素是:%d\n", lq->data[lq->front]);
lq->front = (lq->front+1)%MAXSIZE;
return OK;
}
//取队头数据元素
Status getFrontEle(loopQueue *lq){
if (lq->front == lq->rear) return ERROR;
printf("查看队头元素是:%d\n", lq->data[lq->front]);
return OK;
}
// 查找元素的位置
Status findEle(loopQueue *lq, QElemType flag){
int i = 0;
if (lq->front == lq->rear) return ERROR;
while (lq->front != flag){
i++;
lq->front = (lq->front +1)%MAXSIZE;
}
return i;
}
int main(void){
loopQueue * lq=NULL;
int result, e, len, flag, index;
lq = initLoopQueue(); // 初始化
printf("初始化队列完成:\n");
printf("======================\n");
printf("元素入队:\n");
scanf("%d", &e);
while (e != 0) {
result = enterLq(lq,e); // 入队
if (result == 0) printf("入队失败");
scanf("%d", &e);
}
printf("\n======================\n");
lqEmpty(lq) == 1 ? printf("为空") : printf("不为空");
printf("\n======================\n");
len = lqLength(lq); // 循环队列的长度
printf("队列的长度:%d", len);
printf("\n======================\n");
lqFull(lq) == 1 ? printf("队满") : printf("队没满");
printf("\n======================\n");
result = popLq(lq); // 出队
if (result == 0) printf("出队失败!");
printf("现在的队头元素是: %d", lq->data[lq->front]);
printf("\n======================\n");
if (!getFrontEle(lq)) printf("取出失败!"); // 查看队头数据元素
printf("======================\n");
printf("请输入要查找的元素:");
scanf("%d", &flag);
index = findEle(lq, flag);
printf("查找的元素在队列的第 %d 个", index);
printf("\n======================\n");
lq->front = 0;
while (lq->front != lq->rear) {
printf("%d\t", lq->data[lq->front]);
lq->front= (lq->front + 1)%MAXSIZE;
}
return 0;
}
四、链式队列:
链式队列: 特殊的单链表,只在单链表上进行头删尾插的操作。
- 由于是链式队列,所以先定义一个存放数据域和指针域的结构体
- 队列结构体中定义一个队头指针和队尾指针
链式基本操作:
initLinkQueue ( ) : 初始化
queuePush (): 入队
queuePop (): 出队
queueEmpty (): 判断队列是否为空
getFrontEle () : 获取队列头部元素
getRearEle () : 获取队列尾部元素
queueDestroy ( ): 销毁队列
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
typedef int Status;
typedef int QElemType;//定义数据类型
typedef struct node{
QElemType data;
struct node *next;
}qNode;
typedef struct {
qNode *front;
qNode *rear;
}linkedQueue;
// 初始化
linkedQueue *initLinkQueue(){
linkedQueue *lq = (linkedQueue*)malloc(sizeof(linkedQueue));
lq->front = lq->rear = NULL;
return lq;
}
// 入队
Status queuePush(linkedQueue *lq, QElemType e){
qNode *newNode = (qNode*)malloc(sizeof(qNode));
if (!newNode) return ERROR;
newNode->data = e;
newNode->next = NULL;
if (lq->front == NULL) { // 链队为空时
lq->front = lq->rear = newNode;
return OK;
}
lq->rear->next = newNode;
lq->rear = newNode;
return OK;
}
// 出队
Status queuePop(linkedQueue *lq, QElemType *e) {
if (lq->rear == lq->front) return ERROR;
qNode *popNode = lq->front;
lq->front = lq->front->next;
if(lq ->front == NULL){
lq ->rear = lq ->front;
}
*e = popNode->data;
free(popNode);
return OK;
}
// 判断队列是否为空
Status queueEmpty(linkedQueue *lq){
return lq->front == NULL;
}
// 获取队列头部元素
Status getFrontEle(linkedQueue *lq, QElemType *x){
if (queueEmpty(lq)) return ERROR;
*x = lq->front->data;
return OK;
}
// 获取队列尾部元素
Status getRearEle(linkedQueue *lq, QElemType *x){
if (queueEmpty(lq)) return ERROR;
*x = lq->rear->data;
return OK;
}
// 销毁队列
Status queueDestroy(linkedQueue *lq){
if (!lq) return ERROR;
while (queueEmpty(lq)){
qNode *popNode = lq->front;
lq->front = lq->front->next;
if(lq ->front == NULL){
lq ->rear = lq ->front;
}
free(popNode);
}
free(lq);
return OK;
}
int main() {
linkedQueue * lq;
QElemType *x = (QElemType *)malloc(sizeof(QElemType));
int e,result;
lq = initLinkQueue();
printf("初始化链队完成!\n");
printf("=========================\n");
printf("请输入队元素(等于 0 结束输入):\n");
scanf("%d",&e);
while (e != 0){
result = queuePush(lq, e);
if (result == 0) printf("入队失败!");
scanf("%d", &e);
}
printf("=========================\n");
result = queueEmpty(lq);
if (result == 1) printf("链队为空\n");
else printf("链队不为空 \n");
printf("=========================\n");
queuePop(lq,x);
printf("出队元素是:%d\n",*x);
printf("=========================\n");
getFrontEle(lq,x);
printf("队头元素是:%d\n", *x);
printf("=========================\n");
getRearEle(lq,x);
printf("队尾元素是:%d\n", *x);
printf("=========================\n");
if (queueDestroy(lq)) printf("链队以销毁!\n");
else printf("链队销毁失败!\n");
return 0;
}