章节3.4----队列的实现与应用

文章目录

    • 前言
    • 顺序队列结构图示
    • 顺序队列的实现以及入队出队(C语言实现)
    • 链式队列结构图示
    • 链式队列的实现以及基本算法(C++实现)
    • 循环队列(C++实现)

前言

其实这章再写下去就是无聊的重复了,本质上来讲,栈和队列都是特殊的线性表,而线性表的两种实现方式,顺序和链式,运用到栈和队列上,也就变成了顺序栈和链式栈,顺序队列和链式队列。所以写法都是一样的,唯一不一样的就是规则不一样,栈先进后出,队列先进先出而已。
所以这节的代码和栈很相似,写代码本来就很枯燥,写重复的代码更枯燥
所以呢,这章我会有一部分使用C++实现
前边说过,课本上面给出的代码片是C++和伪代码的形式,之前我一直用的C语言来实现算法,所以书上使用的引用我只能用双重指针来替换,很多人可能指针用的不是很熟,不太懂,所以这章我会给出几个C++写法(讲真,C++确实好用多了,指针真的烦 #%#-~)

顺序队列结构图示

注意:此处我给出的结构,队头指针所指地方没有存数据,在有的地方你也会看到,队头存了数据,队尾指针不存数据。
这里存不存数据,其实不用纠结,此处和栈的写法是类似的,我们存不存都行。我们统一操作之后,若入队的时候先入队,指针再加加,那队头就有数据,但是队尾没有,若我们统一操作为,指针先加加,再入队,那队头就没存数据了。哪个方便就用哪个,无所谓。

章节3.4----队列的实现与应用_第1张图片

顺序队列的实现以及入队出队(C语言实现)

#include
#include
typedef struct QNode{
	int x;
}QDataNode;

typedef struct{
	QDataNode *front;
	QDataNode *rear;
}QHeadNode,*LinkQueue;

#define MaxSize 100

int InitQueue(LinkQueue *Q){
    (*Q)=(LinkQueue)malloc(sizeof(QHeadNode));

    (*Q)->front=(*Q)->rear=(QDataNode *)malloc(sizeof(QDataNode)*MaxSize);
    if(!(*Q)->front) return -1;
    return 0;
}
int EnQueue(LinkQueue *Q,int e){
    //因为第一个位置空着没存数据 所以这里判断队满用的是MaxSize-1
    if((*Q)->rear-(*Q)->front == MaxSize-1){
        return -1;//队满
    }
    (*Q)->rear++;
    (*Q)->rear->x=e;
    return 0;
}
int DeQueue(LinkQueue *Q,int *e){
    if((*Q)->front==(*Q)->rear) return -1;
    (*Q)->front++;
    *e=(*Q)->front->x;
    return 0;
}

int main(){
    LinkQueue Q;
    InitQueue(&Q);
    for(int i=1;i<=10;i++){
        EnQueue(&Q,i);
    }
    int e;

    while(Q->front != Q->rear){
        DeQueue(&Q,&e);
        printf("%d ",e);
    }
}

链式队列结构图示

章节3.4----队列的实现与应用_第2张图片

链式队列的实现以及基本算法(C++实现)

注:书上给出的很多算法是代码片,但是我在博客中给出的程序都是完整的,可以运行的,并不是代码片。

/******
author:  1900
language: C++
******/
#include
#include
using namespace std;
typedef struct QNode{
    int data;
    struct QNode *next;
}QNode,*QueuePtr;
typedef struct{
    QueuePtr front;//队头指针
    QueuePtr rear;//队尾指针
}LinkQueue;

int InitQueue(LinkQueue &Q){//初始化
    Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
    if(!Q.front) return -1;//申请失败
    Q.front->next=NULL;
    return 0;
}
int EnQueue(LinkQueue &Q,int e){//入队
    QueuePtr p=(QueuePtr)malloc(sizeof(QNode));
    if(!p) return -1;
    p->data=e;
    p->next=NULL;
    Q.rear->next=p;
    Q.rear=p;
    return 0;
}
int DeQueue(LinkQueue &Q,int &e){//出队
    if(Q.front==Q.rear) return -1;//队列为空
    QueuePtr p=Q.front->next;
    e=p->data;
    Q.front->next=p->next;
    if(Q.rear==p) Q.rear=Q.front;//队空
    return 0;
}

int main(){
    LinkQueue Q;
    InitQueue(Q);
    for(int i=1;i<=10;i++){
        EnQueue(Q,i);
    }
    int e;
    while(Q.front!=Q.rear){
        DeQueue(Q,e);
        cout<<e<<endl;
    }
}

循环队列(C++实现)

循环队列的优势在于节省空间,已经出队的元素把空间腾出来了,不用就浪费了,所以有了循环队列。
所以,循环队列是针对顺序队列的改进,因为链式队列不存在浪费空间的缺点,所以这是对顺序队列的优化。
这里我用**C++**实现的,主要是用C语言的话,此处将使用大量的指针,指来指去,容易晕

//C++
/**
这个顺序循环队列的初始空间大小是10个位置
下面进行的操作是:
先把1-8这8个数字入队
再进行五次出队操作
再把10 20 30 40 50 这五个数字入队
把队中元素全部出队
**/

#include
#include
using namespace std;

typedef struct{
	int *base;
	int front;
	int rear;
}SqQueue;

#define MaxSize 10

int InitQueue(SqQueue &Q){
    Q.base=(int *)malloc(sizeof(int)*MaxSize);
    if(!Q.base) return -1;
    Q.front=Q.rear=0;
    return 0;
}
int EnQueue(SqQueue &Q,int e){
    if((Q.rear+1)%MaxSize==Q.front) return -1;//队满
    Q.base[Q.rear]=e;
    Q.rear=(Q.rear+1)%MaxSize;
    return 0;
}
int DeQueue(SqQueue &Q,int &e){
    if(Q.front==Q.rear) return -1;
    e=Q.base[Q.front];
    Q.front=(Q.front+1)%MaxSize;
    return 0;
}

int main(){
    SqQueue Q;
    InitQueue(Q);
    for(int i=1;i<=8;i++){
        EnQueue(Q,i);
    }
    int e;
    for(int i=1;i<=5;i++){
        DeQueue(Q,e);
        cout<<e<<endl;
    }
    for(int i=1;i<=5;i++){
        EnQueue(Q,i*10);
    }

    while(Q.front != Q.rear){
        DeQueue(Q,e);
        cout<<e<<endl;
    }
}

你可能感兴趣的:(数据结构(严蔚敏版))