一、个人理解
链队是线性表的衍生之一,具有先进先出的特性,在队尾进行插入操作,在队头进行删除操作。
链队由于是动态扩容的,需要新的数据节点时,分配一个,所以不存在顺序队的真上溢情况。
链队删除队头节点,也就是出队后,头节点直接指向原首元节点的下一个节点,所以也不存在顺序队的假上溢情况。
顺序队相关概念、实现以及真假上溢的理解说明,请参考之前写的文章,链接:《数据结构与算法基础-学习-12-线性表之顺序队》
二、图解
1、链队
2、空队列
3、出队
数据a和b出队。
4、入队
数据a和b入队。
三、结构体
1、ElemType
(1)说明
链队单节点数据域的内容,保存学生学号、学生姓名、学生分数。
(2)定义
typedef struct ElemType
{
char StudentNum[StudentNumLen];
char StudentName[StudentNameLen];
int StudentScore;
}ElemType;
2、LinkQueueNode
(1)说明
链队单节点分数据域指针域。
(2)定义
typedef struct LinkQueueNode
{
ElemType Data;
struct LinkQueueNode* NextPointer;
}LinkQueueNode, *LinkQueueNodePtr;
3、LinkQueue
(1)说明
链队结构,有队头指针、队尾指针、队长。
(2)定义
typedef struct LinkQueue
{
LinkQueueNodePtr FrontPtr; //队头,出队时用,指的是头节点。
LinkQueueNodePtr RearPtr; //队尾,入队时用。
QueueLenType QueueLen;
}LinkQueue;
四、函数
1、InitLinkQueue
(1)用途
初始化链队。
(2)源码
Status InitLinkQueue(LinkQueue* LQ)
{
JudgeAllNullPointer(LQ);
LQ->FrontPtr = (LinkQueueNodePtr)MyMalloc(sizeof(LinkQueueNode));
memset(&(LQ->FrontPtr->Data),0,sizeof(ElemType));
LQ->FrontPtr->NextPointer = NULL;
LQ->RearPtr = LQ->FrontPtr;
LQ->QueueLen = 0;
Log("Init LinkQueue : OK\n",Info);
return SuccessFlag;
}
(3)参数
参数名 | 说明 |
LQ | LinkQueue*类型链队。 |
2、GetLinkQueueLen
(1)用途
获取链队长度。
(2)源码
QueueLenType GetLinkQueueLen(LinkQueue* LQ)
{
JudgeAllNullPointer(LQ);
return LQ->QueueLen;
}
(3)参数
参数名 | 说明 |
LQ | LinkQueue*类型链队。 |
3、DestroyLinkQueue
(1)用途
销毁链队。
(2)源码
Status DestroyLinkQueue(LinkQueue* LQ)
{
JudgeAllNullPointer(LQ);
LinkQueueNodePtr TmpPtr = LQ->FrontPtr;
while(TmpPtr)
{
LQ->FrontPtr = TmpPtr->NextPointer;
free(TmpPtr);
TmpPtr = LQ->FrontPtr;
}
LQ->RearPtr = NULL;
LQ->QueueLen = 0;
free(LQ);
LQ = NULL;
Log("Destroy LinkQueue : OK\n",Info);
return SuccessFlag;
}
(3)参数
参数名 | 说明 |
LQ | LinkQueue*类型链队。 |
4、EnterLinkQueue
(1)用途
链队入队,将E的数据复制到链队LQ中。
(2)源码
Status EnterLinkQueue(LinkQueue* LQ, ElemType E)
{
JudgeAllNullPointer(LQ);
LinkQueueNodePtr NewNode = (LinkQueueNodePtr)MyMalloc(sizeof(LinkQueueNode));
NewNode->Data = E;
NewNode->NextPointer = NULL;
LQ->RearPtr->NextPointer = NewNode;
LQ->RearPtr = NewNode;
LQ->QueueLen++;
Log("Enter LinkQueue : OK\n",Info);
return SuccessFlag;
}
(3)参数
参数名 | 说明 |
LQ | LinkQueue*类型链队。 |
E | ElemType类型数据。 |
5、LeaveLinkQueue
(1)用途
链队出队,将队头的出队节点的数据域复制到输出参数E中。
实现时需要注意的点,链队中只有一个元素中时,出队后,需要把队尾指针指向队头指针,表示这是一个空的链队,特殊情况备注一下。
(2)源码
Status LeaveLinkQueue(LinkQueue* LQ, ElemType* E)
{
JudgeAllNullPointer(LQ);
JudgeAllNullPointer(E);
if(GetLinkQueueLen(LQ) == 0)
{
Log("LinkQueue is Empty, Data cannot be left\n",Warning);
return FailFlag;
}
LQ->QueueLen--;
*E = LQ->FrontPtr->NextPointer->Data;
LinkQueueNodePtr TmpPtr = LQ->FrontPtr->NextPointer->NextPointer;
free(LQ->FrontPtr->NextPointer);
LQ->FrontPtr->NextPointer = TmpPtr;
//如果链队中只有一个元素,这个元素出队后,需要把队尾指针指向队头指针,表示这是一个空链队。
if(GetLinkQueueLen(LQ) == 1)
{
LQ->RearPtr = LQ->FrontPtr;
}
Log("Leave LinkQueue : OK\n",Info);
return SuccessFlag;
}
(3)参数
参数名 | 说明 |
LQ | LinkQueue*类型链队。 |
E | ElemType*类型数据,输出参数。 |
6、GetLinkQueueTop
(1)用途
获取链队队头元素。
(2)源码
ElemType GetLinkQueueTop(LinkQueue* LQ)
{
JudgeAllNullPointer(LQ);
if(GetLinkQueueLen(LQ) == 0)
{
Log("LinkQueue is Empty, can't get LinkQueueTop\n",Warning);
return LQ->FrontPtr->Data;
}
return LQ->FrontPtr->NextPointer->Data;
}
(3)参数
参数名 | 说明 |
LQ | LinkQueue*类型链队。 |
五、编译执行
[gbase@czg2 LinearTable_LinkQueue]$ make
gcc -Wall -g ../Log/Log.c LinkQueue.c main.c -o TestLinkQueue -I ../Log/
[gbase@czg2 LinearTable_LinkQueue]$ ./TestLinkQueue
2023-2--Info--Init LinkQueue : OK
2023-2--Info--Enter LinkQueue : OK
2023-2--Info--Enter LinkQueue : OK
2023-2--Info--Enter LinkQueue : OK
2023-2--Info--Enter LinkQueue : OK
2023-2--Info--Enter LinkQueue : OK
2023-2--Info--Enter LinkQueue : OK
2023-2--Info--Enter LinkQueue : OK
2023-2--Info--Enter LinkQueue : OK
2023-2--Debug--ElemType Data :
StudentNum : X666
StudentName : Sun
StudentScore : 100
2023-2--Debug--LinkQueue Data :
StudentNum : X666
StudentName : Sun
StudentScore : 100
+++++++++++++++
StudentNum : X666
StudentName : Sun
StudentScore : 101
+++++++++++++++
StudentNum : X666
StudentName : Sun
StudentScore : 102
+++++++++++++++
StudentNum : X666
StudentName : Sun
StudentScore : 103
+++++++++++++++
StudentNum : X666
StudentName : Sun
StudentScore : 104
+++++++++++++++
StudentNum : X666
StudentName : Sun
StudentScore : 105
+++++++++++++++
StudentNum : X666
StudentName : Sun
StudentScore : 106
+++++++++++++++
StudentNum : X666
StudentName : Sun
StudentScore : 107
+++++++++++++++
FrontPtr : 0x246f100
RearPtr : 0x246f320
QueueLen : 8
2023-2--Info--Leave LinkQueue : OK
2023-2--Debug--ElemType Data :
StudentNum : X666
StudentName : Sun
StudentScore : 100
2023-2--Info--Leave LinkQueue : OK
2023-2--Debug--ElemType Data :
StudentNum : X666
StudentName : Sun
StudentScore : 101
2023-2--Info--Leave LinkQueue : OK
2023-2--Debug--ElemType Data :
StudentNum : X666
StudentName : Sun
StudentScore : 102
2023-2--Info--Leave LinkQueue : OK
2023-2--Debug--ElemType Data :
StudentNum : X666
StudentName : Sun
StudentScore : 103
2023-2--Info--Leave LinkQueue : OK
2023-2--Debug--ElemType Data :
StudentNum : X666
StudentName : Sun
StudentScore : 104
2023-2--Info--Leave LinkQueue : OK
2023-2--Debug--ElemType Data :
StudentNum : X666
StudentName : Sun
StudentScore : 105
2023-2--Info--Leave LinkQueue : OK
2023-2--Debug--ElemType Data :
StudentNum : X666
StudentName : Sun
StudentScore : 106
2023-2--Info--Leave LinkQueue : OK
2023-2--Debug--ElemType Data :
StudentNum : X666
StudentName : Sun
StudentScore : 107
2023-2--Warning--LinkQueue is Empty, Data cannot be left
2023-2--Debug--ElemType Data :
StudentNum : X666
StudentName : Sun
StudentScore : 107
2023-2--Debug--LinkQueue Data :
FrontPtr : 0x246f100
RearPtr : 0x246f100
QueueLen : 0
2023-2--Warning--LinkQueue is Empty, can't get LinkQueueTop
2023-2--Debug--ElemType Data :
StudentNum :
StudentName :
StudentScore : 0
2023-2--Info--Destroy LinkQueue : OK