C语言实现队列

队列:

  1. 先进先出(First In First Out,FIFO):这是队列的核心特点。就像排队买票,先排队的人先买到票。例如,向队列中依次加入元素 1、2、3,那么取出的顺序将是 1、2、3。
  2. 操作受限:队列只允许在一端进行插入(称为入队,enqueue)操作,在另一端进行删除(称为出队,dequeue)操作。插入端通常称为队尾,删除端通常称为队头。
  3. 存储方式:队列可以使用数组或链表来实现。使用数组实现时,可能需要处理循环队列以充分利用存储空间;使用链表实现则相对灵活,但会有额外的指针操作开销。
  4. 应用场景广泛
    • 例如在计算机系统中,打印任务通常按照提交的先后顺序排队处理,这就是一个队列的应用。
    • 在网络数据包的传输中,数据包也可能在缓冲区中以队列的形式等待处理。
  5. 可预测性:由于遵循先进先出原则,队列中元素的处理顺序是可预测的。

下面是最基本的一种实现方式

cpp 复制代码
#include<stdio.h>
#include<stdlib.h>

typedef struct QueueDemo{
	int arr[10];
	int flag=0;
}Queue;
Queue xx;
void init(){
	xx.flag=0;
}
void put(int x){
	printf("存入数据%d\n",x);
	xx.arr[xx.flag]=x;
	xx.flag++;
}
int get(){
	int k;
	int w;
	w=xx.arr[0];
	printf("取出数据%d\n",w);
	for( k=0;k<xx.flag-1;k++){
		xx.arr[k]=xx.arr[k+1];
	}
	xx.flag--;	
}
void leftshow(){
	int i;
	for( i=0;i<xx.flag;i++){
		printf("栈内数据%d\n",xx.arr[i]);
		//TODO
	}
}
int main(int argc,char *argv[]){
	put(1);put(2);put(3);put(4);put(5);put(6);put(7);put(8);
		get();
	leftshow();
	return 0;
}

循环队列的实现

cpp 复制代码
#include<stdio.h>
#include<stdlib.h>

typedef struct QueueDemo{
	int arr[10];
	int putindex;
	int getindex;
}Queue;
Queue xx;
void init(){
	xx.putindex=0;
	xx.getindex=0;
}
void put(int x){
	printf("存入数据%d\n",x);
	xx.arr[xx.putindex%10]=x;
	xx.putindex++;
}
int get(){
	printf("取出数据%d\n",xx.arr[xx.getindex%10]);
		xx.getindex++;
}
void leftshow(){
	int i;
	for( i=xx.getindex;i<xx.putindex;i++){
		printf("栈内数据%d\n",xx.arr[i%10]);
		//TODO
	}
}
int main(int argc,char *argv[]){
	put(1);put(2);put(3);put(4);put(5);put(6);put(7);put(8);put(9);
	get();	get();get();get();
	leftshow();
	return 0;
}

但是这个代码还有缺陷,就是如果超过了循环队列的内存,那么就会出现错误,于是我们改进,给他加上判空或者队列已满的操作。

cpp 复制代码
#include<stdio.h>
#include<stdlib.h>

typedef struct QueueDemo{
	int arr[10];
	int putindex;
	int getindex;
}Queue;
Queue xx;
void init(){
	xx.putindex=0;
	xx.getindex=0;
}
void put(int x){
	if(xx.putindex-xx.getindex==10){
		printf("已经满了,存储失败\n");
		return ;
	}
	printf("存入数据%d\n",x);
	xx.arr[xx.putindex%10]=x;
	xx.putindex++;
}
int get(){
	if(xx.putindex==xx.getindex){
		printf("取空了\n");
		return -1;
	}
	printf("取出数据%d\n",xx.arr[xx.getindex%10]);
		xx.getindex++;
}
void leftshow(){
	int i;
	for( i=xx.getindex;i<xx.putindex;i++){
		printf("栈内数据%d\n",xx.arr[i%10]);
		//TODO
	}
}
int main(int argc,char *argv[]){
	put(1);put(2);put(3);put(4);put(5);put(6);put(7);put(8);put(9);
	put(1);put(2);put(3);
	get();	get();get();get();get();	get();get();get();get();	get();get();get();
	put(1);put(2);put(3);
	leftshow();
	return 0;
}

欧克,我们已经加上了判断队列空与满的情况了。那我们可以更灵活一点,实现队列的扩容。

cpp 复制代码
#include<stdio.h>
#include<stdlib.h>

typedef struct QueueDemo{
	int* arr;
	int putindex;
	int getindex;
}Queue;
Queue xx;
int arrsize=10;
void init(){
	xx.putindex=0;
	xx.getindex=0;
	xx.arr=(int*)malloc(sizeof(int) * arrsize);
}
void put(int x){
	if(xx.putindex-xx.getindex==arrsize){
		int* arrnew=(int*)malloc(sizeof(int)*arrsize*2);
		int arrnewsize=arrsize*2;
		int i;
		for(i=xx.getindex;i<xx.putindex;i++){
			arrnew[i%arrnewsize]=xx.arr[i%arrsize];
		}
		free(xx.arr);
		xx.arr=arrnew;
		arrsize=arrnewsize;
		printf("已经满了,正在扩容\n");  // 增加扩容提示
	}
	printf("存入数据%d\n",x);
	xx.arr[xx.putindex%arrsize]=x;
	xx.putindex++;
}
int get(){
	if(xx.putindex==xx.getindex){
		printf("取空了\n");
		return -1;
	}
	printf("取出数据%d\n",xx.arr[xx.getindex%arrsize]);
		xx.getindex++;
}
void leftshow(){
	int i;
	for( i=xx.getindex;i<xx.putindex;i++){
		printf("栈内数据%d\n",xx.arr[i%arrsize]);
	}
}
int main(int argc,char *argv[]){
	init();
	put(1);put(2);
	get();
	leftshow();
	return 0;
}

这就是实现了队列的扩容操作,不会出现内存满的情况了。

相关推荐
xlq223225 小时前
22.多态(上)
开发语言·c++·算法
666HZ6665 小时前
C语言——高精度加法
c语言·开发语言·算法
sweet丶5 小时前
iOS MMKV原理整理总结:比UserDefaults快100倍的存储方案是如何炼成的?
算法·架构
星释5 小时前
Rust 练习册 100:音乐音阶生成器
开发语言·后端·rust
风生u6 小时前
go进阶语法
开发语言·后端·golang
666HZ6666 小时前
C语言——黑店
c语言·开发语言
Gomiko6 小时前
JavaScript基础(八):函数
开发语言·javascript·ecmascript
云里雾里!6 小时前
力扣 209. 长度最小的子数组:滑动窗口解法完整解析
数据结构·算法·leetcode
〝七夜5696 小时前
JVM内存结构
java·开发语言·jvm
初级炼丹师(爱说实话版)6 小时前
JAVA泛型作用域与静态方法泛型使用笔记
java·开发语言·笔记