一. 队列的基本概念
- 队列是一种特殊的受限制的线性表
- 队列只允许在一端进行插入操作,在另外一端进行删除操作的线性表
- 队列是一种先进先出(First In First Out),
FIFO .允许插入的一端为队尾,允许删除的一端为队头. - 队列不允许在中间部位进行操作,删除的时候,总是从队头删除,插入的时候插入到队尾.
二. 队列的顺序存储实现
- 使用一块连续的内存空间来实现队列的存储
- 我们使用列表来实现一个队列
SeqQueue.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define QUEUE_MAX 1024
#define SEQ_QUEUE_TRUE 1
#define SEQ_QUEUE_FALSE 0
typedef struct SeqQueue
{
void *data[QUEUE_MAX];
int size;
}SeqQueue;
SeqQueue *init_seq_queue();
void push_seq_queue(SeqQueue* q, void * data);
void pop_seq_queue(SeqQueue *q);
void *front_seq_queue(SeqQueue *q);
void *back_seq_queue(SeqQueue *q);
int is_empty(SeqQueue *sq);
int get_size_seq_queue(SeqQueue *q);
void clear_seq_queue(SeqQueue *q);
void destroy_seq_queue(SeqQueue *q);
SeqQueue.c
#include "SeqQueue.h"
SeqQueue *init_seq_queue()
{
SeqQueue *q = (SeqQueue *)malloc(sizeof(SeqQueue));
if (q != NULL)
{
for (int i = 0; i < QUEUE_MAX; i++)
{
q->data[i] = NULL;
}
q->size = 0;
}
return q;
}
void push_seq_queue(SeqQueue* q, void *data)
{
if (data != NULL && q != NULL && q->size < QUEUE_MAX)
{
q->data[q->size] = data;
q->size++;
}
}
void pop_seq_queue(SeqQueue *q)
{
if (q != NULL && q->size > 0)
{
for (int i = 0; i < q->size - 1; i++)
{
q->data[i] = q->data[i + 1];
}
q->data[q->size - 1] = NULL;
q->size--;
}
}
void *front_seq_queue(SeqQueue *q)
{
if (q != NULL && q->size > 0)
{
return q->data[0];
}
return NULL;
}
void *back_seq_queue(SeqQueue *q)
{
if (q != NULL && q->size > 0)
{
return q->data[q->size - 1];
}
return NULL;
}
int is_empty(SeqQueue *q)
{
if (q != NULL)
{
return q->size == 0 ? SEQ_QUEUE_TRUE : SEQ_QUEUE_FALSE;
}
return SEQ_QUEUE_FALSE;
}
int get_size_seq_queue(SeqQueue *q)
{
if (q != NULL)
{
return q->size;
}
return -1;
}
void clear_seq_queue(SeqQueue *q)
{
if (q != NULL)
{
for(int i = 0;i <q->size;i++)
{
q->data[i] = NULL;
}
q->size = 0;
}
}
void destroy_seq_queue(SeqQueue *q)
{
if (q != NULL)
{
free(q);
}
}
测试代码
#include "SeqQueue.h"
int main()
{
SeqQueue *q = init_seq_queue();
int arr[5] = { 1,2,3,4,5 };
for (int i = 0; i < 5; i++)
{
push_seq_queue(q, (void *)&(arr[i]));
}
printf("5个数据入队之后的大小: %d\n", q->size);
printf("队头: %d, 队尾: %d\n", *(int *)front_seq_queue(q), *(int *)back_seq_queue(q));
int index = 1;
while (q->size > 0)
{
printf("第 %d 个出队的数据为: %d\n", index, *(int *)front_seq_queue(q));
pop_seq_queue(q);
index++;
}
if (is_empty(q))
{
push_seq_queue(q, (void *)(&arr[0]));
push_seq_queue(q, (void *)(&arr[1]));
printf("入队两个之后队列大小: %d,队头: %d,队尾: %d\n", q->size, *(int *)front_seq_queue(q),*(int*)back_seq_queue(q));
clear_seq_queue(q);
printf("清空之后大小为: %d\n", q->size);
}
else
{
printf("出错了,全部都出队了,队列不为空!");
}
destroy_seq_queue(q);
system("pause");
return 0;
}
结果:
三. 队列的链式存储
- 使用链表来实现队列
- 单向链表实现队列
- 链表的最后一个节点是队尾
- 链表的第一个节点是队头
- 插入的时候,就正常插入,插入到链表的尾部,也就是队尾
- 取出的时候,在头部取出,这样就保证了先进先出.
- 注意头节点的设计,一开始的头节点是指向NULL
头文件 LinkQueue.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LINK_QUEUE_TRUE 1
#define LINK_QUEUE_FALSE 0
typedef struct LinkNode
{
struct LinkNode *next;
void *data;
} LinkNode;
typedef struct LinkQueue
{
LinkNode *head;
int size;
}LinkQueue;
LinkQueue *init_link_queue();
void push_link_queue(LinkQueue *q, void *node);
void pop_link_queue(LinkQueue *q);
void *front_link_queue(LinkQueue *q);
void *back_link_queue(LinkQueue *q);
int get_size_link_queue(LinkQueue *q);
int is_empty(LinkQueue *q);
void clear_link_queue(LinkQueue *q);
void destroy_link_queue(LinkQueue *q);
实现部分: LinkQueue.c
#include "LinkQueue.h"
LinkQueue *init_link_queue()
{
LinkQueue *q = (LinkQueue *)malloc(sizeof(LinkQueue));
LinkNode *node = (LinkNode *)malloc(sizeof(LinkNode));
if (q != NULL && node != NULL)
{
node->data = NULL;
node->next = NULL;
q->head = node;
q->size = 0;
}
return q;
}
void push_link_queue(LinkQueue *q, void *data)
{
if (q != NULL && data != NULL)
{
LinkNode *newNode = (LinkNode *)malloc(sizeof(LinkNode));
if (newNode != NULL)
{
newNode->data = data;
newNode->next = NULL;
}
LinkNode *pCurrent = q->head;
while (pCurrent->next != NULL)
{
pCurrent = pCurrent->next;
}
pCurrent->next = newNode;
q->size++;
}
}
void pop_link_queue(LinkQueue *q)
{
if (q != NULL && q->size > 0)
{
LinkNode *nodeDel = q->head->next;
q->head->next = nodeDel->next;
free(nodeDel);
q->size--;
}
}
void *front_link_queue(LinkQueue *q)
{
if (q != NULL && q->size > 0)
{
LinkNode *nodeTemp = q->head->next;
return nodeTemp->data;
}
return NULL;
}
void *back_link_queue(LinkQueue *q)
{
if (q != NULL && q->size > 0)
{
LinkNode *nodeLast = q->head->next;
while (nodeLast->next != NULL)
{
nodeLast = nodeLast->next;
}
return nodeLast->data;
}
return NULL;
}
int get_size_link_queue(LinkQueue *q)
{
if (q != NULL)
{
return q->size;
}
return -1;
}
int is_empty(LinkQueue *q)
{
if (q != NULL)
{
return q->size == 0 ? LINK_QUEUE_TRUE : LINK_QUEUE_FALSE;
}
return LINK_QUEUE_TRUE;
}
void clear_link_queue(LinkQueue *q)
{
if (q != NULL)
{
q->size = 0;
q->head->next = NULL;
}
}
void destroy_link_queue(LinkQueue *q)
{
if (q != NULL)
{
LinkNode *pCurrent = q->head;
while (pCurrent->next != NULL)
{
free(pCurrent->next);
pCurrent = pCurrent->next;
}
free(q);
}
}
测试代码
#include"LinkQueue.h"
int main()
{
int arr[5] = { 1,2,3,4,5 };
LinkQueue *q = init_link_queue();
int arrLen = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < arrLen; i++)
{
push_link_queue(q, (void *)&(arr[i]));
}
printf("入队后队列大小: %d,队头: %d,队尾: %d\n", get_size_link_queue(q),*(int*)front_link_queue(q),*(int*)back_link_queue(q));
int temp;
int index = 1;
while (q->size > 0)
{
temp = *(int *)front_link_queue(q);
printf("第 %d 次出队的数据: %d\n", index, temp);
pop_link_queue(q);
}
if (is_empty(q))
{
push_link_queue(q, (void *)&arr[0]);
push_link_queue(q, (void *)&arr[1]);
printf("存入两个数之后,队列大小: %d,队头: %d,队尾: %d\n", get_size_link_queue(q), *(int *)front_link_queue(q), *(int *)back_link_queue(q));
}
else
{
printf("出错,全部出队之后,队列不为空!");
}
clear_link_queue(q);
printf("清空之后队列大小: %d\n", get_size_link_queue(q));
destroy_link_queue(q);
system("pause");
return 0;
}
结果:
|