数据结构5-队列

队列

队列(queue)是一种先进先出(First In First Out FIFO)的线性表。在表一端(表尾)插入,在另一端(表头)删除
在这里插入图片描述
相关术语:

  • 队列(Queue)是仅在表尾进行插入操作,在表头进行删除操作的线性表。
  • 表尾即an端,称为队尾;
  • 表头即a1端,称为队头。
  • 它是一种先进先出(FIFO)的线性表。
    例如:队列Q=(a1,a2,a3,……,an-1,an)
  • 插入元素称为人队;删除元素称为出队。
  • 队列的存储结构为链队或顺序队(常用循环顺序队)

队列的总结:

1.定义:只能在表的一端进行插入运算在表的另一端进行删除操作运算的线性表(头删尾插)

2.逻辑结构:同线性表一样栈元素具有线性关系即前驱后继关系(一对一)

3.存储结构:顺序队和链队均可,循环顺序队更常见

4.运算规则:只能在队首和队尾运算,且访问结点时依照后进先出的原则(FIFO)

5.实现方式:关键是掌握入队和出队操作具体实现依顺序队和链队的不同而不同

栈和队列的区别:栈是吃进去的东西吐出来(嘴【栈顶】)队列是吃进去的东西拉出来(队首和队尾)


队列的基本操作:

  1. 队QQ的初始化操作。
    void InitQueue(QQ);
  2. 销毁队列SS。
    void DestroyQueue(QQ);
  3. 清空队列。
    void Clear(QQ);
  4. 元素入队,返回值:0-失败;1-成功。
    int InQueue(QQ ee);
  5. 元素出队,返回值:0-失败;1-成功。
    int OutQueue(QQ ee);
  6. 判断队列是否为空,返回值:1-空,0-非空或失败。
    int IsEmpty(QQ);
  7. 判断队列是否已满,返回值:1-已满,0-未满或失败。
    int IsFull(QQ);
  8. 求队列的长度,返回队列QQ元素的个数。
    int Length(QQ);
  9. 获取队头元素,返回值:0-失败;1-成功。
    int GetHead(QQee);

队列的顺序存储

顺序存储为了最大化使用空间采用循环队列。
循环队列
方案一:
在这里插入图片描述

/*
 * 程序名:seqqueue3.c,此程序演示循环队列的数组实现,队尾指针指向队尾元素,没有length的辅助变量。
*/
#include <stdio.h>
#include <string.h>

#define MAXSIZE 10       // 循环队列的最大长度,最多可以存放MAXSIZE-1个元素。

typedef int ElemType;    // 自定义循环队列的数据元素为整数。

typedef struct
{
  ElemType data[MAXSIZE];   // 用数组存储循环队列中的元素。
  int front;                // 队列的头指针。
  int rear;                 // 队列的尾指针,指向队尾元素。
}SeqQueue,*PSeqQueue;

// 循环队列QQ的初始化操作。
void InitQueue(PSeqQueue QQ);                     

// 销毁循环队列QQ。
void DestroyQueue(PSeqQueue QQ);

// 元素入队,返回值:0-失败;1-成功。
int InQueue(PSeqQueue QQ, ElemType *ee);

// 元素出队,返回值:0-失败;1-成功。
int OutQueue(PSeqQueue QQ, ElemType *ee);

// 求循环队列的长度,返回值:>=0-队列QQ元素的个数。
int  Length(PSeqQueue QQ);                   

// 清空循环队列。
void Clear(PSeqQueue QQ);                    

// 判断循环队列是否为空,返回值:1-空,0-非空或失败。
int  IsEmpty(PSeqQueue QQ);                    

// 判断循环队列是否已满,返回值:1-已满,0-未满或失败。
int IsFull(PSeqQueue QQ);

// 打印循环队列中全部的元素。
void PrintQueue(PSeqQueue QQ);                    

// 获取队头元素,返回值:0-失败;1-成功。
// 只查看队头元素的值,元素不出队。
int GetHead(PSeqQueue QQ, ElemType *ee);

int main()
{
  SeqQueue QQ;     // 创建循环队列。

  InitQueue(&QQ);  // 初始化循环队列。

  ElemType ee;     // 创建一个数据元素。

  printf("元素(1、2、3、4、5、6、7、8、9、10、11)入队。\n");
  ee=1;  InQueue(&QQ, &ee);
  ee=2;  InQueue(&QQ, &ee);
  ee=3;  InQueue(&QQ, &ee);
  ee=4;  InQueue(&QQ, &ee);
  ee=5;  InQueue(&QQ, &ee);
  ee=6;  InQueue(&QQ, &ee);
  ee=7;  InQueue(&QQ, &ee);
  ee=8;  InQueue(&QQ, &ee);
  ee=9;  InQueue(&QQ, &ee);
  ee=10; InQueue(&QQ, &ee);
  ee=11; InQueue(&QQ, &ee);

  printf("队列的长度是%d\n",Length(&QQ));
  PrintQueue(&QQ);

  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);

  printf("队列的长度是%d\n",Length(&QQ));
  PrintQueue(&QQ);

  printf("元素(11、12、13、14、15)入队。\n");
  ee=11;  InQueue(&QQ, &ee);
  ee=12;  InQueue(&QQ, &ee);
  ee=13;  InQueue(&QQ, &ee);
  ee=14;  InQueue(&QQ, &ee);
  ee=15;  InQueue(&QQ, &ee);

  printf("队列的长度是%d\n",Length(&QQ));

  PrintQueue(&QQ);

  // 只查看队头元素的值,元素不出队。
  if (GetHead(&QQ,&ee)==1)  printf("队头的元素值为%d\n",ee);

  return 0;
}

