【数据结构初阶】一文详解顺序栈和链队列的基本操作(下)

简介: 【数据结构初阶】一文详解顺序栈和链队列的基本操作

1.队列的概念

队列是一种特殊的线性表,特殊在只能从一端进行插入操作,另一端进行删除操作,队列具有Fist  In First Out的原则。

队尾:进行插入操作的一端,这个过程叫做入队列

队头:进行删除操作的一端,这个过程叫做出队列

c54e7264defb43918b2342290bd9bdac.png

抽号机:先来先服务,先给号码排队 (涉及嵌入式)


8dc1471c4f6c4ed1b1faea9dae2decde.png

2.队列的结构

队列我们采用链表实现:顺序表在满了要扩容,删完了后再入队列的时候还得扩容

链表的话,入队列就是尾插,定义一个尾指针。出队列就是头删,定义一个头指针

3.实现队列的基本操作

3-1结构体定义

b3af918729e74116b32dd1fc3531babc.png

typedef int QDateType;
typedef struct QueueNode
{
  struct QueueNode* next;
  QDateType val;
}QueueNode;
typedef struct Queue
{
  QueueNode* head;
  QueueNode* tail;
}Queue;

3-2队列的初始化

这里的链表队列我并没有带头,没有带头就要在入队列和出队列时有一点特殊情况的考虑

void QueueInit(Queue* ps)
{
  assert(ps);
  ps->head = ps->tail = NULL;
}

3-3入队列

相当于尾插,考虑特殊情况:队列为空的情况

//入队列:尾插
void QueuePush(Queue* ps,QDateType x)
{
  assert(ps);
  QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
  newnode->next = NULL;
  newnode->val = x;
  if (newnode == NULL)
  {
    perror("malloc fail.");
    exit(-1);
  }
  if (ps->tail == NULL)
  {
    ps->head = ps->tail = newnode;
  }
  else
  {
    ps->tail->next = newnode;
    ps->tail = ps->tail->next;
  }
}

3-4出队列

相当于头删,考虑特殊情况:只有一个结点的情况,出队列后要改变ps->tail

void QueuePop(Queue* ps)
{
  assert(ps);
  assert(!QueueEmpty(ps));
  if (ps->head->next == NULL)
  {
    free(ps->head);
    ps->head = ps->tail = NULL;
  }
  else
  {
    QueueNode* next = ps->head->next;
    free(ps->head);
    ps->head = next;
  } 
}

3-5取队头元素

QDateType QueueFront(Queue* ps)
{
  assert(ps);
  assert(!QueueEmpty(ps));
  return ps->head->val;
}

3-6取队尾元素

QDateType QueueBack(Queue* ps)
{
  assert(ps);
  assert(!QueueEmpty(ps));
  return ps->tail->val;
}

3-7队列判空

1. bool QueueEmpty(Queue* ps)
2. {
3.  assert(ps);
4.  return ps->tail == NULL;
5. }

3-8队列长度

int QueueSize(Queue* ps)
{
  assert(ps);
  int size = 0;
  QueueNode* cur = ps->head;
  while(cur)
  {
    ++size;
    cur = cur->next;
  }
  return size;
}

3-9队列销毁

void QueueDestory(Queue* ps)
{
  assert(ps);
  QueueNode* cur = ps->head;
  while (cur)
  {
    QueueNode* next = cur->next;
    free(cur);
    cur = next;
  }
  ps->head = ps->tail = NULL;
}

4.源代码

