数据结构之队列的链式存储


队列的链式存储

这里是数据结构个人学习的笔记记录,如有问题欢迎指正说明

一、队列的链式存储结构

队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出,我们把它简单称为链队列。为了操作上的方便,我们将队头指针指向链队列的头结点,而队尾指针指向终端结点。空队列时,我们将队头指针和队尾指针都指向头结点。
在这里插入图片描述

先来定义链队列的结构,它类似于单链表,不过有队头指针和队尾指针,具体定义如下

结构体的定义:

typedef struct LinkNode{
    int data;
    LinkNode* next;
}*LinkNodePtr;

typedef struct LinkQueue{
    LinkNodePtr front;
    LinkNodePtr rear;
}*LinkQueuePtr;

二、相关操作实现

1.初始化

malloc一个链队列,并生成一个头结点,队头指针和队尾指针为NULL。

/* 初始化 */
LinkQueuePtr initQueue(){
    LinkQueuePtr resultPtr=(LinkQueuePtr)malloc(sizeof(LinkQueue));
    LinkNodePtr headerPtr=(LinkNodePtr)malloc(sizeof(LinkNodePtr));
    headerPtr->next=NULL;

    resultPtr->front=headerPtr;
    resultPtr->rear=headerPtr;
    return resultPtr;
}

2.依次对栈中的每个数据元素输出

定义一个tempPtr指向队头指针的下一位。

void outputLinkQueue(LinkQueuePtr paraQueuePtr)
{
    LinkNodePtr tempPtr=paraQueuePtr->front->next;
    while(tempPtr!=NULL)
    {
        printf("%d ",tempPtr->data);
        tempPtr=tempPtr->next;
    }
    printf("\r\n");
}

3.进队列

进队列只能在队尾,所以只需要将队尾指针进行移动。
在这里插入图片描述

void enqueue(LinkQueuePtr paraQueuePtr,int paraElement)
{
    LinkNodePtr tempNodePtr=(LinkNodePtr)malloc(sizeof(LinkNodePtr));
    tempNodePtr->data=paraElement;
    tempNodePtr->next=NULL;

    paraQueuePtr->rear->next=tempNodePtr;
    paraQueuePtr->rear=tempNodePtr;
}

4.出队列

首先需要判断队列是否为空,如果不为空则将队头元素出队列,并返回该值,并需要判断出队列之后是否为空队列
在这里插入图片描述

int dequeue(LinkQueuePtr paraQueuePtr)
{
    int resultValue;
    LinkNodePtr tempNodePtr;

    if(paraQueuePtr->front==paraQueuePtr->rear)
    {
        printf("The queue is empty.\r\n");
        return -1;
    }

    tempNodePtr=paraQueuePtr->front->next;
    resultValue=tempNodePtr->data;
    paraQueuePtr->front->next=tempNodePtr->next;

    if(paraQueuePtr->rear==tempNodePtr)
    {
        paraQueuePtr->rear=paraQueuePtr->front;
    }

    tempNodePtr=NULL;

    return resultValue;
}

5.链队列中元素个数

遍历整个链队列便能得到这个链队列的长度了。

int lengthQueue(LinkQueuePtr paraQueuePtr)
{
    int length=0;
    LinkNodePtr tempNodePtr;
    tempNodePtr=paraQueuePtr->front->next;

    while(tempNodePtr!=NULL)
    {
        length++;
        tempNodePtr=tempNodePtr->next;
    }
    return length;
}

6.测试函数

该处我写了两个测试函数,一个为对链队列的测试操作,还有一个是对地址的输出,便于我们看到链队列是如何存储数据的。

void testLinkQueue(){
    printf("---Begin!---\r\n");
    LinkQueuePtr tempQueuePtr;
    tempQueuePtr=initQueue();
    enqueue(tempQueuePtr,10);
    enqueue(tempQueuePtr,30);
    enqueue(tempQueuePtr,50);

    outputLinkQueue(tempQueuePtr);

    printf("Length of the queue is %d\r\n",lengthQueue(tempQueuePtr));

    printf("dequeue gets %d\r\n",dequeue(tempQueuePtr));
    printf("dequeue gets %d\r\n",dequeue(tempQueuePtr));
    printf("dequeue gets %d\r\n",dequeue(tempQueuePtr));
    printf("dequeue gets %d\r\n",dequeue(tempQueuePtr));

    enqueue(tempQueuePtr,8);
    enqueue(tempQueuePtr,6);
    enqueue(tempQueuePtr,9);
    outputLinkQueue(tempQueuePtr);
    printf("---End!---\r\n");
}

void testAddress()
{
    LinkQueuePtr tempQueuePtr;
    tempQueuePtr=initQueue();

    enqueue(tempQueuePtr,8);
    enqueue(tempQueuePtr,6);
    enqueue(tempQueuePtr,9);
    outputLinkQueue(tempQueuePtr);

    printf("tempQueuePtr:%ld\n",&tempQueuePtr);
    printf("tempQueuePtr->front:%ld\n",&tempQueuePtr->front);
    printf("tempQueuePtr->rear:%ld\n",&tempQueuePtr->rear);
    printf("tempQueuePtr->front->next:%ld\n",&tempQueuePtr->front->next);
}