// 初始化循环队列
void InitQueue(PSeqQueue QQ)
{
  Clear(QQ); // 清空循环队列。
}

// 清空循环队列。
void Clear(PSeqQueue QQ)
{
  if (QQ == NULL) return;   // 检查空指针。

  QQ->front=0;
  QQ->rear=MAXSIZE-1;    // xxxx
  memset(QQ->data,0,sizeof(ElemType)*MAXSIZE);  // 数组元素清零。
}

// 求循环队列的长度,返回值:>=0-队列QQ元素的个数。
int Length(PSeqQueue QQ)
{
  if (QQ == NULL) return 0;  // 检查空指针。

  // xxxxxxx
  return (QQ->rear-QQ->front+1+MAXSIZE)%MAXSIZE;
}

// 销毁循环队列QQ。
void DestroyQueue(PSeqQueue QQ)
{
  // 静态循环队列无需释放内存,不需要销毁操作。

  Clear(QQ); // 清空循环队列。

  return;
}

// 判断循环队列是否为空,返回值:1-空,0-非空或失败。
int IsEmpty(PSeqQueue QQ)
{
  if (QQ == NULL) return 0;   // 检查空指针。

  // xxxxx
  if ( ((QQ->rear+1)%MAXSIZE) == QQ->front ) return 1;

  return 0;
}

// 判断循环队列是否已满,返回值:1-已满,0-未满或失败。
int IsFull(PSeqQueue QQ)
{
  if (QQ == NULL) return 0;   // 检查空指针。

  // xxxxx
  if ( ((QQ->rear+2)%MAXSIZE) == QQ->front ) return 1;

  return 0;
}

// 元素入队,返回值:0-失败;1-成功。
int InQueue(PSeqQueue QQ, ElemType *ee)
{
  if ( (QQ == NULL) || (ee == NULL) ) return 0;   // 检查空指针。

  if (IsFull(QQ) == 1)
  {
    printf("循环队列已满,不能插入。\n"); return 0;
  }

  // xxxx 先移动队尾指针,然后再插入数据。
  QQ->rear=(QQ->rear+1)%MAXSIZE;  // 队尾指针后移。

  memcpy(&QQ->data[QQ->rear],ee,sizeof(ElemType));  // 用数组的下标访问。
  // memcpy(QQ->data+QQ->rear,ee,sizeof(ElemType));    // 采用指针运算也可以。

  return 1;
}

// 打印循环队列中全部的元素。
void PrintQueue(PSeqQueue QQ)
{
  if (QQ == NULL) return;   // 检查空指针。

  if (IsEmpty(QQ) == 1) { printf("队列为空。\n"); return; }

  int kk,qlen=Length(QQ);
  for (kk = 0; kk < qlen; kk++)
  {
    // 用数组的下标访问。
    printf("data[%d],value=%d\n",(QQ->front+kk)%MAXSIZE,QQ->data[(QQ->front+kk)%MAXSIZE]);     
   
    // 采用指针运算也可以。
    // printf("data[%d],value=%d\n",(QQ->front+kk)%MAXSIZE,*(QQ->data+(QQ->front+kk)%MAXSIZE));
  }
}

// 元素出队,返回值:0-失败;1-成功。
int OutQueue(PSeqQueue QQ, ElemType *ee)
{
  if ( (QQ == NULL) || (ee == NULL) ) return 0;   // 检查空指针。

  if (IsEmpty(QQ) == 1) { printf("队列为空。\n"); return 0; }

  memcpy(ee,&QQ->data[QQ->front],sizeof(ElemType));  // 用数组的下标访问。
  // memcpy(ee,QQ->data+QQ->front,sizeof(ElemType));    // 采用指针运算也可以。

  QQ->front=(QQ->front+1)%MAXSIZE;  // 队列头指针后移。

  return 1;
}

// 获取队头元素,返回值:0-失败;1-成功。
// 只查看队头元素的值,元素不出队。
int GetHead(PSeqQueue QQ, ElemType *ee)
{
  if ( (QQ == NULL) || (ee == NULL) ) return 0;   // 检查空指针。

  if (IsEmpty(QQ) == 1) { printf("队列为空。\n"); return 0; }

  memcpy(ee,&QQ->data[QQ->front],sizeof(ElemType));  // 用数组的下标访问。
  // memcpy(ee,QQ->data+QQ->front,sizeof(ElemType));    // 采用指针运算也可以。

  return 1;
}

方案二:
在这里插入图片描述

/*
 * 程序名:seqqueue1.c,此程序演示循环队列的数组实现,队尾指针指向队尾的下一个元素,没有length的辅助变量。
*/
#include <stdio.h>
#include <string.h>

#define MAXSIZE 10       // 循环队列的最大长度,最多可以存放MAXSIZE-1个元素。

typedef int ElemType;    // 自定义循环队列的数据元素为整数。

