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