栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【数据结构】-队列的实现(有源码可自行修改实现)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【数据结构】-队列的实现(有源码可自行修改实现)

文章目录

一,什么是队列

二,循环队列

三,银行系统的代码(可直接运行)


1.什么是队列:

   队列是一种遵循某一原则(FIFO)的线性表.

 队列的分类: 顺序表示和链式表示

#defien MAXSIZE 100
typedef struct
{
    QELEMType *base;
    int  front;  //头
    int rear;   //尾巴
}Sequeue;

并在此约定,当创建空队列的时候,当front = rear = 0;

每当有新的队尾元素时,尾指针rear增 1--------删除队列头元素时候,头指针front增加 1

强调:头指针始终指向队列头元素,尾指针始终指向队列为元素的下一个位置。

当前的SIZEMAX=5,但是如果你在图4的情况下再次插入一个元素的时候就会出现“溢出”的现象,从而使数组越界程序不能运行,但是你又发现,当我的front指的是D的时候,依然图4,添加后还是会溢出,但是我的数组并没有满,那将这一称为“假溢出”。

二,循环队列

怎样解决假溢出的问题?------------------如果我是一个圆圈,我的不是可以一直用了吗,就形成了一种环装的循环列表:循环队列.

循环队列采用的处理方式是;少用一个元素的空间,当SIZEMAX=n的时候,那当n-1个元素是就显示队满了,当front和rear的指针的值相同时,就为队空,尾指针在循环里加一后若等于头指针,队满. 判断条件

队满 Q.friont==Q.rear

队满:(Q.rear+1)%SIZEMAX==Q.front

对于循环列表的初始化(目的是让head和tail为0):

CycQueue* CycQueueInit()
{
    CycQueue* q; //指针,为了指向地址
    if (q = (CycQueue*)malloc(sizeof(CycQueue)))
    {
        q->head = 0; //使其头和尾开始都为0
        q->tail = 0;
        return q;
    }else
    return NULL;
}

因为队列是由malloc函数申请的空间来保存元素的值,so,在不用的时候要进行释放

void CycQueueFree(CycQueue* q)
{
    if (q != NULL)
        free(q); //空间的释放
}

接下来考虑队列的性质-是否为空 是否已满 (为空的条件是首尾相等)

int CycQueueIsEmpty(CycQueue* q)
{
    return (q->head==q->tail); //是否为空
}

int CycQueueIsFull(CycQueue* q)
{
    return ((q->tail+1)% QUEUEMAX==q->head);//是否已满
}

那么就看入队元素,入队之前不要忘记判断,(入队尾指针加一,头指针不动)

int CycQueueIn(CycQueue* q, DATA data) //入队操作
{
    if ((q->tail+1) % QUEUEMAX==q->head)
    {
        printf("队列已满!n");
        return 0;
    }
    else {    //可添加
        q->tail = (q->tail + 1) % QUEUEMAX;
        q->data[q->tail++] = data;  //q->tail++ 通过自增一开储存新的元素
        return 1;
    }
}

既然入队了,怎么着也待出队吧,那么依旧先判断,在动头指针,不动尾指针

DATA* CycQueueOut(CycQueue* q)
{
    if (q->head == q->tail)
    {
        printf("n队列已空!n");
        return NULL;
    }
    else { //成功条件
        q->head = (q->head + 1) % QUEUEMAX; //那个求余的方法
        return &(q->data[q->head++]); //依然向后移动一,头指针始终指向头元素
    }
}

还有一个就是获取头元素,这个没有让其出队,不用头指针向后进行移动一位.

DATA* CycQueuePeek(CycQueue* q)
{
    if (q->head==q->tail)
    {
        printf("n队列为空!n");
        return NULL;
    }
    else {
        return &(q->data[(q->head+1)%QUEUEMAX]);
    }
    
}

有没有感觉忘记点什么? 我的长度呢? 在这呢

int CycQueueLen(CycQueue* q)
{
    
    int n;
    n = q->tail - q->head;
    if (n < 0)
        n = QUEUEMAX + n;
    return n/2;
}

上述是对于整个循环队列的分析,那么加上main函数我们可以跑一下.

三,银行系统的代码(可直接运行)

这个是CycQueue.h