typedef struct
{
  ElemType data[MAXSIZE];   // 用数组存储循环队列中的元素。
  int front;                // 队列的头指针。
  int rear;                 // 队列的尾指针,指向队尾的下一个元素。
}SeqQueue,*PSeqQueue;

// 循环队列QQ的初始化操作。
void InitQueue(PSeqQueue QQ);                     

// 销毁循环队列QQ。
void DestroyQueue(PSeqQueue QQ);

// 元素入队,返回值:0-失败;1-成功。
int InQueue(PSeqQueue QQ, ElemType *ee);

// 元素出队,返回值:0-失败;1-成功。
int OutQueue(PSeqQueue QQ, ElemType *ee);

// 求循环队列的长度,返回值:>=0-队列QQ元素的个数。
int  Length(PSeqQueue QQ);                   

// 清空循环队列。
void Clear(PSeqQueue QQ);                    

// 判断循环队列是否为空,返回值:1-空,0-非空或失败。
int  IsEmpty(PSeqQueue QQ);                    

// 判断循环队列是否已满,返回值:1-已满,0-未满或失败。
int IsFull(PSeqQueue QQ);

// 打印循环队列中全部的元素。
void PrintQueue(PSeqQueue QQ);                    

// 获取队头元素,返回值:0-失败;1-成功。
// 只查看队头元素的值,元素不出队。
int GetHead(PSeqQueue QQ, ElemType *ee);

int main()
{
  SeqQueue QQ;     // 创建循环队列。

  InitQueue(&QQ);  // 初始化循环队列。

  ElemType ee;     // 创建一个数据元素。

  printf("元素(1、2、3、4、5、6、7、8、9、10、11)入队。\n");
  ee=1;  InQueue(&QQ, &ee);
  ee=2;  InQueue(&QQ, &ee);
  ee=3;  InQueue(&QQ, &ee);
  ee=4;  InQueue(&QQ, &ee);
  ee=5;  InQueue(&QQ, &ee);
  ee=6;  InQueue(&QQ, &ee);
  ee=7;  InQueue(&QQ, &ee);
  ee=8;  InQueue(&QQ, &ee);
  ee=9;  InQueue(&QQ, &ee);
  ee=10; InQueue(&QQ, &ee);
  ee=11; InQueue(&QQ, &ee);

  printf("队列的长度是%d\n",Length(&QQ));
  PrintQueue(&QQ);

  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);

  printf("队列的长度是%d\n",Length(&QQ));
  PrintQueue(&QQ);

  printf("元素(11、12、13、14、15)入队。\n");
  ee=11;  InQueue(&QQ, &ee);
  ee=12;  InQueue(&QQ, &ee);
  ee=13;  InQueue(&QQ, &ee);
  ee=14;  InQueue(&QQ, &ee);
  ee=15;  InQueue(&QQ, &ee);

  printf("队列的长度是%d\n",Length(&QQ));

  PrintQueue(&QQ);

  // 只查看队头元素的值,元素不出队。
  if (GetHead(&QQ,&ee)==1)  printf("队头的元素值为%d\n",ee);

  return 0;
}

// 初始化循环队列
void InitQueue(PSeqQueue QQ)
{
  Clear(QQ); // 清空循环队列。
}

// 清空循环队列。
void Clear(PSeqQueue QQ)
{
  if (QQ == NULL) return;  // 检查空指针。

  QQ->front=QQ->rear=0;
  memset(QQ->data,0,sizeof(ElemType)*MAXSIZE);  // 数组元素清零。
}

// 求循环队列的长度,返回值:>=0-队列QQ元素的个数。
int Length(PSeqQueue QQ)
{
  if (QQ == NULL) return 0;  // 检查空指针。

  return (QQ->rear-QQ->front+MAXSIZE)%MAXSIZE;
}

// 销毁循环队列QQ。
void DestroyQueue(PSeqQueue QQ)
{
  // 静态循环队列无需释放内存,不需要销毁操作。

  Clear(QQ); // 清空循环队列。

  return;
}

// 判断循环队列是否为空,返回值:1-空,0-非空或失败。
int IsEmpty(PSeqQueue QQ)
{
  if (QQ == NULL) return 0;    // 检查空指针。

  if (QQ->front == QQ->rear) return 1;

  return 0;
}

// 判断循环队列是否已满,返回值:1-已满,0-未满或失败。
int IsFull(PSeqQueue QQ)
{
  if (QQ == NULL) return 0;   // 检查空指针。

  if ( ((QQ->rear+1)%MAXSIZE) == QQ->front) return 1;

  return 0;
}

// 元素入队,返回值:0-失败;1-成功。
int InQueue(PSeqQueue QQ, ElemType *ee)
{
  if ( (QQ == NULL) || (ee == NULL) ) return 0;   // 检查空指针。

  if (IsFull(QQ) == 1)
  {
    printf("循环队列已满,不能插入。\n"); return 0;
  }

  memcpy(&QQ->data[QQ->rear],ee,sizeof(ElemType));  // 用数组的下标访问。
  // memcpy(QQ->data+QQ->rear,ee,sizeof(ElemType));    // 采用指针运算也可以。

  QQ->rear=(QQ->rear+1)%MAXSIZE;  // 队尾指针后移。

  return 1;
}

