数据结构——C语言实现队列

C语言实现队列
1.队列的结构及相关概念
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出 FIFO(First In First Out)的特性。
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
在这里插入图片描述
2.队列的实现:
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数 组头上出数据,效率会比较低。下面,我们描述如何使用链表实现队列。
QueueNode.h文件:

typedef int DataType;
typedef struct QueueNode
{
 struct QueueNode* _next;
 DataType _data;
}QueueNode;
typedef struct Queue
{
 QueueNode* _front;//队头
 QueueNode* _rear;//队尾
}Queue;
void QueueInit(Queue* p);//初始化队列
void QueueDestory(Queue* p);//销毁队列
void QueuePush(Queue* p,DataType x);//入队
void QueuePop(Queue* p);//出队
DataType QueueFront(Queue* p);//获取队首元素
DataType QueueBack(Queue* p);//获取队尾元素
int QueueEmpty(Queue* p);//判断队列是否为空
int QueueSize(Queue* p);//队列的大小
void Queueprint(Queue* p);//打印队列
void TestQueue();//测试

QueueNode.c文件:

//对队列进行初始化
void QueueInit(Queue* p)
{
 assert(p);
 p->_front = p->_rear = NULL;
}
//销毁队列
void QueueDestory(Queue* p)
{
 assert(p);
 QueueNode* cur = p->_front;
 while (cur)
 {
  p->_front = cur->_next;
  free(cur);
  cur = p->_front;
 }
 //将队尾置空
 p->_rear = NULL;
}
//入队:队尾插入元素
void QueuePush(Queue* p, DataType x)
{
 assert(p);
 QueueNode* newNode = (QueueNode*)malloc(sizeof(QueueNode));
 newNode->_data = x;
 newNode->_next = NULL;
 //判断是否为第一个插入的元素
 if (p->_front == NULL)
 {
  p->_front = p->_rear = newNode;
 }
 else
 {
  p->_rear->_next = newNode;
  p->_rear = p->_rear->_next;
 }
}
//出队:队首删除元素
void QueuePop(Queue* p)
{
 assert(p);
 if (p->_front)
 {
  QueueNode* next = p->_front->_next;
  //删除,出队
  free(p->_front);
  p->_front = next;
  //如果删除的为最后一个元素
  if (p->_front == NULL)
  {
   p->_rear = NULL;
  }
 }
}
//获取队首元素
DataType QueueFront(Queue* p)
{
 assert(p);
 return p->_front->_data;
}
DataType QueueBack(Queue* p)
{
 assert(p);
 return p->_rear->_data;
}
//判断队列是否为空
int QueueEmpty(Queue* p)
{
 assert(p);
 if (p->_front == NULL)
 {
  return 1;
 }
 else
 {
  return 0;
 }
}
//队列的大小
int QueueSize(Queue* p)
{
 assert(p);
 QueueNode* cur = p->_front;
 DataType n = 0;
 while (cur)
 {
  ++n;
  cur = cur->_next;
 }
}
//打印队列
void Queueprint(Queue* p)
{
 assert(p);
 QueueNode* cur = p->_front;
 while (cur)
 {
  printf("%d ", cur->_data);
  cur = cur->_next;
 }
 printf("\n");
}
//测试
void TestQueue()
{
 Queue p;
 QueueInit(&p);
 QueuePush(&p, 1);
 QueuePush(&p, 2);
 QueuePush(&p, 3);
 QueuePush(&p, 4);
 QueuePop(&p);
 QueuePop(&p);
 Queueprint(&p);
}

main.c文件:

int main()
{
 TestQueue();
 return 0;
}

队列中需特别理解队列的特性——先进先出规则。
在实际使用中还有一种特殊的队列——循环队列。如操作系统课程讲解生产者消费者模型时可以就会使用循环队列。环形队列可以使用数组实现,也可以使用循环链表实现。
在这里插入图片描述
循环队列的实现(leetcode上的原题):

//函数接口说明:
//MyCircularQueue(k) : 构造器,设置队列长度为 k 。
//Front : 从队首获取元素。如果队列为空,返回 - 1 。
//Rear : 获取队尾元素。如果队列为空,返回 - 1 。
//enQueue(value) : 向循环队列插入一个元素。如果成功插入则返回真。
//deQueue() : 从循环队列中删除一个元素。如果成功删除则返回真。
//isEmpty() : 检查循环队列是否为空。
//isFull() : 检查循环队列是否已满。
//free():释放空间
typedef struct 
{
 int* _a;
 int _front;//队首
 int _rear;//队尾
 int _k;
} MyCircularQueue;

/** Checks whether the circular queue is empty or not. */
//判断为空的条件即是队尾等于队首
bool myCircularQueueIsEmpty(MyCircularQueue* obj) 
{
 return obj->_front == obj->_rear;
}

/** Checks whether the circular queue is full or not. */
//判断是否已满的条件是(队尾大小+1)%(容量大小+1)==  队首大小。
bool myCircularQueueIsFull(MyCircularQueue* obj) {
 return ((obj->_rear + 1) % (obj->_k) == (obj->_front));
}

/** Initialize your data structure here. Set the size of the queue to be k. */
MyCircularQueue* myCircularQueueCreate(int k) 
{
 MyCircularQueue* Queue = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
 Queue->_a = (int*)malooc(sizeof(int)*(k + 1));
 Queue->_front = 0;
 Queue->_rear = 0;
 Queue->_k = k;
}

/** Insert an element into the circular queue. Return true if the operation is successful. */
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) 
{
 assert(obj);
 if (myCircularQueueIsFull(obj))
 {
  return false;
 }
  obj->_a[obj->_rear] = value;
 obj->_rear++;
 if (obj->_rear == obj->_k + 1)
 {
  obj->_rear = 0;
 }
 return true;
}

** Delete an element from the circular queue. Return true if the operation is successful. */
bool myCircularQueueDeQueue(MyCircularQueue* obj) 
{
 assert(obj);
 if (myCircularQueueIsEmpty(obj))
 {
  return false;
 }
  obj->_front++;
 if (obj->_front == obj->_k + 1)
 {
  obj->_front = 0;
 }
 return true;
}

/** Get the front item from the queue. */
int myCircularQueueFront(MyCircularQueue* obj) 
{
 assert(obj);
 if (myCircularQueueIsEmpty(obj))
 {
  return -1;
 }
 return obj->_a[obj->_front];
}

/** Get the last item from the queue. */
int myCircularQueueRear(MyCircularQueue* obj) 
{
 assert(obj);
 if (myCircularQueueIsEmpty(obj))
 {
  return -1;
 }
  if (obj->_rear == 0)
 {
  return obj->_a[obj->_k];
 }
 return obj->_a[obj->_rear - 1];
}

void myCircularQueueFree(MyCircularQueue* obj) 
{
 free(obj->_a);
 free(obj);
}

需注意:循环队列是逻辑上循环,物理上不循环的。

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值