基础数据结构-队列

目录

1、队列的概念

2、链队列

2、1入队

2、2出队

2、3取队头元素

3、顺序队列

3、1入队

3、2出队

3、3取队头元素

4、关于队列力扣题


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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值