// 打印循环队列中全部的元素。
void PrintQueue(PSeqQueue QQ)
{
  if (QQ == NULL) return;   // 检查空指针。

  if (IsEmpty(QQ) == 1) { printf("队列为空。\n"); return; }

  int kk,qlen=Length(QQ);
  for (kk = 0; kk < qlen; kk++)
  {
    // 用数组的下标访问。
    printf("data[%d],value=%d\n",(QQ->front+kk)%MAXSIZE,QQ->data[(QQ->front+kk)%MAXSIZE]);     
   
    // 采用指针运算也可以。
    // printf("data[%d],value=%d\n",(QQ->front+kk)%MAXSIZE,*(QQ->data+(QQ->front+kk)%MAXSIZE));
  }
}

// 元素出队,返回值:0-失败;1-成功。
int OutQueue(PSeqQueue QQ, ElemType *ee)
{
  if ( (QQ == NULL) || (ee == NULL) ) return 0;   // 检查空指针。

  if (IsEmpty(QQ) == 1) { printf("队列为空。\n"); return 0; }

  memcpy(ee,&QQ->data[QQ->front],sizeof(ElemType));  // 用数组的下标访问。
  // memcpy(ee,QQ->data+QQ->front,sizeof(ElemType));    // 采用指针运算也可以。

  QQ->front=(QQ->front+1)%MAXSIZE;  // 队列头指针后移。

  return 1;
}

// 获取队头元素,返回值:0-失败;1-成功。
// 只查看队头元素的值,元素不出队。
int GetHead(PSeqQueue QQ, ElemType *ee)
{
  if ( (QQ == NULL) || (ee == NULL) ) return 0;   // 检查空指针。

  if (IsEmpty(QQ) == 1) { printf("队列为空。\n"); return 0; }

  memcpy(ee,&QQ->data[QQ->front],sizeof(ElemType));  // 用数组的下标访问。
  // memcpy(ee,QQ->data+QQ->front,sizeof(ElemType));    // 采用指针运算也可以。

  return 1;
}

方案三:
在这里插入图片描述

//SeqQueue.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//函数结果状态代码 
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define MAXSIZE 10
//Status 是函数的类型,其值是函数结果状态代码
typedef int Status;
// 循环队列的最大长度,最多可以存放MAXSIZE个元素。

typedef int ElemType;    // 自定义循环队列的数据元素为整数。

typedef struct
{
	ElemType data[MAXSIZE];   // 用数组存储循环队列中的元素。
	int front;                // 队列的头指针。
	int rear;                 // 队列的尾指针,指向队尾的下一个元素。
	int length;               // 队列的实际长度。    // xxx
}SeqQueue, *PSeqQueue;

// 循环队列QQ的初始化操作。
void InitQueue(PSeqQueue QQ);

// 销毁循环队列QQ。
void DestroyQueue(PSeqQueue QQ);

// 元素入队,返回值:0-失败;1-成功。
int InQueue(PSeqQueue QQ, ElemType *ee);

// 元素出队,返回值:0-失败;1-成功。
int OutQueue(PSeqQueue QQ, ElemType *ee);

// 求循环队列的长度,返回值:>=0-队列QQ元素的个数。
int  Length(PSeqQueue QQ);

// 清空循环队列。
void Clear(PSeqQueue QQ);

// 判断循环队列是否为空,返回值:1-空,0-非空或失败。
int  IsEmpty(PSeqQueue QQ);

// 判断循环队列是否已满,返回值:1-已满,0-未满或失败。
int IsFull(PSeqQueue QQ);

// 打印循环队列中全部的元素。
void PrintQueue(PSeqQueue QQ);

// 获取队头元素,返回值:0-失败;1-成功。
// 只查看队头元素的值,元素不出队。
int GetHead(PSeqQueue QQ, ElemType *ee);

  


//SeqQueue.cpp
#include "SeqQueue.h"
//循环队列的数组实现,队尾指针指向队尾的下一个元素,增加了length的辅助变量。
// 循环队列QQ的初始化操作。
void InitQueue(PSeqQueue QQ)
{
	if (QQ == NULL )
	{
		return ;
	}

		QQ->front = QQ->rear = QQ->length = 0;
		memset(QQ->data, 0, sizeof(ElemType)*MAXSIZE);  // 数组元素清零。
}

// 销毁循环队列QQ。
void DestroyQueue(PSeqQueue QQ)
{
	if (QQ)
	{
		QQ->front = QQ->rear = QQ->length = 0;
		memset(QQ->data, 0, sizeof(ElemType)*MAXSIZE);  // 数组元素清零。
		delete QQ;
	}
	return;
}

// 元素入队,返回值:0-失败;1-成功。
int InQueue(PSeqQueue QQ, ElemType *ee)
{
	if (QQ==NULL ||  ee == NULL )
	{
		return ERROR;
	}
	if (IsFull(QQ))
	{
		printf("循环队列已满,不能插入。\n"); return 0;
	}
	memcpy(&QQ->data[QQ->rear], ee, sizeof(ElemType));  // 用数组的下标访问。
	QQ->rear = (QQ->rear + 1) % MAXSIZE;
	QQ->length++;
	return OK;
}

// 元素出队,返回值:0-失败;1-成功。
int OutQueue(PSeqQueue QQ, ElemType *ee)
{
	if (QQ == NULL || ee == NULL)
	{
		return ERROR;
	}
	//memset(ee,&QQ->data[QQ->front], sizeof(ElemType));
	memcpy(ee, &QQ->data[QQ->front], sizeof(ElemType));  // 用数组的下标访问。
	QQ->front = (QQ->front + 1) % MAXSIZE;
	QQ->length--;
	return OK;
}

