【数据结构】队列(顺序表&链表)

 

顺序表版(循环队列):

插入的一端是队尾,删除的一端是队头

  • 初始化:令front=rear=0
  • 插入:指针增一
  • 删除:指针增一

如何判断队满和队空?

因为循环队列可能会遇到队满和队空都是front=rear=0的诡异情况,所以需要以下操作来界定队空和队满。

如你所见,每一次的数据的增加都会使rear指针加一,则,在加入最后一个元素后rear会指向最后一个空间,所以如果下一个位置是front指向的位置,则队满。(%取余操作是因为循环队列需要模运算)

也就是在数据结构中添加一个size变量,添加一个元素则,size++,那么队满的条件自然就是size==MaxSize

在数据结构中添加一个tag变量,添加元素时置1,删除元素时置0,这样就可以知道front=rear=0是添加时造成的还是删除时造成的了

以下代码为使用第一种方法区分队空和队满的循环队列↓

#include<iostream>
#define MaxSize 50
/*队列(Queue) FIFO(先进先出)  front 指向队头元素或前一个位置,rear指向队尾,初始front=rear=0
判空条件:front==rear
队长:rear-front
问题:会产生假溢出,需要成为循环队列,
用取余来制造循环移动
队长:(rear-front+MaxSize)%MaxSize
*/
typedef struct {
    int data[MaxSize];
    int front,rear;
} Queue;
/*初始化队列,构造空队列*/
void InitQueue(Queue &q);
/*判断空队列,若队列为空返回true,否则返回false*/
bool isEmpty(Queue q);
/*入队,若Q未满则将X加入队尾*/
bool EnQueue(Queue &q,int x);
/*出队,Q非空则删除队头元素用X返回*/
bool DeQueue(Queue &q,int &x);
/*读取队头元素,Q非空则用X返回队头元素*/
void GetHead(Queue q,int &x);
/*销毁队列,释放Q占用的内存*/
void ClearQueue(Queue &q);

/*
数据结构教材中的做法是在结构体中添加*base指针来存放基地址,而我采用的是声明数组的方式,书中的方法:
typedef struct {
    int *base;
    int front,rear;
} Queue;
void InitQueue(Queue &q){
    q.base = (int *)malloc(MaxSize*sizeof(Queue));
    if(!q) return false;//分配失败
    q.front=q.rear=0;
    return true;
}
*/

void InitQueue(Queue &q){
    q.front=q.rear=0;
}

bool isEmpty(Queue q){
    if(q.front==q.rear){
        return true;
    }
    return false;
}

bool EnQueue(Queue &q,int x){
    //判断队尾是否和队头相等(队满)
    if((q.rear+1)%MaxSize==q.front)
    return false;
    q.data[q.rear]=x;
    q.rear=(q.rear+1)%MaxSize;
    return true;
}
bool DeQueue(Queue &q,int &x){
    //判断队列是否为空
    if(isEmpty(q)){
        return false;
    }
    x=q.data[q.front];
    q.front=(q.front+1)%MaxSize;
    return true;
}
void GetHead(Queue q,int &x){
    x=q.data[q.front];
}
void ClearQueue(Queue &q){
    InitQueue(q);
}

链表版:

这就是一个很基本的链表结构:在链尾添加元素,在链头删除元素

链尾节点就是rear指向的节点,头节点就是front指针指向的节点。

链式队列的各种操作

注意:队列最后一个元素被删除后rear指针丢失,此时需要重新赋值

#include<iostream>

//队列节点结构,QueuePtr用来声明指针rear,front
typedef struct {
    int data;
    QNode *next;
}QNode,*QueuePtr;
//队列结构体
typedef struct{
    QueuePtr front;
    QueuePtr rear;
}LinkQueue;

//初始化队列
bool InitLinkQueue(LinkQueue &q){
    q.front=q.rear=(QueuePtr)malloc(sizeof(QNode));
    if(!q.front) return false;
    q.front->next=NULL;
    return true;
}
//销毁队列
//从头沿链表销毁,rear和front就像两条腿,rear先迈一步,然后删除front节点,随后front跟上rear;
bool DestroyQueue(LinkQueue &q){
    while (q.front)
    {
        q.rear=q.front->next;
        free(q.front);
        q.front=q.rear;
    }
    return true;
}
//入队
bool EnQueue(LinkQueue &q,int x){
    //p用来指代当前新建的节点
    QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
    if(!p) return false;
    p->data = x;
    p->next=NULL;
    //将rear指向新建的节点
    q.rear->next=p;
    q.rear=p;
    return true;
}
//出队
bool DeQueue(LinkQueue &q, int &x){
    //判断队列是否为空
    if(q.front==q.rear) return false;
    QueuePtr p=q.front->next;
    x=p->data;
    q.front->next=p->next;
    //如果出队元素为最后一个元素,则重置队列
    if(q.rear==p) q.rear=q.front;
    free(p);
    return true;
}

 

 

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术工厂 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读