目录
1、队列的概念
队列是仅限在一端(表尾/队尾)进行插入,在另一端(表头/队头)进行删除的线性表。又称先进先出的线性表。先进先出可以想象成火车过隧道,火车头先进隧道就会先出隧道。
2、链队列
2、1入队
栈有两种存储表示方法,分别称为顺序队列和链队列。
●利用链表来模拟队列(链队列):
队列的插入操作叫做入队,它是将数据元素从队尾进行插入的过程。
//-------队列的链式存储结构-----------
typedef int DataTpye
struct QueueNode;
struct QueueNode {
DataTpye data; //数据域
struct QueueNode *next; //指针域
};
//------初始化--------
struct Queue{
struct QueueNode *head,*tail; //队首队尾指针
int size; //队列长度
};
//--------入队---------
void QueueEnqueue(struct Queue *que,DataType dt)
{ //这里的意思呢,是要将值 dt 插入到队列 que 的队尾位置。
sturct QueueNode *vtx = (struct QueueNode *)malloc (sizeof(struct QueueNode));
//创建一个值为dt的队列结点vtx
vtx -> data = dt;
vtx -> next = NULL;
if(que -> tail){ //判断队尾是否为空,如果不为空,即为队列不为空,将vtx 作为队尾元素的后继即可
que -> tail -> next = vxt;
}else{
que -> tail = vxt; //如果为空,那么说明队列为空,将队首元素置为vtx即可。
}
que->tail = vtx;
++que ->size;
}
2、2出队
队列的删除操作叫做出队,它是将队首元素进行删除的过程。
//----------出队------------
//意思是将 队列que的队首进行删除
void QueueDequeue(struct Queue* que)
{
struct QueueNode *temp = que -> head; //将队首元素缓存到temp中
que ->head =temp ->next; //将que 的队首变成 temp的后继
free(temp); //释放temp的内
--que -> size; //队列长度减一
if(que -> size == 0)
{
que -> tail = NULL; //如果此时队列为空,也就是队列只有一个元素已经被删掉了,把队尾置为空就行
}
}
2、3取队头元素
DataType QueueGetFront(struct Queue* que)
{
return que -> head -> data;
}
3、顺序队列
3、1入队
//---------队列的顺序存储结构-------
#define MAXQSIZE 100 //队列可能达到的最大长度
typedef struct
{
QElemType *base; //存储空间的基地址
int front; //头指针
int rear; //尾指针
}SqQueue;
//------初始化--------
Status InitQueue (SqQueue &Q) //构造一个空队列
{
Q.base = new QElemType[MXQSIZE]; //为队列分配一个最大容量为MAXQSIZE的数组空间
if(!Q.base) exit(OVERFLOW); //如果存储分配失败
Q.front = Q.rear =0; //将头指针和尾指针置为0,队列为空
return OK;
}
//-----求队列的长度-------
int QueueLenght(SqQueue Q)
{
return (Q.rear - Q.front + MAXQSIZE) %MAXQSIZE;
//返回Q的元素个数,即队列的长度
}
//-------入队--------
Status EnQueue(SqQueue &Q,QElemType e)
{
if((Q.rear+1) % MAXQSIZE == Q.front)
return ERROR;
//判断队列是否已满
Q.base[Q.rear]=e; //新元素插入队尾
Q.rear = (Q.rear +1)%MAXQSIZE; //队尾指针加1
return OK;
}
3、2出队
Status DeQueue(SqQueue &Q,QElemTpye &e)
{
if(Q.front == Q.rear) return ERROR; //队空
e = Q.base[Q.front]; //用e保存队头元素
Q.front = (Q.front + 1) % MAXQSIZE; //队头指针加1
return OK;
}
3、3取队头元素
QElemType GetHead (SqQueue Q)
{
if(Q.front != Q.rear) //队列非空
return Q.base[Q.front]; //返回队头元素的值,队头指针不变。
}
4、关于队列力扣题
学校的自助午餐提供圆形和方形的三明治,分别用数字
0
和1
表示。所有学生站在一个队列里,每个学生要么喜欢圆形的要么喜欢方形的。
餐厅里三明治的数量与学生的数量相同。所有三明治都放在一个 栈 里,每一轮:
- 如果队列最前面的学生 喜欢 栈顶的三明治,那么会 拿走它 并离开队列。
- 否则,这名学生会 放弃这个三明治 并回到队列的尾部。
这个过程会一直持续到队列里所有学生都不喜欢栈顶的三明治为止。
给你两个整数数组
students
和sandwiches
,其中sandwiches[i]
是栈里面第i
个三明治的类型(i = 0
是栈的顶部),students[j]
是初始队列里第j
名学生对三明治的喜好(j = 0
是队列的最开始位置)。请你返回无法吃午餐的学生数量。示例 1:
输入:students = [1,1,0,0], sandwiches = [0,1,0,1] 输出:0 解释: - 最前面的学生放弃最顶上的三明治,并回到队列的末尾,学生队列变为 students = [1,0,0,1]。 - 最前面的学生放弃最顶上的三明治,并回到队列的末尾,学生队列变为 students = [0,0,1,1]。 - 最前面的学生拿走最顶上的三明治,剩余学生队列为 students = [0,1,1],三明治栈为 sandwiches = [1,0,1]。 - 最前面的学生放弃最顶上的三明治,并回到队列的末尾,学生队列变为 students = [1,1,0]。 - 最前面的学生拿走最顶上的三明治,剩余学生队列为 students = [1,0],三明治栈为 sandwiches = [0,1]。 - 最前面的学生放弃最顶上的三明治,并回到队列的末尾,学生队列变为 students = [0,1]。 - 最前面的学生拿走最顶上的三明治,剩余学生队列为 students = [1],三明治栈为 sandwiches = [1]。 - 最前面的学生拿走最顶上的三明治,剩余学生队列为 students = [],三明治栈为 sandwiches = []。 所以所有学生都有三明治吃。示例 2:
输入:students = [1,1,1,0,0,1], sandwiches = [1,0,0,0,1,1] 输出:3提示:
1 <= students.length, sandwiches.length <= 100
students.length == sandwiches.length
sandwiches[i]
要么是0
,要么是1
。students[i]
要么是0
,要么是1
。
思路:根据题目的意思就是把学生放到一个队列里,然后把队列遍历出来挨个和数组里的三明治进行比较。如果比较为相同则比下一个学生和下一个三明治。若不相同,则把学生放到队尾去,接着比。
int countStudents(int* students, int studentsSize, int* sandwiches, int sandwichesSize){
int head =0,tail =-1; //代表一个队列
int data[30000]; //定于数据域
int i;
int sandIdx =0;
int gg =0;
for(i =0;i<studentsSize;i++)
{
data[++tail] =students[i]; //把学生放到队列里
}
while(head <= tail)
{
if(data[head] == sandwiches[sandIdx]) //第一个学生如果等于第一个三明治
{
++head; //那就把第一个学生去掉,变成第二个学生
++sandIdx; //第二个三明治
if(sandIdx ==sandwichesSize){
return 0; //说明所有学生都吃到了想吃的三明治
}
}else{
data[++tail] =data[head]; //如果这个学生不喜欢当前的三明治,则把这个学生挪到队尾去
++head; //看下一个学生
if(gg ++ >10000) //可能一直都匹配不上喜欢的
{
return tail -head +1;
}
}
}
return tail -head +1;
}