// 求循环队列的长度,返回值:>=0-队列QQ元素的个数。
int  Length(PSeqQueue QQ)
{
	if (QQ == NULL )return ERROR;
	return QQ->length;
}

// 清空循环队列。
void Clear(PSeqQueue QQ)
{
	if (QQ == NULL)return;
	QQ->front = QQ->rear = QQ->length = 0;
	memset(QQ->data, 0, sizeof(ElemType)*MAXSIZE);  // 数组元素清零。
}

// 判断循环队列是否为空,返回值:1-空,0-非空或失败。
int  IsEmpty(PSeqQueue QQ)
{
	if (QQ == NULL) return ERROR;
	if (QQ->length == 0)
	{
		return OK;
	}
	else
	{
		return 0;
	}
}

// 判断循环队列是否已满,返回值:1-已满,0-未满或失败。
int IsFull(PSeqQueue QQ)
{
	if (QQ == NULL) return ERROR;
	if (QQ->length < MAXSIZE)
	{
		return 0;
	}
	else
	{
		return OK;
	}
}

// 打印循环队列中全部的元素。
void PrintQueue(PSeqQueue QQ)
{
	if (QQ == NULL) return ;
	if (IsEmpty(QQ) == 1) { printf("队列为空。\n"); return; }
	for (int i = 0; i < QQ->length ; i++)
	{
		//printf("data[%d],value=%d\n", i, QQ->data[(QQ->front+i )% MAXSIZE]);
		// 用数组的下标访问。
		printf("data[%d],value=%d\n", /*(QQ->front + i) % MAXSIZE*/i, QQ->data[(QQ->front + i) % MAXSIZE]);
		//printf("data[%d],value=%d\n",(QQ->front+i)%MAXSIZE,QQ->data[(QQ->front+i)%MAXSIZE]);   
	}
}

// 获取队头元素,返回值:0-失败;1-成功。
// 只查看队头元素的值,元素不出队。
int GetHead(PSeqQueue QQ, ElemType *ee)
{
	if (QQ == NULL || ee == NULL) return ERROR;
	memcpy(ee, &QQ->data[QQ->front], sizeof ElemType);
	return OK;
}

void test01()
{
	SeqQueue QQ;     // 创建循环队列。

	InitQueue(&QQ);  // 初始化循环队列。

	ElemType ee;     // 创建一个数据元素。
	  
	printf("元素(1、2、3、4、5、6、7、8、9、10、11)入队。\n");
	ee = 1;  InQueue(&QQ, &ee);
	ee = 2;  InQueue(&QQ, &ee);
	ee = 3;  InQueue(&QQ, &ee);
	ee = 4;  InQueue(&QQ, &ee);
	ee = 5;  InQueue(&QQ, &ee);
	ee = 6;  InQueue(&QQ, &ee);
	ee = 7;  InQueue(&QQ, &ee);
	ee = 8;  InQueue(&QQ, &ee);
	ee = 9;  InQueue(&QQ, &ee);
	ee = 10; InQueue(&QQ, &ee);
	ee = 11; InQueue(&QQ, &ee);

	printf("队列的长度是%d\n", Length(&QQ));
	PrintQueue(&QQ);

	if (OutQueue(&QQ, &ee) == 1)  printf("出队的元素值为%d\n", ee);
	if (OutQueue(&QQ, &ee) == 1)  printf("出队的元素值为%d\n", ee);
	if (OutQueue(&QQ, &ee) == 1)  printf("出队的元素值为%d\n", ee);
	if (OutQueue(&QQ, &ee) == 1)  printf("出队的元素值为%d\n", ee);
	if (OutQueue(&QQ, &ee) == 1)  printf("出队的元素值为%d\n", ee);
	if (OutQueue(&QQ, &ee) == 1)  printf("出队的元素值为%d\n", ee);
	if (OutQueue(&QQ, &ee) == 1)  printf("出队的元素值为%d\n", ee);

	printf("队列的长度是%d\n", Length(&QQ));
	PrintQueue(&QQ);

	printf("元素(11、12、13、14、15)入队。\n");
	ee = 11;  InQueue(&QQ, &ee);
	ee = 12;  InQueue(&QQ, &ee);
	ee = 13;  InQueue(&QQ, &ee);
	ee = 14;  InQueue(&QQ, &ee);
	ee = 15;  InQueue(&QQ, &ee);

	printf("队列的长度是%d\n", Length(&QQ));

	PrintQueue(&QQ);

	// 只查看队头元素的值,元素不出队。
	if (GetHead(&QQ, &ee) == 1)  printf("队头的元素值为%d\n", ee);

}
int main()
{
	test01();//test
	system("pause");
	return EXIT_SUCCESS;	
}

方案四:
尾指针指向队尾元素,增加length变量。

/*
 * 程序名:seqqueue4.c,此程序演示循环队列的数组实现,队尾指针指向队尾元素,增加了length的辅助变量。
*/
#include <stdio.h>
#include <string.h>

#define MAXSIZE 10       // 循环队列的最大长度,最多可以存放MAXSIZE个元素。

