首页 > 其他分享 >[数据结构] 队列 (C语言)

[数据结构] 队列 (C语言)

时间:2023-01-21 11:55:07浏览次数:49  
标签:队列 SqQueue LinkQueue C语言 出队 front 数据结构 rear

队列

队列基本概念

队列( queue )是一种特殊的线性表结构,只从队尾插入新的元素,并且只从队首弹出元素。一般将队尾称为 rear,队首称为 front

队列基本操作

(1)入队:从队尾 rear 插入新元素;
(2)出队:从队首 front 弹出元素。

队列的特性

队列遵循 先进先出 的原则。比如元素 1、2、3、4、5 依次入队,且中途不存在出队过元素再次入队或其他元素入队,出队顺序为 1、2、3、4、5



循环顺序队列

循环顺序队列基本概念

顺序队列是用数组实现的队列,但是由于定义的数组的空间有限,可以想象一下,当队首 front 和 队尾 rear 经过一系列操作都往后移动时,之前所使用到的空间都不会再被使用了,这造成了空间上的浪费。

所以定义顺序队列往往采用更加高效的 循环顺序队列,其基本上就是在顺序队列的基础上加了一点小小的修改。

循环顺序队列的入队操作

循环顺序队列入队操作图解

初始状态下的循环顺序队列

元素1入队

元素2、3、4、5入队

循环顺序队列入队操作代码

//队列元素入队
void Enter_SqQueue(SqQueue *Q, int e){
    if((Q->rear + 1) % MAXSIZE == Q->front){
	printf("队列已满\n");
	return;
    }
    Q->data[Q->rear] = e;               //在队尾指向的地址赋值
    Q->rear = (Q->rear + 1) % MAXSIZE;  //队尾指针进1
}


循环顺序队列的出队操作

循环顺序队列出队操作图解

元素1出队

元素2、3、4、5出队

循环顺序队列出队操作代码

//队列元素出队
void Depart_SqQueue(SqQueue *Q, int *e){
    if(IsEmpty(Q)){
	printf("队列中无元素\n");
	return;
    }
    *e = Q->data[Q->front];             //取出队首指针指向的地址元素
    Q->front = (Q->front + 1) % MAXSIZE;//队首指针进1
}

循环顺序队列中的循环示例

入队

此时队列rear虽然指向数组的最后,但循环操作可以使其重复利用之前使用的空间。

出队

类似的此时队列front指向数组的最后



循环顺序队列完整程序

源代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXSIZE 1000

typedef int Elemtype;
typedef struct SqQueue{
	
    Elemtype data[MAXSIZE];
    int front;           //队列前指针
    int rear;            //队列后指针

}SqQueue;

//初始化
void Create_SqQueue(SqQueue *Q){
    Q->front = Q->rear = 0;
}

//判断队列是否为空
bool IsEmpty(SqQueue *Q){
    return Q->front == Q->rear;
}

//求得队列长度
int SqQueue_Length(SqQueue *Q){
    return (Q->rear - Q->front + MAXSIZE) % MAXSIZE;
}

//队列元素入队
void Enter_SqQueue(SqQueue *Q, int e){
    if((Q->rear + 1) % MAXSIZE == Q->front){
	printf("队列已满\n");
	return;
    }
    Q->data[Q->rear] = e;               //在队尾指向的地址赋值
    Q->rear = (Q->rear + 1) % MAXSIZE;  //队尾指针进1
}

//队列元素出队
void Depart_SqQueue(SqQueue *Q, int *e){
    if(IsEmpty(Q)){
	printf("队列中无元素\n");
	return;
    }
    *e = Q->data[Q->front];             //取出队首指针指向的地址元素
    Q->front = (Q->front + 1) % MAXSIZE;//队首指针进1
}

//取队首
int Get_front(SqQueue *Q){
    if(IsEmpty(Q)){
	printf("队列为空\n");
	return -1;
    }
    return Q->data[Q->front];
}


int main(){
    SqQueue myQueue;
    Elemtype a[5] = {35, 30, 11, 23, 9};

    Create_SqQueue(&myQueue);
    for(int i = 0; i < 5; i++)
        Enter_SqQueue(&myQueue, a[i]);

    Elemtype e;
    Depart_SqQueue(&myQueue, &e);
    printf("出队元素: %d\n", e);

    printf("元素22入队并将所有元素出队: \n");
    Enter_SqQueue(&myQueue, 22);

    while(!IsEmpty(&myQueue)){
    	printf("%d ", Get_front(&myQueue));
    	Depart_SqQueue(&myQueue, &e);
    }

    return 0;
}

程序运行结果



链队列

链队列基本概念

链队列是链式的队列结构,其拥有一个 front 指针作为队首,一般队首 front 是不带数据的;还有一个 rear 指针作为队尾,队尾 rear 指向队列的最后一个元素。链队列的操作和链表也有一些相似之处。

链队列的入队操作

链队列入队操作图解

初始状态下的链队列

元素1入队

元素2、3入队

链队列入队操作代码

//链队列元素入队
void Enter_LinkQueue(LinkQueue *Q, int e){
    Linknode *node = (Linknode*)malloc(sizeof(Linknode));
    node->data = e;
    node->next = NULL;

    Q->rear->next = node;     //原先队列尾指针后继next指向新节点node
    Q->rear = node;           //尾指针重新指向新节点node
}

链队列的出队操作

链队列出队操作图解

元素1出队

链队列出队操作代码

当链队列只有一个元素并且将其出队时,需要特判一下,将链队列置于空队列的状态。

