数据结构(四)—— 队列(顺序队列和链队列)

一 队列

队列(Queue)是一种数据结构,它遵循先进先出(First-In-First-Out,FIFO)的原则。队列中的数据
项只能在一端插入,而在另一端删除。插入操作称为入队(enqueue),删除操作称为出队(dequeue)。

二 顺序队列

1、定义

顺序队列(Sequential Queue)是一种使用数组实现的队列。在顺序队列中,数据项按照插入的顺序排列,并且在队头进行删除操作,在队尾进行插入操作。实现顺序队列时,需要定义一个固定大小的数组,使用两个指针(front指针和rear指针)来分别表示队头和队尾的位置。

2、代码示例


头文件

/*===============================================
*   文件名称:seqqueue.h
*   创 建 者:  
*   创建日期:2023年08月09日
*   描    述:
================================================*/
#ifndef _SEQQUEUE_H
#define _SEQQUEUE_H
#define N 1024
typedef int queue_data;

typedef struct seq_squeue
{
    queue_data data[N];
    int f;  //首
    int r; // 尾
}squeue, *psqueue;

//创建
psqueue init_seqqueue();

//入队
int input_seqqueue(psqueue Q , queue_data value);

//出队
int out_seqqueue(psqueue Q);

//判空
int empty_seqqueue(psqueue Q);

//判满
int full_seqqueue(psqueue Q );


#endif

功能代码

/*===============================================
*   文件名称:seqqueue.c
*   创 建 者: 
*   创建日期:2023年08月09日
*   描    述:
================================================*/
#include <stdio.h>
#include "seqqueue.h"
#include <stdlib.h>
//创建
psqueue init_seqqueue()
{
    psqueue Q = (psqueue ) malloc(sizeof(squeue));
    if( NULL == Q )
        return NULL;
    Q->r = 0; //队尾
    Q->f = 0;//队首
    return Q;
}

//入队
int input_seqqueue(psqueue Q , queue_data value)
{
    if( NULL == Q )
        return -1;
    if( 0 == full_seqqueue(Q))
        return -2;

    Q->data[Q->r] = value ;// 从队尾插入
    Q->r = (Q->r+1)%N; //队尾移动一位
    return 0;

}

//出队
queue_data out_seqqueue(psqueue Q)
{

    //
    if( NULL == Q )
        return -1;
    if( 0 == empty_seqqueue(Q))
        return -2;

    queue_data t = Q->data[Q->f];//从队头出队
    Q->f = (Q->f+1)%N; //队头移动一位
    return t;
}

//判空
int empty_seqqueue(psqueue Q)
{
    if( NULL == Q )
        return -1;
    if( Q->r == Q->f )  // 如果出队与入队标识重合,则为空队列
        return 0 ;
    else
        return 1;

}

//判满
int full_seqqueue(psqueue Q )
{

    if( NULL == Q )
        return -1;
    if( Q->f == (Q->r+1)%N ) // 人为定义,在队尾离队头有一个位置时为满队列,用一个数组元素空间来判断队列是否满
        return 0;
    else 
        return 1;
}



测试代码

/*===============================================
*   文件名称:main.c
*   创 建 者: 
*   创建日期:2023年08月09日
*   描    述:
================================================*/
#include <stdio.h>
#include "chstack.h"
int main(int argc, char *argv[])
{ 
    //创建
    pchstack H = init_chstack();
    if( NULL == H )
    {
        puts("init err");
        return -1;
    }

    //入栈
    puts("入栈");
    for( int i = 0 ; i < 10 ; i++ )
    {
        printf("%d " , i+1);
        if( 0 != input_chstack(H , i+1))
        {
            puts("input err");
            return -1;
        }
    }
    puts("");

    //出栈
    puts("出栈");
    int ret = 0 ;
    while( 0 != empty_chstack(H))
    {
        if( 0 > (ret = out_chstack( H )))
        {
            puts("out err");
            return -1;
        }
        printf("%d ",ret);
    }
    puts("");


    return 0;
} 

3、运行结果


在这里插入图片描述

三 链队列

1、定义

链队列(Linked Queue)是一种使用链表实现的队列。链队列中,每个数据项保存一个指向下一个数据项的指针,通过这些指针将数据项连接在一起。链队列可以动态地增加或删除数据项,因此没有固定的大小限制。在链队列中,只需要一个指向队头和队尾的指针即可。