typedef int ElemType;    // 自定义循环队列的数据元素为整数。

typedef struct
{
  ElemType data[MAXSIZE];   // 用数组存储循环队列中的元素。
  int front;                // 队列的头指针。
  int rear;                 // 队列的尾指针,指向队尾元素。
  int length;               // 队列的实际长度。    // xxx
}SeqQueue,*PSeqQueue;

// 循环队列QQ的初始化操作。
void InitQueue(PSeqQueue QQ);                     

// 销毁循环队列QQ。
void DestroyQueue(PSeqQueue QQ);

// 元素入队,返回值:0-失败;1-成功。
int InQueue(PSeqQueue QQ, ElemType *ee);

// 元素出队,返回值:0-失败;1-成功。
int OutQueue(PSeqQueue QQ, ElemType *ee);

// 求循环队列的长度,返回值:>=0-队列QQ元素的个数。
int  Length(PSeqQueue QQ);                   

// 清空循环队列。
void Clear(PSeqQueue QQ);                    

// 判断循环队列是否为空,返回值:1-空,0-非空或失败。
int  IsEmpty(PSeqQueue QQ);                    

// 判断循环队列是否已满,返回值:1-已满,0-未满或失败。
int IsFull(PSeqQueue QQ);

// 打印循环队列中全部的元素。
void PrintQueue(PSeqQueue QQ);                    

// 获取队头元素,返回值:0-失败;1-成功。
// 只查看队头元素的值,元素不出队。
int GetHead(PSeqQueue QQ, ElemType *ee);

int main()
{
  SeqQueue QQ;     // 创建循环队列。

  InitQueue(&QQ);  // 初始化循环队列。

  ElemType ee;     // 创建一个数据元素。

  printf("元素(1、2、3、4、5、6、7、8、9、10、11)入队。\n");
  ee=1;  InQueue(&QQ, &ee);
  ee=2;  InQueue(&QQ, &ee);
  ee=3;  InQueue(&QQ, &ee);
  ee=4;  InQueue(&QQ, &ee);
  ee=5;  InQueue(&QQ, &ee);
  ee=6;  InQueue(&QQ, &ee);
  ee=7;  InQueue(&QQ, &ee);
  ee=8;  InQueue(&QQ, &ee);
  ee=9;  InQueue(&QQ, &ee);
  ee=10; InQueue(&QQ, &ee);
  ee=11; InQueue(&QQ, &ee);

  printf("队列的长度是%d\n",Length(&QQ));
  PrintQueue(&QQ);

  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);
  if (OutQueue(&QQ,&ee)==1)  printf("出队的元素值为%d\n",ee);

  printf("队列的长度是%d\n",Length(&QQ));
  PrintQueue(&QQ);

  printf("元素(11、12、13、14、15)入队。\n");
  ee=11;  InQueue(&QQ, &ee);
  ee=12;  InQueue(&QQ, &ee);
  ee=13;  InQueue(&QQ, &ee);
  ee=14;  InQueue(&QQ, &ee);
  ee=15;  InQueue(&QQ, &ee);

  printf("队列的长度是%d\n",Length(&QQ));

  PrintQueue(&QQ);

  // 只查看队头元素的值,元素不出队。
  if (GetHead(&QQ,&ee)==1)  printf("队头的元素值为%d\n",ee);

  return 0;
}

// 初始化循环队列
void InitQueue(PSeqQueue QQ)
{
  Clear(QQ); // 清空循环队列。
}

// 清空循环队列。
void Clear(PSeqQueue QQ)
{
  if (QQ == NULL) return;  // 检查空指针。

  QQ->front=0;
  QQ->rear=MAXSIZE-1;    // xxxx
  QQ->length=0;
  memset(QQ->data,0,sizeof(ElemType)*MAXSIZE);  // 数组元素清零。
}

// 求循环队列的长度,返回值:>=0-队列QQ元素的个数。
int Length(PSeqQueue QQ)
{
  if (QQ == NULL) return 0;  // 检查空指针。

  return QQ->length;    // xxx
}

// 销毁循环队列QQ。
void DestroyQueue(PSeqQueue QQ)
{
  // 静态循环队列无需释放内存,不需要销毁操作。

  Clear(QQ); // 清空循环队列。

  return;
}

// 判断循环队列是否为空,返回值:1-空,0-非空或失败。
int IsEmpty(PSeqQueue QQ)
{
  if (QQ == NULL) return 0;   // 检查空指针。

  // if (QQ->front == QQ->rear) return 1;  

  if (QQ->length == 0) return 1;    // xxx

  return 0;
}

// 判断循环队列是否已满,返回值:1-已满,0-未满或失败。
int IsFull(PSeqQueue QQ)
{
  if (QQ == NULL) return 0;   // 检查空指针。

  // if ( ((QQ->rear+1)%MAXSIZE) == QQ->front) return 1;
  if (QQ->length == MAXSIZE) return 1;    // xxx

  return 0;
}

// 元素入队,返回值:0-失败;1-成功。
int InQueue(PSeqQueue QQ, ElemType *ee)
{
  if ( (QQ == NULL) || (ee == NULL) ) return 0;   // 检查空指针。

  if (IsFull(QQ) == 1)
  {
    printf("循环队列已满,不能插入。\n"); return 0;
  }

  // xxxx 先移动队尾指针,然后再插入数据。
  QQ->rear=(QQ->rear+1)%MAXSIZE;  // 队尾指针后移。

  memcpy(&QQ->data[QQ->rear],ee,sizeof(ElemType));  // 用数组的下标访问。
  // memcpy(QQ->data+QQ->rear,ee,sizeof(ElemType));    // 采用指针运算也可以。

  QQ->length++;    // xxx

  return 1;
}