4-1queue.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"queue.h"
void QueueInit(Queue* ps)
{
  assert(ps);
  ps->head = ps->tail = NULL;
}
void QueueDestory(Queue* ps)
{
  assert(ps);
  QueueNode* cur = ps->head;
  while (cur)
  {
    QueueNode* next = cur->next;
    free(cur);
    cur = next;
  }
  ps->head = ps->tail = NULL;
}
//入队列:尾插
void QueuePush(Queue* ps,QDateType x)
{
  assert(ps);
  QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
  newnode->next = NULL;
  newnode->val = x;
  if (newnode == NULL)
  {
    perror("malloc fail.");
    exit(-1);
  }
  if (ps->tail == NULL)
  {
    ps->head = ps->tail = newnode;
  }
  else
  {
    ps->tail->next = newnode;
    ps->tail = ps->tail->next;
  }
}
void QueuePop(Queue* ps)
{
  assert(ps);
  assert(!QueueEmpty(ps));
  if (ps->head == ps->tail)
  {
    free(ps->head);
    ps->head = ps->tail = NULL;
  }
  else
  {
    QueueNode* next = ps->head->next;
    free(ps->head);
    ps->head = next;
  } 
}
QDateType QueueFront(Queue* ps)
{
  assert(ps);
  assert(!QueueEmpty(ps));
  return ps->head->val;
}
QDateType QueueBack(Queue* ps)
{
  assert(ps);
  assert(!QueueEmpty(ps));
  return ps->tail->val;
}
bool QueueEmpty(Queue* ps)
{
  assert(ps);
  return ps->tail == NULL;
}
int QueueSize(Queue* ps)
{
  assert(ps);
  int size = 0;
  QueueNode* cur = ps->head;
  while(cur)
  {
    ++size;
    cur = cur->next;
  }
  return size;
}

4.2queue.h

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int QDateType;
typedef struct QueueNode
{
  struct QueueNode* next;
  QDateType val;
}QueueNode;
typedef struct Queue
{
  QueueNode* head;
  QueueNode* tail;
}Queue;
void QueueInit(Queue* ps);
void QueuePush(Queue* ps, QDateType x);
void QueuePop(Queue* ps);
QDateType QueueFront(Queue* ps);
QDateType QueueBack(Queue* ps);
bool QueueEmpty(Queue* ps);
int QueueSize(Queue* ps);
void QueueDestory(Queue* ps);

4.3test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"queue.h"
int main()
{
  Queue Q;
  QueueInit(&Q);
  QueuePush(&Q, 1);
  QueuePush(&Q, 2);
  QueuePush(&Q, 3);
  QueuePush(&Q, 4);
  QueuePush(&Q, 5);
  QDateType ret1 = QueueFront(&Q);
  printf("QueueFront:%d\n", ret1);
  QDateType ret2 = QueueBack(&Q);
  printf("QueueBack:%d\n", ret2);
  int size = QueueSize(&Q);
  printf("size:%d\n", size);
  while (!QueueEmpty(&Q))
  {
    printf("%d", QueueFront(&Q));
    QueuePop(&Q);
  }
  QueueDestory(&Q);
  return 0;
}

4.4效果图


025e2f7d9fc7441d97ba59b4fe9111fd.png


目录
相关文章
|
17天前
|
消息中间件 存储 搜索推荐
深入理解栈和队列(二):队列
深入理解栈和队列(二):队列
30 0
|
26天前
|
存储 编译器 C语言
【数据结构】C语言实现链队列(附完整运行代码)
【数据结构】C语言实现链队列(附完整运行代码)
36 0
|
1月前
【栈】数据结构栈的实现
【栈】数据结构栈的实现
|
1月前
|
存储
数据结构--栈和队列
数据结构--栈和队列
|
1月前
|
存储 算法 数据处理
数据结构从入门到精通——栈
栈,作为一种后进先出(LIFO)的数据结构,在计算机科学中扮演着重要的角色。它的特性使得它在处理函数调用、括号匹配、表达式求值等问题时具有得天独厚的优势。然而,如果我们跳出传统思维的束缚,会发现栈的用途远不止于此。
58 0
|
1月前
|
C语言
数据结构之栈详解(C语言手撕)
数据结构之栈详解(C语言手撕)
37 1
|
1月前
|
存储 算法
数据结构— — 队列的基本操作
数据结构— — 队列的基本操作
33 0
|
10天前
|
存储 算法 调度
数据结构期末复习(3)栈和队列
数据结构期末复习(3)栈和队列
18 0
|
22天前
|
存储 缓存 算法
【算法与数据结构】栈的实现详解
【算法与数据结构】栈的实现详解