2、代码示例


头文件

/*===============================================
*   文件名称:chqueue.h
*   创 建 者:    
*   创建日期:2023年08月09日
*   描    述:
================================================*/
#ifndef _CHQUEUE_H
#define _CHQUEUE_H
typedef int chqueue_data;


//定义节点类型
typedef struct ch_queue
{
    chqueue_data data;
    struct ch_queue * next;
}chqueue , *pchqueue;

//定义指向头和尾的指针的类型
typedef struct node
{
    pchqueue f; //头
    pchqueue r; //尾
}nod,*pnod;

//创建链队列
pnod init_chqueue();

//入队链队列
int input_chqueue(pnod S , chqueue_data value );

//出队链队列
int out_chqueue(pnod S);

//判空
int empty_chqueue(pnod S);

#endif

功能代码

/*===============================================
*   文件名称:chqueue.c
*   创 建 者:   
*   创建日期:2023年08月09日
*   描    述:
================================================*/
#include <stdio.h>
#include "chqueue.h"
#include <stdlib.h>
//创建链队列
pnod init_chqueue()
{
    //创建链队列头节点
    pchqueue H = (pchqueue) malloc(sizeof(chqueue));
    if( NULL == H)
        return NULL;
        
    //创建一个有两个节点类型指针的结构体空间
    pnod S = (pnod) malloc(sizeof(nod));
    if( NULL == S )
        return NULL;
        
    S->r = S->f = H;//两个指针都指向头节点,其中,r指向尾,f指向头
    return S;
}

//入队链队列
int input_chqueue(pnod S , chqueue_data value )
{
    if( NULL == S )
        return -1;
     
    //开辟一个新节点
    pchqueue H = (pchqueue)malloc(sizeof(chqueue));
    if( NULL == H)
        return -1;
        
    //通过尾插的方式插入链队列
    S->r->next = H;//尾节点指向新节点
    S->r = H ;  // 指针r指向新节点(也是新的尾节点)
    H->next = NULL ;  // 新节点的next为空
    H->data = value ;  // 将插入值给新节点

    return 0;
}

//出队链队列
int out_chqueue(pnod S)
{
    if( NULL == S )
        return -1;
    
    // 如果除了头节点外只有一个节点的情况
    if( S->f->next == S->r )
    {
        pchqueue t = S->r;
        chqueue_data  m = t->data ;
        S->r = S->f;  // 头指针和尾指针都指向头节点,此时链队列为空
        free(t);
        t == NULL;
        return m ;
    }
    else // 有超过一个节点的情况
    {
        pchqueue q = S->f->next;  //临时保存需要删除的节点地址
        S->f->next = q->next;     // 头节点断开被删除的节点,指向删除节点的下一个节点
        chqueue_data t = q->data ; //临时保存需要删除的节点数据
        free(q); // 释放节点
        q =NULL;
        return t; //返回节点数据
    }
}

//判空
int empty_chqueue(pnod S)
{

    if( NULL == S )
        return -1;
    if( S->r == S->f )   // 如果尾指针和头指针指向一个地方,则链队列为空
        return 0;
    else
        return 1;
}


测试代码

/*===============================================
*   文件名称:main.c
*   创 建 者:  
*   创建日期:2023年08月09日
*   描    述:
================================================*/
#include <stdio.h>
#include "chqueue.h"
int main(int argc, char *argv[])
{ 
    //创建链队列
    pnod S = init_chqueue();
    if( NULL == S )
    {
        puts("init err");
        return -1;
    }
    
    //入队
    puts("入队");
    for( int i = 0 ; i < 10 ; i++ )
    {
        printf("%d ",i+1);
        if( 0 != input_chqueue(S,i+1))
        {
            puts("input err");
            return -1;
        }
    }
    puts("");

    //出队
    puts("出队");
    chqueue_data ret;
    while( 0 != empty_chqueue(S))
    {
        if( 0 > (ret = out_chqueue(S)))
        {
            puts("out err");
            return -1;
        }
        printf("%d ",ret);
    }
    puts("");

    return 0;
} 

在这里插入图片描述




总结来说,顺序队列适合于固定大小的队列,插入和删除操作的时间复杂度为O(1);链队列适用于动态大小的队列,插入和删除操作的时间复杂度也为O(1)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值