// 打印循环队列中全部的元素。
void PrintQueue(PSeqQueue QQ)
{
  if (QQ == NULL) return;   // 检查空指针。

  if (IsEmpty(QQ) == 1) { printf("队列为空。\n"); return; }

  int kk,qlen=Length(QQ);
  for (kk = 0; kk < qlen; kk++)
  {
    // 用数组的下标访问。
    printf("data[%d],value=%d\n",(QQ->front+kk)%MAXSIZE,QQ->data[(QQ->front+kk)%MAXSIZE]);     
   
    // 采用指针运算也可以。
    // printf("data[%d],value=%d\n",(QQ->front+kk)%MAXSIZE,*(QQ->data+(QQ->front+kk)%MAXSIZE));
  }
}

// 元素出队,返回值:0-失败;1-成功。
int OutQueue(PSeqQueue QQ, ElemType *ee)
{
  if ( (QQ == NULL) || (ee == NULL) ) return 0;   // 检查空指针。

  if (IsEmpty(QQ) == 1) { printf("队列为空。\n"); return 0; }

  memcpy(ee,&QQ->data[QQ->front],sizeof(ElemType));  // 用数组的下标访问。
  // memcpy(ee,QQ->data+QQ->front,sizeof(ElemType));    // 采用指针运算也可以。

  QQ->front=(QQ->front+1)%MAXSIZE;  // 队列头指针后移。

  QQ->length--;    // xxx

  return 1;
}

// 获取队头元素,返回值:0-失败;1-成功。
// 只查看队头元素的值,元素不出队。
int GetHead(PSeqQueue QQ, ElemType *ee)
{
  if ( (QQ == NULL) || (ee == NULL) ) return 0;   // 检查空指针。

  if (IsEmpty(QQ) == 1) { printf("队列为空。\n"); return 0; }

  memcpy(ee,&QQ->data[QQ->front],sizeof(ElemType));  // 用数组的下标访问。
  // memcpy(ee,QQ->data+QQ->front,sizeof(ElemType));    // 采用指针运算也可以。

  return 1;
}

队列的链式存储

只讨论带头节点的链式存储队列
在这里插入图片描述

只能采用链尾入队,链头出队。
双端队列,不常用
在这里插入图片描述

//Linkqueue.h
#pragma once
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//函数结果状态代码 
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
//Status 是函数的类型,其值是函数结果状态代码
typedef int Status;


typedef int ElemType;    // 自定义循环队列的数据元素为整数。
typedef struct LNode
{
	ElemType data;         // 存储队列中的元素。
	struct LNode *next;    // next指针。
}LNode;

typedef struct
{
	LNode *front, *rear;     // 队列的头指针和尾指针。
}LinkQueue, *PLinkQueue;

// 队列QQ的初始化操作。
int InitQueue(PLinkQueue QQ);

// 销毁队列QQ。
void DestroyQueue(PLinkQueue QQ);

// 清空队列。
void Clear(PLinkQueue QQ);

// 元素入队,返回值:0-失败;1-成功。
int InQueue(PLinkQueue QQ, ElemType *ee);

// 打印队列中全部的元素。
void PrintQueue(PLinkQueue QQ);

// 求队列的长度,返回值:>=0-队列QQ元素的个数。
int  Length(PLinkQueue QQ);

// 判断队列是否已满,链式队列不存在队满的说法。
int IsFull(PLinkQueue QQ);

// 判断队列是否为空,返回值:1-空,0-非空或失败。
int  IsEmpty(PLinkQueue QQ);

// 元素出队,返回值:0-失败;1-成功。
int OutQueue(PLinkQueue QQ, ElemType *ee);

// 获取队头元素,返回值:0-失败;1-成功。
// 只查看队头元素的值,元素不出队。
int GetHead(PLinkQueue QQ, ElemType *ee);




//


//Linkqueue.cpp
#include "LinkQueue.h"

// 队列QQ的初始化操作。
int InitQueue(PLinkQueue QQ)
{
	if (QQ == NULL)return ERROR;
	LNode *s = new LNode;
	s->next = NULL;
	QQ->front =QQ->rear =  s;
	return OK;
}

// 销毁队列QQ。
void DestroyQueue(PLinkQueue QQ)
{
	if (QQ == NULL)return;
	LNode *p = QQ->front;
	LNode *q ;
	while (p)
	{
		q = p->next;
		delete p;
		p = q;
	}
	QQ->front = QQ->rear = NULL;  // 防止野指针。
	return;
}

// 清空队列。
void Clear(PLinkQueue QQ)
{
	if (QQ == NULL)return;
	LNode *p = QQ->front->next;
	LNode *q;
	while (p)
	{
		q = p->next;
		delete p;
		p = q;
	}
	QQ->rear = QQ->front;
	QQ->front->next = NULL;
	
}