7.具体代码实现

#include<stdio.h>
#include<malloc.h>

typedef struct LinkNode{
    int data;
    LinkNode* next;
}*LinkNodePtr;

typedef struct LinkQueue{
    LinkNodePtr front;
    LinkNodePtr rear;
}*LinkQueuePtr;

LinkQueuePtr initQueue(){
    LinkQueuePtr resultPtr=(LinkQueuePtr)malloc(sizeof(LinkQueue));
    LinkNodePtr headerPtr=(LinkNodePtr)malloc(sizeof(LinkNodePtr));
    headerPtr->next=NULL;

    resultPtr->front=headerPtr;
    resultPtr->rear=headerPtr;
    return resultPtr;
}

void outputLinkQueue(LinkQueuePtr paraQueuePtr)
{
    LinkNodePtr tempPtr=paraQueuePtr->front->next;
    while(tempPtr!=NULL)
    {
        printf("%d ",tempPtr->data);
        tempPtr=tempPtr->next;
    }
    printf("\r\n");
}

void enqueue(LinkQueuePtr paraQueuePtr,int paraElement)
{
    LinkNodePtr tempNodePtr=(LinkNodePtr)malloc(sizeof(LinkNodePtr));
    tempNodePtr->data=paraElement;
    tempNodePtr->next=NULL;

    paraQueuePtr->rear->next=tempNodePtr;
    paraQueuePtr->rear=tempNodePtr;
}

int dequeue(LinkQueuePtr paraQueuePtr)
{
    int resultValue;
    LinkNodePtr tempNodePtr;

    if(paraQueuePtr->front==paraQueuePtr->rear)
    {
        printf("The queue is empty.\r\n");
        return -1;
    }

    tempNodePtr=paraQueuePtr->front->next;
    resultValue=tempNodePtr->data;
    paraQueuePtr->front->next=tempNodePtr->next;

    if(paraQueuePtr->rear==tempNodePtr)
    {
        paraQueuePtr->rear=paraQueuePtr->front;
    }

    free(tempNodePtr);

    return resultValue;
}

int lengthQueue(LinkQueuePtr paraQueuePtr)
{
    int length=0;
    LinkNodePtr tempNodePtr;
    tempNodePtr=paraQueuePtr->front->next;

    while(tempNodePtr!=NULL)
    {
        length++;
        tempNodePtr=tempNodePtr->next;
    }
    return length;
}

void testLinkQueue(){
    printf("---Begin!---\r\n");
    LinkQueuePtr tempQueuePtr;
    tempQueuePtr=initQueue();
    enqueue(tempQueuePtr,10);
    enqueue(tempQueuePtr,30);
    enqueue(tempQueuePtr,50);

    outputLinkQueue(tempQueuePtr);

    printf("Length of the queue is %d\r\n",lengthQueue(tempQueuePtr));

    printf("dequeue gets %d\r\n",dequeue(tempQueuePtr));
    printf("dequeue gets %d\r\n",dequeue(tempQueuePtr));
    printf("dequeue gets %d\r\n",dequeue(tempQueuePtr));
    printf("dequeue gets %d\r\n",dequeue(tempQueuePtr));

    enqueue(tempQueuePtr,8);
    enqueue(tempQueuePtr,6);
    enqueue(tempQueuePtr,9);
    outputLinkQueue(tempQueuePtr);
    printf("---End!---\r\n");
}

void testAddress()
{
    LinkQueuePtr tempQueuePtr;
    tempQueuePtr=initQueue();

    enqueue(tempQueuePtr,8);
    enqueue(tempQueuePtr,6);
    enqueue(tempQueuePtr,9);
    outputLinkQueue(tempQueuePtr);

    printf("tempQueuePtr:%ld\n",&tempQueuePtr);
    printf("tempQueuePtr->front:%ld\n",&tempQueuePtr->front);
    printf("tempQueuePtr->rear:%ld\n",&tempQueuePtr->rear);
    printf("tempQueuePtr->front->next:%ld\n",&tempQueuePtr->front->next);
}
int main()
{
    testLinkQueue();
    testAddress();
    return 0;
}

三、样例输出

—Begin!—
10 30 50
Length of the queue is 3
dequeue gets 10
dequeue gets 30
dequeue gets 50
The queue is empty.
dequeue gets -1
8 6 9
—End!—
8 6 9
tempQueuePtr:6421992
tempQueuePtr->front:13004720
tempQueuePtr->rear:13004728
tempQueuePtr->front->next:12981320

四、问题回答

1.这个问题在链队列里我没有找到答案,但我发现一个巧合,就是我多次打印链队列的队头指针和队尾指针的地址,我发现它们总是差两个字节,无论该链队列中有多少数据。
2.局部变量的空间能重复利用,它之所以叫局部变量,就是它只在局部函数里利用,函数调用结束则该空间就会释放。
3.指针的值是它所指向的变量的地址,而指针的地址是指该指针变量本身的地址。

五、写在最后

链队列适用于长度不确定的链队列。
因为链队列类似于单链表,所以每个结点的存储位置不一定是连续的。
在空间上链队列比循环队列更加灵活。

  • 11
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ALuoJi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值