//链队列元素出队
void Depart_LinkQueue(LinkQueue *Q, int *e){
    if(Q->rear == Q->front) return;
    Linknode *p;
    p = Q->front->next;       //要删除的节点暂存给p
    *e = p->data;             //取出删除队头节点的数据
    Q->front->next = p->next; //队头节点的后继next直接跨过删除的节点指向其下一个节点
	
    if(Q->rear == p)          //当队列只有一个元素的情况
    	Q->rear = Q->front;   
    free(p);
}


链队列完整程序

源代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef int Elemtype;
//队列节点结构
typedef struct Linknode{

    Elemtype data;             //队列节点数据域
    struct Linknode *next;     //队列next指针域
	
}Linknode;

//链队列整体结构
typedef struct LinkQueue{

    Linknode *front;           //链队列首指针  队首指针不带数据
    Linknode *rear;            //链队列尾指针

}LinkQueue;

//初始化创建链队列
void Create_LinkQueue(LinkQueue *Q){
    Q->front = Q->rear = (Linknode*)malloc(sizeof(Linknode));
    Q->front->next == NULL;
}

//链队列元素入队
void Enter_LinkQueue(LinkQueue *Q, int e){
    Linknode *node = (Linknode*)malloc(sizeof(Linknode));
    node->data = e;
    node->next = NULL;

    Q->rear->next = node;     //原先队列尾指针后继next指向新节点node
    Q->rear = node;           //尾指针重新指向新节点node
}

//链队列元素出队
void Depart_LinkQueue(LinkQueue *Q, int *e){
    if(Q->rear == Q->front) return;
    Linknode *p;
    p = Q->front->next;       //要删除的节点暂存给p
    *e = p->data;             //取出删除队头节点的数据
    Q->front->next = p->next; //队头节点的后继next直接跨过删除的节点指向其下一个节点
	
    if(Q->rear == p)          //当队列只有一个元素的情况
    	Q->rear = Q->front;  
    
    free(p);
}

//判断是否为空
bool IsEmpty(LinkQueue *Q){
    return Q->front == Q->rear;
}

//取队首
int Front_LinkQueue(LinkQueue *Q){
    if(IsEmpty(Q)){
	printf("队列为空\n");
	return -1;
    }
    return Q->front->next->data;
}

int main(){
    LinkQueue myQueue;
    Create_LinkQueue(&myQueue);

    Enter_LinkQueue(&myQueue, 1);
    Enter_LinkQueue(&myQueue, 2);
    Enter_LinkQueue(&myQueue, 3);
    printf("当前队首元素为 %d \n", Front_LinkQueue(&myQueue));
    
    Elemtype e;
    Depart_LinkQueue(&myQueue, &e);
    printf("出队的元素为 %d \n", e);
    printf("当前队首元素为 %d \n", Front_LinkQueue(&myQueue)); 
   	
    printf("\n所有元素出队:\n");
    while(!IsEmpty(&myQueue)){
    	printf("%d ", Front_LinkQueue(&myQueue));
    	Depart_LinkQueue(&myQueue, &e);
    }

    return 0;
}

程序运行结果

标签:队列,SqQueue,LinkQueue,C语言,出队,front,数据结构,rear
From: https://www.cnblogs.com/MAKISE004/p/17063234.html

相关文章

  • 代码随想录算法训练营第十天 栈与队列 | 232.用栈实现队列 | 225. 用队列实现栈
    栈与队列栈:先进后出(叠起来的盘子Stack)队列:先进先出(现实中排队Queue)三个版本的STLHPSTL,其他STL的蓝本,开源P.J.PlaugerSTL,被VisualC++采用,不开源SGISTL,被Lin......
  • 算法经常用到的数据结构
    栈:先进后出Stack<Integer>stack=newStack<>();//推荐Deque<Integer>stack1=newArrayDeque<>();//pop()删除并返回栈顶的值//peek()返回栈顶端的值,不删类似......
  • C语言实现 vector( 动态数组) 改进版(转)
    之所以再写一封邮件缘起于我写的《C语言实现vector(动态数组)》这篇文章http://blog.csdn.net/dengxu11/article/details/5915857。原来这个是在Linux下写的,多谢troubl......
  • 数据结构 C语言版 严蔚敏 电子书 pdf
    讲解的清楚、明白, 考研必备。关注公众号:后厂村搬砖工。发送:数据结构即可    ......
  • C语言实现扫雷游戏
    前言如何利用代码实现一个扫雷游戏呢?在我们玩过的扫雷游戏里,打开游戏后看到的是一个nxn的棋盘,我们需要点击棋盘的某一位置,在最短的时间内根据点击格子出现的数字找出所有非......
  • C语言实现三子棋游戏
    什么是三子棋游戏?三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉棋、一条龙、井字棋等。游戏分为双方对战,双方依次在9宫格棋盘上摆放棋子,棋盘被占满前率先将自己的三个棋子......
  • 数据结构:树状数组 学习笔记
    树状数组基本思想树状数组是一种基于二进制拆分的思想,用来动态维护序列的前缀和的树形数据结构。在全国青少年信息学奥林匹克竞赛大纲内难度评级为6,是提高级中开始学习......
  • 动手学数据结构 -- Task02_1
    【回顾&引言】前面一章的内容大家可以感觉到我们主要是对基础知识做一个梳理,让大家了解数据分析的一些操作,主要做了数据的各个角度的观察。那么在这里,我们主要是做数据分析......
  • 数据结构课程设计[2023-01-19]
    数据结构课程设计[2023-01-19]数据结构课程设计一、课程设计要求实现指定的题目(学号最后两位%4+1),并撰写课程设计报告。独立完成,功能不完备也没关系,只要是自己做的使......
  • 进程+线程+队列爬取斗图网
    需求:爬取斗图网数据首先我们使用线程的方式,爬取前4页数据准备工作图片链接存在页面源代码中但是,界面使用了懒加载技术,真正的url在data-original中importrequ......