// 元素入队,返回值:0-失败;1-成功。
int InQueue(PLinkQueue QQ, ElemType *ee)
{
	if (QQ == NULL || *ee == NULL)return ERROR;
	if (QQ->front ==  NULL)
	{
		printf("队列未初始化\n");
	}

	LNode *s = new LNode;
	if (s == NULL) return 0;  // 内存不足,返回失败
	memcpy(&s->data, ee, sizeof(ElemType));
	s->next = NULL;

	QQ->rear->next = s;
	QQ->rear = s;
	return OK;

}

// 打印队列中全部的元素。
void PrintQueue(PLinkQueue QQ)
{
	if (QQ == NULL)return;
	if (QQ->front == NULL)
	{
		printf("队列未初始化\n");
	}
	LNode *p = QQ->front->next;
	while (p)
	{
		printf("%-3d", p->data);  // 如果元素ee为结构体,这行代码要修改。
		p = p->next;

	}
	printf("\n");
}

// 求队列的长度,返回值:>=0-队列QQ元素的个数。
int  Length(PLinkQueue QQ)
{
	if (QQ == NULL)return ERROR;
	if (QQ->front == NULL)
	{
		return 0;
	}
	int n = 0;
	LNode *p = QQ->front->next;
	while (p)
	{
		++n;
		p = p->next;
	}
	return n;
}

// 判断队列是否为空,返回值:1-空,0-非空或失败。
int  IsEmpty(PLinkQueue QQ)
{
	if (QQ == NULL)return ERROR;
	if (QQ->front == NULL)
	{
		printf("队列未初始化\n");
		return ERROR;
	}
	if (QQ->front->next == NULL)
	{
		printf("队列为空\n");
		return OK;
	}
	return ERROR;
}

// 元素出队,返回值:0-失败;1-成功。
int OutQueue(PLinkQueue QQ, ElemType *ee)
{
	if (QQ == NULL || *ee == NULL)return ERROR;
	if (QQ->front == NULL)
	{
		printf("队列未初始化\n");
	}
	if (IsEmpty(QQ) == 1) { printf("队列为空。\n"); return 0; }
	LNode * p = QQ->front->next;
	memcpy(ee, &p->data, sizeof ElemType);
	QQ->front->next = p->next;
	if (QQ->rear == p) QQ->rear = QQ->front;
	delete p;
	return OK;

}

// 获取队头元素,返回值:0-失败;1-成功。
// 只查看队头元素的值,元素不出队。
int GetHead(PLinkQueue QQ, ElemType *ee)
{
	if (QQ == NULL || *ee == NULL)return ERROR;
	if (QQ->front == NULL)
	{
		printf("队列未初始化\n");
	}
	if (IsEmpty(QQ) == 1) { printf("队列为空。\n"); return 0; }
	memcpy(ee, &QQ->front->next->data, sizeof ElemType);
	return OK;
}



void test01()
{
	LinkQueue QQ;     // 创建队列。

	memset(&QQ, 0, sizeof(LinkQueue));

	InitQueue(&QQ);  // 初始化队列。

	ElemType ee;     // 创建一个数据元素。

	printf("元素(1、2、3、4、5、6、7、8、9、10)入队。\n");
	ee = 1;  InQueue(&QQ, &ee);
	ee = 2;  InQueue(&QQ, &ee);
	ee = 3;  InQueue(&QQ, &ee);
	ee = 4;  InQueue(&QQ, &ee);
	ee = 5;  InQueue(&QQ, &ee);
	ee = 6;  InQueue(&QQ, &ee);
	ee = 7;  InQueue(&QQ, &ee);
	ee = 8;  InQueue(&QQ, &ee);
	ee = 9;  InQueue(&QQ, &ee);
	ee = 10; InQueue(&QQ, &ee);

	printf("队列的长度是%d\n", Length(&QQ));

	PrintQueue(&QQ);

	if (OutQueue(&QQ, &ee) == 1)  printf("出队的元素值为%d\n", ee);
	if (OutQueue(&QQ, &ee) == 1)  printf("出队的元素值为%d\n", ee);
	if (OutQueue(&QQ, &ee) == 1)  printf("出队的元素值为%d\n", ee);
	if (OutQueue(&QQ, &ee) == 1)  printf("出队的元素值为%d\n", ee);
	if (OutQueue(&QQ, &ee) == 1)  printf("出队的元素值为%d\n", ee);
	if (OutQueue(&QQ, &ee) == 1)  printf("出队的元素值为%d\n", ee);
	if (OutQueue(&QQ, &ee) == 1)  printf("出队的元素值为%d\n", ee);

	printf("队列的长度是%d\n", Length(&QQ));
	PrintQueue(&QQ);

	printf("元素(11、12、13、14、15)入队。\n");
	ee = 11;  InQueue(&QQ, &ee);
	ee = 12;  InQueue(&QQ, &ee);
	ee = 13;  InQueue(&QQ, &ee);
	ee = 14;  InQueue(&QQ, &ee);
	ee = 15;  InQueue(&QQ, &ee);

	printf("队列的长度是%d\n", Length(&QQ));

	PrintQueue(&QQ);

	// 只查看队头元素的值,元素不出队。
	if (GetHead(&QQ, &ee) == 1)  printf("队头的元素值为%d\n", ee);

	DestroyQueue(&QQ); // 销毁队列QQ。

}

int main()
{
	test01();
	system("pause");
	return EXIT_SUCCESS;
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值