【考研代码笔记】数据结构

219 阅读3分钟

【数据结构学习笔记】3.2队列(Queue)

1.队列的定义

  • 只允许在一端进行插入(入队),在另一端删除(出队)线性表
  • 特点:先进入队列的元素先出队-First In First Out(FIFO)

2.队列的初始化

#define MaxSize 10          //定义队列中元素的最大个数 
typedef struct{
    Elemtype data[MaxSize]; //用静态数组存放队列元素 
    int front,rear;         //对头指针和队尾指针 
}SqQueue; 
​
//初始化队列
void InitQueue(SqQueue &Q){
    //初始时 队头、队尾指针指向0
    Q.rear=Q.front=0; 
} 
​
//判断队列是否为空
bool QueueEmpty(SqQueue Q){
    if(Q.rear==Q.front)     //队空条件
        return true;
    else
        return false; 
}

3.入队操作

//入队
bool EnQueue(SqQueue &Q,ElemType x){
    Q.data[Q.rear]=x;       //将x插入队尾
    Q.rear=Q.rear+1;        //队尾指针后移
    return true; 
} 
​
//循环队列-入队操作 
bool EnQueue(SqQueue &Q,ElemType x){
    if((Q.rear+1)%MaxSize==Q.front) //判断队满
        return false; 
    Q.data[Q.rear]=x;       //将x插入队尾
    Q.rear=(Q.rear+1)%MaxSize;      //队尾指针加1取模 
    return true; 
} 
  • 用模运算将存储空间在逻辑上变成了"环状"
  • 用循环队列的代价:牺牲一个存储单元

1.png

4.出队操作+队列元素的获取

//出队(删除一个队头元素,并用x返回)
bool DeQueue(SqQueue &Q,ElemType &x){
    if(Q.rear==Q.front)     //判断队空 
        return false;
    x=Q.data[Q.front];
    Q.front=(Q.front+1)%MaxSize;    //队头指针后移 
    return true;
} 
​
//获得队头元素的值,用x返回
bool GetHead(SqQueue Q,ElemType &x){
    if(Q.rear==Q.front)
        return false;
    x=Q.data[Q.front];
    return true; 
} 
  • 队列元素个数公式:

    (rear+MaxSize-front)%MaxSize

5.判断队空的其他方法

方案一:不浪费存储空间
  • #define MaxSize 10          //定义队列中元素的最大个数 
    typedef struct{
        Elemtype data[MaxSize]; //用静态数组存放队列元素 
        int front,rear;         //对头指针和队尾指针 
        int size;       //队列当前长度 
    }SqQueue; 
    
  • 插入成功:size++;

    插入失败:size--;

  • 初始化时:rear=front=0; size=0;

  • 队满条件:size==MaxSize;

  • 队空条件:size==0;

方案二:不浪费存储空间
  • #define MaxSize 10          //定义队列中元素的最大个数 
    typedef struct{
        Elemtype data[MaxSize]; //用静态数组存放队列元素 
        int front,rear;         //对头指针和队尾指针 
        int tag;        //最近进行的是删除/插入
    }SqQueue; 
    
  • 每次删除操作成功时,都令tag=0

    每次插入操作成功时,都令tag=1

  • 初始化时:rear=front=0; size=0;

  • 队满条件:front==rear&&tag==1;

  • 队空条件:front==rear&&tag==0;

6.队列的链式实现(带头结点)

typedef struct LinkNode{
    ElemType data;
    struct LinkNode *next;
}LinkNode;
​
typedef struct{
    LinkNode *front,*rear;
}LinkQueue; 
​
//初始化链队列(带头结点)
void InitQueue(LinkQueue &Q){
    //初始时 front、rear都指向头结点
    Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode));
    Q.front->next=NULL; 
}
​
//判断队列是否为空
bool IsEmpty(LinkQueue Q){
    if(Q.front==Q.rear)
        return true;
    else
        return false;
} 

image.png

7.入队(带头结点)

//入队(带头结点)
void EnQueue(LinkQueue &Q,ElemType x){
    LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));
    s->data=x;
    s->next=NULL;
    Q.rear->next=s;     //新结点插入到rear之后
    Q.rear=s;           //修改表尾指针 
} 

image.png

8.出队(带头结点)

//出队(带头结点)
bool DeQueue(LinkQueue &Q,ElemType &x){
    if(Q.front==Q.rear)
        return false;       //空队
    LinkNode *p=Q.front->next;
    x=p->data;              //用变量x返回队头元素
    Q.front->next=p->next;  //修改头结点的next指针
    if(Q.rear==p)           //此次是最后一个结点出队
        Q.rear=Q.front;     //修改rear指针
    free(p);                //释放结点空间
    return true; 
} 

image.png

9.队列的链式实现(不带头结点)

//初始化链队列(不带头结点)
void InitQueue(LinkQueue &Q){
    //初始时 front、rear都指向NULL
    Q.front=NULL;
    Q.rear=NULL;
}
​
//判断队列是否为空
bool IsEmpty(LinkQueue Q){
    if(Q.front==NULL)
        return true;
    else
        return false;
} 

10.入队(不带头结点)

//入队(不带头结点)
void EnQueue(LinkQueue &Q,ElemType x){
    LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));
    s->data=x;
    s->next=NULL;
    if(Q.front==NULL){  //在空队列中插入第一个元素
        Q.front=s;
        Q.rear=s; 
    }
    else{
        Q.rear->next=s;     //新结点插入到rear之后
        Q.rear=s;           //修改表尾指针 
    }
} 

11.出队(不带头结点)

//出队(带头结点)
bool DeQueue(LinkQueue &Q,ElemType &x){
    if(Q.front==NULL)
        return false;       //空队
    LinkNode *p=Q.front;
    x=p->data;              //用变量x返回队头元素
    Q.front=p->next;        //修改front指针
    if(Q.rear==p){          //此次是最后一个结点出队
        Q.front=NULL;       //front指向NULL
        Q.rear=NULL;        //rear指向NUL 
    }
    free(p);                //释放结点空间
    return true; 
} 

image.png

12.双端队列的定义

  • 只允许从两端插入、两端删除的线性表
  • 双端队列可以退化为:栈、输入端受限的双端队列(两端都能删除但是只能从一端输入)、删除受限的双端队列(两端都能输入但是只能从一端删除)