1、难点
要想用链表实现队列,就必须队尾进,队头出,先进先出,后进后出,这些利用链表的头尾节点都可以实现,即:头删(出队)和尾插(入队),那么如何保证入队和出队的**时间复杂度都为O(1)**呢?显然,头删的时间复杂度已经为O(1),因此要让尾插的复杂度为O(1)的话需要将尾节点保存起来。
2、结构体设计
因此需要进行改进,改进之后的结构体设计如下:
//有效节点
typedef struct LQueue
{
ELEM_TYPE data;//用来保存节点数据
LQueue* next;//用来保存下一个节点地址
}Node, * PNode;
//头节点
typedef struct Head
{
LQueue* front;//用来保存下一个节点地址
LQueue* tail;//用来保存最后一个结点的地址,只用头节点保存就行,其他的就会浪费
}head, * Phead;
3、头文件
typedef int ELEM_TYPE;
/*如下设计会让每个节点浪费4字节*/
//typedef struct LQueue
//{
// ELEM_TYPE* data;//用来保存节点数据
// LQueue* next;//用来保存下一个节点地址
// LQueue* tail;//用来保存最后一个结点的地址,只用头节点保存就行,其他的就会浪费
//}Node,*PNode;
//有效节点
typedef struct LQueue
{
ELEM_TYPE data;//用来保存节点数据
LQueue* next;//用来保存下一个节点地址
}Node, * PNode;
//头节点
typedef struct Head
{
LQueue* front;//用来保存下一个节点地址
LQueue* tail;//用来保存最后一个结点的地址,只用头节点保存就行,其他的就会浪费
}head, * Phead;
//购买节点
PNode Buynode();
//初始化
void Init(Phead pq);
//入队
bool push(Phead pq,ELEM_TYPE val);
//出队
bool Pop(Phead pq, ELEM_TYPE* rtval);
//获取有效节点个数
int Get_length(Phead pq);
//判空
bool Is_Empty(Phead pq);
//清空
void Clear(Phead pq);
//销毁
void Destory(Phead pq);
//打印
void Print(Phead pq);
4、函数实现
#include<stdio.h>
#include<assert.h>
#include"LinkQueue.h"
#include<stdlib.h>
//购买节点
PNode Buynode()
{
PNode s = (PNode)malloc(sizeof(Node));
if (s == NULL)
{
return NULL;
}
return s;
}
//初始化
void Init(Phead pq)
{
assert(pq != NULL);
pq->front = pq->tail = NULL;
}
//入队
bool push(Phead pq, ELEM_TYPE val)
{
assert(pq != NULL);
PNode s = Buynode();
s->data = val;
if (Is_Empty(pq))
{
pq->front = s;
pq->tail = s;
s->next = NULL;
}
else
{
s->next = NULL;
pq->tail->next = s;
pq->tail = s;
}
return true;
}
//出队
bool Pop(Phead pq, ELEM_TYPE* rtval)
{
assert(pq != NULL);
if (Is_Empty(pq))
{
return false;
}
*rtval = pq->front->data;
if (pq->front->next == NULL)//只有一个节点
{
pq->front = NULL;
pq->tail = NULL;
}
else//有多节点
{
PNode p = pq->front;
pq->front = p->next;
}
return true;
}
//获取有效节点个数
int Get_length(Phead pq)
{
assert(pq != NULL);
if (Is_Empty(pq))
{
return 0;
}
PNode p = pq->front;
int length = 0;
while (p != NULL)
{
length++;
p = p->next;
}
return length;
}
//判空
bool Is_Empty(Phead pq)
{
assert(pq != NULL);
return pq->front == NULL;
}
//打印
void Print(Phead pq)
{
assert(pq != NULL);
if (Is_Empty(pq))
{
return;
}
else
{
PNode p= pq->front;
while (p != NULL)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
}
//清空
void Clear(Phead pq)
{
assert(pq != NULL);
pq->front = pq->tail = NULL;
}
void Destory(Phead pq)
{
assert(pq != NULL);
Clear(pq);
free(pq);
pq = NULL;
}
int main()
{
Head x = {};
Phead pq = &x;
Init(pq);
for (int i = 0; i < 10; i++)
{
push(pq, i);
Print(pq);
}
int rtval;
for (int i = 0; i < 10; i++)
{
Pop(pq, &rtval);
printf("出栈元素为;%d 剩余%d个元素\n ", rtval,Get_length(pq));
}
Destory(pq);
push(pq, 1);
}
运行结果如下:
当队列中最后一个元素出队之后,我将队列销毁,此时会终止,原因是,每次加的断言,说明销毁成功。