数据结构之队列的定义与简单实现

队列的定义与简单实现

和栈相反,队列是一种先进先出(FIFO)的线性表,队列仅在线性表的两端进行操作:
1.
队头(Front):取出数据元素的一端;

2.队尾(Rear):插入数据元素的一端。


现实中,队列的例子也有很多,比如:银行排队办业务,食堂排队打饭等。

既然队列也是一种线性表,那么理论上也应该有线性表该有的操作。

队列的一些常用操作:
1.
创建队列;
2.
销毁队列;
3.
清空队列;
4.
进队列;
5.
出队列;
6.
获取队头元素;
7.
获取队列的长度。

队列通常有两种实现方式:

1.顺序结构实现;


2. 链式结构实现。

或许有人已经发现本节开头说的队列是与栈相反的特殊线性表,那么队列的实现不就是将栈反过来吗?BINGO,就是这个道理。

回顾前面栈实现的方式,我们知道顺序栈是通过从尾部插入元素,尾部取出元素来实现后进先出的;链式栈是通过从头部插入元

素,头部取出元素来实现后进先出的。

所以这里队列的顺序实现就应该是从尾部插入元素,头部取出元素;链式实现方式也应该是从尾部插入元素,头部取出元素。这

样就可以实现先进先出了,可以通过复用顺序表和的单链表来实现。

首先看一下顺序队列的实现代码:

#include "SeqList.h"
#include "SeqQueue.h"
// 创建队列
SeqQueue* SeqQueue_Create(int capacity) // O(1)
{
    return SeqList_Create(capacity);
}
// 销毁队列
void SeqQueue_Destroy(SeqQueue* queue) // O(1)
{
    SeqList_Destroy(queue);
}
// 清空队列
void SeqQueue_Clear(SeqQueue* queue) // O(1)
{
    SeqList_Clear(queue);
}
// 进队列
int SeqQueue_Append(SeqQueue* queue, void* item) // O(1)
{
    return SeqList_Insert(queue, item, SeqList_Length(queue));
}
// 出队列
void* SeqQueue_Retrieve(SeqQueue* queue) // O(n)
{
    return SeqList_Delete(queue, 0);
}
// 获取队头元素
void* SeqQueue_Header(SeqQueue* queue) // O(1) 
{
    return SeqList_Get(queue, 0);
}
// 获取队列的长度
int SeqQueue_Length(SeqQueue* queue) // O(1)
{
    return SeqList_Length(queue);
}
// 获取队列的容量
int SeqQueue_Capacity(SeqQueue* queue) // O(1)
{
    return SeqList_Capacity(queue);
}

链式队列的实现代码

#include <malloc.h>
#include "LinkList.h"
#include "LinkQueue.h"
// 定义链式队列结点结构体
typedef struct _tag_LinkQueueNode
{
    LinkListNode header;
    void* item;
} TLinkQueueNode;
// 创建队列
LinkQueue* LinkQueue_Create() // O(1)
{
    return LinkList_Create();
}
// 销毁队列
void LinkQueue_Destroy(LinkQueue* queue) // O(n)
{
    LinkQueue_Clear(queue);
    LinkList_Destroy(queue);
}
// 清空队列
void LinkQueue_Clear(LinkQueue* queue) // O(n)
{
    while( LinkQueue_Length(queue) > 0 )
    {
        LinkQueue_Retrieve(queue);
    }
}
// 进队列
int LinkQueue_Append(LinkQueue* queue, void* item) // O(n)
{
    TLinkQueueNode* node = (TLinkQueueNode*)malloc(sizeof(TLinkQueueNode));
    int ret = (item != NULL) && (node != NULL);
    
    if( ret )
    {
        node->item = item;
        
        ret = LinkList_Insert(queue, (LinkListNode*)node, LinkList_Length(queue));
    }
    
    if( !ret )
    {
        free(node);
    }
    
    return ret;
}
// 出队列
void* LinkQueue_Retrieve(LinkQueue* queue) // O(1)
{
    TLinkQueueNode* node = (TLinkQueueNode*)LinkList_Delete(queue, 0);
    void* ret = NULL;
    
    if( node != NULL )
    {
        ret = node->item;
        
        free(node);
    }
    
    return ret;
}
// 获取队头元素
void* LinkQueue_Header(LinkQueue* queue) // O(1)
{
    TLinkQueueNode* node = (TLinkQueueNode*)LinkList_Get(queue, 0);
    void* ret = NULL;
    
    if( node != NULL )
    {
        ret = node->item;
    }
    
    return ret;
}
// 获取队列的长度
int LinkQueue_Length(LinkQueue* queue) // O(1)
{
    return LinkList_Length(queue);
}

详细代码见下面链接:

顺序队列C实现

链式队列C实现

我们观察代码会发现,顺序队列的实现出队列的时间复杂度为O(n),链式队列的进队列的时间复杂度为O(n)。所以,这样看来复用顺序表及单链表实现的队列还不够优秀,那么,队列有没有其他的实现形式,可以提高进队和出队的效率呢?答案是肯定,不过将在下节揭晓。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值