顺序循环队列&链队列

目录

顺序队列

         顺序循环队列实现

创建循环队列

循环队列的入队

循环队列的出队

创建链队

一、链队为空 

二、链队初始化

二、链队建立/入队

三、链队出队


          队列与栈同样是一种操作受限制的线性表,队列的特点是先进先出即 FIFO,一般在尾部插入头部删除,在通常使用过程中,顺序队列经常产生假溢出等情况,因此时常采用顺序循环队列

除顺序队列外还有链队,双端队列等。接下来先从顺序循环队列开始……

顺序队列

头尾指针与顺序栈是一个思路,本质其实是数组的下标,如图所示,起始双指针指向同一位置,因此也可以推导出队列判空的条件即Q.front=Q.rear。始终保持rear指向后继元素

接下来可以进行入队操作,即:先在rear位置插入元素,然后再将rear向后移动。始终保持rear指向后继空元素位置,入队过程中front指针是始终没有变化的

出队操作与之相反,因队列的特性。出队应在队首进行即:先将front位置的元素删除,再将front移动,出队过程中rear无变化如图所示

 由下图可以看出单纯的顺序队列会产生假溢出的情况,即当Q.rear=Q.MAX时,已无法再入队,但队列前部分还有空缺。因此采用循环队列可解决此情况。

 除改为循环队列外,还需要进行一些改进方便使用,即始终保留一空位。原因如下图,如不保留一块空位则会导致队空队满的条件皆为:Q.front=Q.rear  不合理,由此图也可看出,Q.rear指向当前尾结点的后继元素,而非当前尾结点

 饼状表示图

 顺序循环队列实现

一、求队列长度

如上图所示,正常队列的队列长度为front-rear, 当变为顺序循环队列后,长度已经不再是front-rear, 经计算要满足两种情况的长度为:

#define MAXSIZE  6
(Q.rear-Q.front+MAXSIZE)%MAXSIZE    //MAXSIZE 为数组长度
 

 二、队

#define MAXSIZE  6
(Q.rear+1) % MAXSIZE = Q.front 

​ 三、队空

rear=front

创建循环队列

静态创建(不可扩容):步骤:① front=rear=-1,初始化数组下标位置 ②rear+1 ③赋值

创建方法各不相同,基本合理即可,图解参照上图栈空情况反推即可

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 5
typedef struct LinkQue {
	int data[MAXSIZE];
	int front;      //头下标
	int rear;      // 尾下标
}LinkQue;

LinkQue CreatQue(LinkQue Q,int arr[]) {
	Q.front = Q.rear = 0;             //首尾下标为0
	for (int i = 0;i < MAXSIZE-1;i++) {  //循环队列有一个空位置
		Q.rear = Q.rear + 1;        //尾指针向后移动
		Q.data[i] = arr[i];           //赋值
		printf("%d\n",Q.data[i]);
	}
	return Q;
}

循环队列的入队

void AddQue(LinkQue* Q1, int e) {   //入队 e
	if ((Q1->rear + 1) % MAXSIZE == Q1->front)  //判断队满条件
		printf("xww");
	else {
		Q1->data[Q1->rear] = e;               //新元素加入队尾 
		Q1->rear = (Q1->rear + 1) % MAXSIZE;   //队尾指针加一 
}

循环队列的出队

void Delete(LinkQue*Q,int e) {   //入队 e
	if (Q.rear==Q.front)         //判断队空条件
	return false;
	else {
		e=Q.data[Q.front];
        Q.front=(Q.front+1)%MAXSIZE;   //指针+1
	}
}

创建链队

链式队列有两个指针分别指向头结点与尾结点,因队列只能头插尾删所以相对带头尾节点的链表简单很多。链队也分为带头结点与不带头结点两种。

链队为链式存储结构,因此与循环队列,顺序队列不同在于,可以无需考虑队满的情况,但仍需考虑空链表的情况。因此首先考虑链表为空的条件。

一、链队为空 

二、链队初始化

初始化即创建只有头结点的链队,头尾指针指向头结点。方便后期插入以建立链队。如上图

typedef struct Qnode {
	int data;               //存放指针front,rear
	QueuePtr next;          //与链表相似 
}Qnode,*QueuePtr;
typedef struct {
	QueuePtr front;        //头指针
	QueuePtr rear;        //尾指针
}LinkQueue;

LinkQueue InitQueue(LinkQueue Q) {
	Q.front = Q.rear = (QueuePtr)maclloc(sizeof(Qnode));  //开辟空间并双指针指向
	Q.front->next = NULL;                                //头节点为NULL
	return Q;
}

二、链队建立/入队

链队插入只能在队尾插入,每次插入的元素next域都为NULL,需要将尾指针Q.rear指向尾结点

 代码实现

LinkQueue CreatQueue(LinkQueue Q,int arr[]) {
	for (int i = 0;i < 5;i++) {
		QueuePtr p = (QueuePtr)malloc(sizeof(Qnode));  //开辟空间
		p->data[i] = arr[i];              //赋值
		p->next = NULL;                   //先将新建节点的next置空
		Q.rear->next= p;                  //将前一节点与p相连
		Q.rear = p;                       //尾指针 指向尾结点
	}
	return Q;
}

三、链队出队

出队除了要进行队空判断外还有一种特殊情况,即:只有头结点与首元结点

代码实现

void DeleteQueue(LinkQueue Q) {
	if (Q.front==Q.rear) {
		printf("空了");    //判断是否为空队
	}
	else {
		QueuePtr p = Q.front->next;   //p为首元结点 即要删除的节点
		int *e = p->data;              //存下要删除的地址
		Q.front->next = p->next;      
		if (Q.rear==p) { Q.front = Q.rear; }  //如果只有尾结点一个元素
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序lee

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

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

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

打赏作者

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

抵扣说明:

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

余额充值