数据结构之链式队列的实现

上篇我们提到了队列的基本概念与操作,这篇我们利用链表的方式来实现队列。
要用到链表,我们发现无论是头插头删还是尾插尾删都会涉及到遍历链表,所以这是不可避免的。再者,再对链表进行头部尾部处理的时候,我们应该引入一个新的指针,一个指针指向链表的头部,另一个指向尾部,这样我们就可以轻松的进行入队与出队。

实现

//linkqueue.h

#pragma once

#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>

typedef char LinkQueueType;

typedef struct LinkQueueNode{
  LinkQueueType data;
  struct LinkQueueNode* next;
}LinkQueueNode;//链表内的元素节点

typedef struct LinkQueue{
  LinkQueueNode* head;
  LinkQueueNode* tail;
}LinkQueue;//这里的两个指针分别是链表的头部与尾部,在初始化的时候创建一个伪节点当做队首,我们不考虑这个伪节点的data的内容

void LinkQueueInit(LinkQueue* q);//初始化链式队列

void LinkQueuePush(LinkQueue* q, LinkQueueType value);//入队

void LinkQueuePop(LinkQueue* q);//出队

void DestroyLinkQueue(LinkQueue* q);//销毁队列

int LinkQueueGetFront(LinkQueue* q, LinkQueueType* value);//获取队首
//linksqueue.c

#include "linkqueue.h"

#define HEAD printf("=================%s================\n",__FUNCTION__)

void LinkQueueInit(LinkQueue* q)//初始化链式队列
{
  if(q == NULL)
  {
    return;
  }

  q->head = q->tail = (LinkQueueNode*)malloc(sizeof(LinkQueueNode));//这里就是创建伪节点
  if(q -> head == NULL)
  {
    return;
  }

  q->head->next = NULL;
}

void LinkQueuePush(LinkQueue* q, LinkQueueType value)//入队
{
  if(q == NULL)
  {
    return;
  }
  if(q->head == NULL)
  {
    return;
  }

  LinkQueueNode* cur = q->head;

  LinkQueueNode* new_node = (LinkQueueNode*)malloc(sizeof(LinkQueueNode));
  new_node->data = value;
  new_node->next = NULL;

  while(cur->next != NULL)
  {
    cur = cur->next;
  }
  cur->next = new_node;
  q->tail = new_node;
  return;
}

void LinkQueuePop(LinkQueue* q)//出队
{
  if(q == NULL)
  {
    return;
  }
  if(q->head == NULL || q->head->next == NULL)
  {
    return;
  }

  LinkQueueNode* cur = q->head;
  LinkQueueNode* to_delete = cur->next;
  cur->next = to_delete->next;
  free(to_delete);
  to_delete = NULL;

  return;
}

void DestroyLinkQueue(LinkQueue* q)//销毁队列
{
  if(q == NULL)
  {
    return;
  }
  if(q->head == NULL)
  {
    return;
  }

  while(q->head != NULL)
  {
    q->tail = q->head->next;
    free(q->head);
    q->head = q->tail;
  }
  return;
}

int LinkQueueGetFront(LinkQueue* q, LinkQueueType* value)//获取队首
{
  if(q == NULL)
  {
    return -1;
  }
  if(q->head == NULL || q->head->next == NULL)
  {
    return -1;
  }

  *value = q->head->next->data;
  return 1;
}
//测试函数如下


void LinkQueuePrint(LinkQueue* q)//打印链表的内容来校验是否成功入队出队等
{
  if(q == NULL)
  {
    return;
  }
  if(q->head->next == NULL)
  {
    return;
  }

  LinkQueueNode* cur = q->head->next;//这里我们不关注伪节点下的data内容,所以打印从next开始打印
  while(cur != NULL)
  {
    printf("%c ",cur->data);
    cur = cur->next;
  }
  printf("\n");
}

void TestPush()
{
  HEAD;
  LinkQueue q;
  LinkQueueInit(&q);
  LinkQueuePush(&q,'a');  
  LinkQueuePrint(&q);
  LinkQueuePush(&q,'b');  
  LinkQueuePrint(&q);
  LinkQueuePush(&q,'c');  
  LinkQueuePrint(&q);
  LinkQueuePush(&q,'d');  
  LinkQueuePrint(&q);
}

void TestPop()
{
  HEAD;
  LinkQueue q;
  LinkQueueInit(&q);
  LinkQueuePush(&q,'a');  
  LinkQueuePush(&q,'b');  
  LinkQueuePush(&q,'c');  
  LinkQueuePush(&q,'d');  
  LinkQueuePrint(&q);
  LinkQueuePop(&q);
  LinkQueuePrint(&q);
}

void TestGetFront()
{
  HEAD;
  LinkQueue q;
  LinkQueueType value;

  LinkQueueInit(&q);
  int ret = LinkQueueGetFront(&q,&value);
  printf("expected ret -1, actual ret %d\n",ret);
  LinkQueuePush(&q,'a');  
  LinkQueuePush(&q,'b');  
  LinkQueuePush(&q,'c');  
  LinkQueuePush(&q,'d');  
  LinkQueuePrint(&q);

  ret = LinkQueueGetFront(&q,&value);
  printf("expected ret 1, actual ret %d\n",ret);
  printf("expected value a, actual value %c\n",value);
}

int main()
{
  TestPush();
  TestPop();
  TestGetFront();

  printf("\n");
  printf("\n");
  printf("\n");
  printf("\n");
  return 0;
}

欢迎大家共同讨论,如有错误及时联系作者指出,并改正。谢谢大家!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值