#define QUEUEMAX  15
typedef struct
{
	long time;
	int num;
}DATA;
typedef struct
{
	DATA data[QUEUEMAX];
	int head;
	int tail;
}CycQueue;
CycQueue* CycQueueInit(); //进行初始化
void CycQueueFree(CycQueue* q); //释放空间
int CycQueueIsEmpty(CycQueue* q);//空的
int CycQueueIsFull(CycQueue* q); //满的
int CycQueueLen(CycQueue* q);//长度
int CycQueueIn(CycQueue* q,DATA data);//入队操作
DATA* CycQueueOut(CycQueue* q); //出队
DATA* CycQueuePeek(CycQueue* q);//获取头文件

CycQueue(函数的定义).c

#include "SqeQueue.h"
#include 
#include  //对应的malloc分配空间
CycQueue* CycQueueInit()
{
    CycQueue* q; //指针,为了指向地址
    if (q = (CycQueue*)malloc(sizeof(CycQueue)))
    {
        q->head = 0; //使其头和尾开始都为0
        q->tail = 0;
        return q;
    }else
    return NULL;
}
void CycQueueFree(CycQueue* q)
{
    if (q != NULL)
        free(q); //空间的释放
}

int CycQueueIsEmpty(CycQueue* q)
{
    return (q->head==q->tail);
}

int CycQueueIsFull(CycQueue* q)
{
    return ((q->tail+1)% QUEUEMAX==q->head);
}


int CycQueueIn(CycQueue* q, DATA data) //入队操作
{
    if ((q->tail+1) % QUEUEMAX==q->head)
    {
        printf("队列已满!n");
        return 0;
    }
    else {
        q->tail = (q->tail + 1) % QUEUEMAX;
        q->data[q->tail++] = data;
        return 1;
    }
}

DATA* CycQueueOut(CycQueue* q)
{
    if (q->head == q->tail)
    {
        printf("n队列已空!n");
        return NULL;
    }
    else {
        q->head = (q->head + 1) % QUEUEMAX; //那个求余的方法
        return &(q->data[q->head++]);
    }
}

int CycQueueLen(CycQueue* q)
{
    
    int n;
    n = q->tail - q->head;
    if (n < 0)
        n = QUEUEMAX + n;
    return n/2;
}


DATA* CycQueuePeek(CycQueue* q)
{
    if (q->head==q->tail)
    {
        printf("n队列为空!n");
        return NULL;
    }
    else {
        return &(q->data[(q->head+1)%QUEUEMAX]);
    }
    
}

main函数的代码

#include "SqeQueue.h"
#include 
#include 
#include 
int num;
void add(CycQueue* q)
{
	DATA data;
	if (!CycQueueIsFull(q))
	{
		data.num = num++;
		data.time = time(NULL);
		CycQueueIn(q, data);
	}
	else
		printf("排队的太多,请稍后在排队!n");
}
void  next(CycQueue* q)
{
	DATA* data;
	if (!CycQueueIsFull(q))
	{
		data = CycQueueOut(q);
		printf("n正在为编号为%d的顾客办理业务!n", data->num);
	}
	if (!CycQueueIsFull(q))
	{
		data = CycQueuePeek(q);
		printf("请编号为%d的顾客准备,马上将为您办理业务!n", data->num);
	}
}
int main()
{
	CycQueue* queue1;
	int i, n,choose;
	int select;
	num = 0;
	queue1 = CycQueueInit(); //初始化队列
	if (queue1 == NULL)
	{
		printf("创建队列出错!n");
		getchar();
		return 0;
	}
	do {
		
		printf("n1.新的顾客:n");
		printf("n2.next onen");
		printf("n0.outn");
		printf("n请选择具体的操作:");
		//fflush(stdin); //键盘的输入
		scanf_s("%d", &choose);
		select = choose;
		switch(select)
		{
		case 1:add(queue1); 
			printf("n现在共有%d为顾客在等候!n", CycQueueLen(queue1)); break;
		case 2:next(queue1);
			printf("n现在共有%d为顾客在等候!n", CycQueueLen(queue1)); break;
		case 0: break;
		}

	} while (select != 0);
	CycQueueFree(queue1);
	getchar();
	return 0;
}

运行的截图

 上方的图片理解来自于:【数据结构】队列(顺序队列、循环队列、链队列)_Jacky_Feng的博客-CSDN博客

我的栈也有自己的想法若有兴趣,可以一看:【数据结构】-栈的基本操作(源码可以直接运行)_i-阿松!的博客-CSDN博客

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1022163.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号