链队列图示:
头结点需要两个指针域(一个指向头元素,一个指向尾元素),不需要数据域,所以头结点单独设计。
链队列头结点设计:
//头结点的结构体设计:
typedef struct LQueue
{
struct Node* front;
struct Node* rear;
}LQueue, * PLQueue;
链队列有效结点设计:
//链队列的结构体设计
typedef int ELEM_TYPE;
//有效数据节点的结构体设计:
typedef struct Node
{
ELEM_TYPE data;//数据域
struct Node* next;//指针域
}Node, * PNode;
可执行函数声明:
//初始化
void Init_LQueue(struct LQueue* lq);
//入队
bool Push(struct LQueue* lq, ELEM_TYPE val);
//出队(这里需要知道出队的值,通过输出参数rtval带出来)
bool Pop(struct LQueue* lq, ELEM_TYPE* rtval);
//获取队头元素值(这里需要知道队头的值,通过输出参数rtval带出来)
bool Top(struct LQueue* lq, ELEM_TYPE* rtval);
//搜索
struct Node* Search(struct LQueue* lq, ELEM_TYPE val);
//判空
bool IsEmpty(struct LQueue* lq);
//判满(链式结构 不需要判满)
//获取有效长度
int Get_length(struct LQueue* lq);
//清空
void Clear(struct LQueue* lq);
//销毁
void Destroy(struct LQueue* lq);
//打印
void Show(struct LQueue* lq);
代码 :
初始化:
//初始化
void Init_LQueue(struct LQueue* lq)
{
assert(lq != NULL);
lq->front = lq->rear = NULL;
}
入队:
bool Push(struct LQueue* lq, ELEM_TYPE val)
{
assert(lq != NULL);
PNode pnewnode = (PNode)malloc(sizeof(Node) * 1);
assert(pnewnode != NULL);
pnewnode->data = val;
if (IsEmpty(lq))//特殊情况下插入:空队列
{
pnewnode->next = lq->front;
lq->front = lq->rear = pnewnode;//因为如果是一个空队列,那么你入队的元素则既是队头也是队尾
}
else//正常情况下插入:插入的时候,里面有元素,不是一个空队列
{
pnewnode->next = lq->rear->next;
lq->rear->next = pnewnode;
lq->rear = pnewnode;//别忘了:更新一下队尾指针,重新让它指向新插入的尾结点
}
return true;
}
出队:
//出队(这里需要知道出队的值,通过输出参数rtval带出来)
bool Pop(struct LQueue* lq, ELEM_TYPE* rtval)
{
assert(lq != NULL);
if (IsEmpty(lq))
{
return false;
}
*rtval = lq->front->data;
//if(lq->front->next == NULL)//ok 判断剩余元素是否仅剩下一个
if (Get_length(lq) == 1)//ok
{
struct Node* p = lq->front;
free(p);
lq->front = lq->rear = NULL;
}
else //正常情况下: 剩余元素不止一个
{
struct Node* p = lq->front;
lq->front = p->next;
free(p);
}
return true;
}
获取队头元素、搜索
//获取队头元素值(这里需要知道队头的值,通过输出参数rtval带出来)
bool Top(struct LQueue* lq, ELEM_TYPE* rtval)
{
assert(lq != NULL);
if (IsEmpty(lq))
{
return false;
}
*rtval = lq->front->data;
return true;
}
//搜索
struct Node* Search(struct LQueue* lq, ELEM_TYPE val)
{
assert(lq != NULL);
//这里用的是 不需要前驱的for循环 ,遍历一遍即可
for (struct Node* p = lq->front; p != NULL; p = p->next)
{
if (p->data == val)
{
return p;
}
}
return NULL;
}
判空,判满、获取有效长度
//判空
bool IsEmpty(struct LQueue* lq)
{
assert(lq!= NULL);
return lq->front == NULL;
}
//判满(链式结构 不需要判满)
//获取有效长度
int Get_length(struct LQueue* lq)
{
assert(lq != NULL);
int cout = 0;
for (PNode p = lq->front; p != NULL; p = p->next)
{
cout++;
}
return cout;
}
清空,销毁,打印
//清空
void Clear(struct LQueue* lq)
{
assert(lq != NULL);
Destroy(lq);
}
//销毁
void Destroy(struct LQueue* lq)
{
assert(lq != NULL);
PNode p = lq->front;
struct Node* q;
while (p != NULL)
{
q = p->next;
free(p);
p = q;
}
lq->front = lq->rear = NULL;
}
//打印
void Show(struct LQueue* lq)
{
assert(lq != NULL);
PNode p = lq->front;
for (p; p != NULL; p = p->next)
{
printf("%d ", p->data);
}
printf("\n");
}
测试:
int main()
{
struct LQueue head;//建立一个头结点
Init_LQueue(&head);//初始化这个头结点
for(int i=0; i<20; i++)
{
Push(&head, i+1);//将1到20入队
}
Show(&head);//打印1到20
ELEM_TYPE tmp;
bool tag = Pop(&head, &tmp);
if(tag)
{
printf("pop = %d\n", tmp);
}//出队1,并且打印出队的元素
Show(&head);//打印2到20
printf("length = %d\n", Get_length(&head));//打印有效长度
ELEM_TYPE flag;
bool tag2 = Top(&head, &flag);
if(tag2)
{
printf("Top = %d\n", flag);
}//获取队头元素(没有删除)
Show(&head);//打印20到20
printf("length = %d\n", Get_length(&head));//打印有效长度
Destroy(&head);//销毁
Show(&head);//打印
printf("length = %d\n", Get_length(&head));//打印有效长度
return 0;
}
测试结果:
没有内存泄漏!