一、链式存储结构的定义
队列的链式存储结构,其实就是线性表的单链表。只不过它是只能尾进头出而已,我们称之为链队列。我们定义了两个指针,一个指向队列的头,一个指向队列的尾。这样进行插入和删除的操作时时间复杂度都为O(1)。如下图所示:
二、队列链式存储结构的简单实现
1、队列链式存储结构的整体实现
typedef int ElemType;
typedef struct Node
{
ElemType data;
struct Node* next;
}Node;
typedef struct LQueue
{
struct Node* phead;
struct Node* ptail;
}LQue,*pQue
2、初始化
队列初始化时,它的头指针和尾指针都指向头结点。
代码如下:
void init(pQue pqu)
{
if(pqu != NULL)
{
Node* pnhead = (Node*)malloc(sizeof(Node));//堆上
pnhead->next = NULL;
pqu->head = pqu->ptail = pnhead;
}
}
2、入队操作
入队操作时,其实就是在链表的尾部插入结点。如下图所示:
在进行入队的操作的时候,我们要先生成一个新的结点,也就是我们要插入的结点。所以我们要先写一个函数购买结点函数(buyNode)
Node* buyNode(ElemType val)
{
Node* pnewnode = (Node*)malloc(sizeof(Node));
pnewnode->data = val;
pnewnode->next = NULL;
return 0;
}
入队操作
void enqueue(pQue pqu,ElemType val)
{
Node* pnewnode = buyNode(val);
pqu->ptail->next = pnewnode;//上图中的1步骤
pqu->tail = pnewnode;//将当前的val设置为队尾结点,ptail指向pnewnode,如上图中的2不住。
}
3、出队操作
出队操作时,就是头结点的后继结点出队。将头结点的后继改成它后面的结点。若链表中除头结点外只剩一个元素时,则需要将ptail指向头结点。如下图所示:
单数在进行出队操作之前我们得先判断队列中的元素是否存在元素。这也就是进行一个判空的操作。
int empty(pQue pqu)
{
return ((pqu->phead == pqu->ptail)&&(pqu->phead != NULL))? 1 : 0;
}
出队操作
int dequeue(pQue pqu)
{
if(empty(pqu))
{
return 0;
}
Node* pdelete = pqu->phead->next;//将欲删除的头结点暂存给pdelete,如上图的1所示:
pqu->phead->next = pdelete->next;//将原队头结点的后继pdelete->next赋值给头结点后继。如上图的2所示
if(pqu->phead->next == NULL)
{
pqu->ptail = pqu->phead;
}
free(pdelete);
return 1;
}
4、获取队头元素
在获取队头元素之前我们都应该先进行判空的操作。
int front(pQue pqu)
{
if(empty(pqu))
{
return -1;//牺牲一个数据位来做错误的标示
}
return pqu->phead->next->data;
}
5、获取队尾元素
同样我们要先进行判空的操作
int back(pQue pqu)
{
if(empty(pqu))
{
return -1;
}
return pqu->ptail->data;
}
6、清理函数
清理数据,结构是不清理的。
void clear(pQue pqu)
{
Node* pcur = pqu->phead->next;
Node* pnext;
while(pcur != NULL)
{
pnext = pcur->next;
free(pcur);
pcur = pnext;
}
pqu->phead->next = NULL;
pqu->ptail = pqu->phead
}
7、销毁所有结点
先清理数据,再清理结构。结构全部销毁。
void destoryed(pQue pqu);
{
clear(pqu);
free(pqu->phead);
pqu->phead = pqu->ptail = NULL;
}