数据结构--2.4 队列


今天敲得是队列,有两个不同的实现方式:链式队列和循环队列。
队列只允许在一端插入数据操作,称为队尾,在另一端进行删除数据操作,称为队首。队列具有先进先出的特性。

链式队列

结构体定义

#include <stdio.h>
#include <malloc.h>

typedef struct Node{
	int data;
	struct Node *next;
}NODE,*PNODE;

typedef struct Queue{
	PNODE front;
	PNODE rear;
}*QUEUE;

创建

QUEUE initLinkQueue()
{
	QUEUE resultPtr = (QUEUE)malloc(sizeof(Queue));
	PNODE headPtr = (PNODE)malloc(sizeof(Node));
	
	headPtr->next = NULL;
	
	resultPtr->front = headPtr;
	resultPtr->rear = headPtr;
	
	return resultPtr;
}

这里出了创建函数之后headPtr就不存在了,因为是临时变量。但是resultPtr依然存在,因为我们把它返回了。

入队

void enQueue(QUEUE paraQueue,int paraVal)
{
	PNODE p;
	p=(PNODE)malloc(sizeof(Node));
	
	p->data = paraVal;
	p->next = NULL;
	
	paraQueue->rear->next = p;
	paraQueue->rear = p;
}

出队

int deQueue(QUEUE paraQueue)
{
	int val;
	PNODE p;
	
	if(paraQueue->front == paraQueue->rear )
	{
		printf("the queue if empty.\r\n");
		return -1;
	}
	
	p = paraQueue->front->next;
	val = p->data;
	paraQueue->front->next = paraQueue->front->next->next;
	
	if(paraQueue->rear == p)
	{
		paraQueue->front = paraQueue->rear;
	}
	free(p);
	
	return val;
}

运行结果

1 2 3
deQueue is 1
2 3

链式队列的时间复杂度为O(1)。
链式队列的逻辑比较简单,所以没有过多的阐述,相比之下循环队列会稍显复杂。

循环队列

循环队列利用数组来实现。我觉得写出这个代码主要解决两个问题,一个是如何去判断满,而二是如何让整个队列循环起来。(好废话)

结构体定义

#include <stdio.h>
#include <malloc.h>

#define MAX_SIZE 5

typedef struct Circle{
	int data[MAX_SIZE];
	int head;
	int tail;
}*CIRCLE;

创建

CIRCLE initCircleQueue()
{
	CIRCLE resultPtr = (CIRCLE)malloc(sizeof(Circle));
	
	resultPtr->head = 0;
	resultPtr->tail = 0;
	
	return resultPtr;
}

判断空和满

先看代码

bool is_full(CIRCLE paraQueue)
{
	if((paraQueue->tail+1)%MAX_SIZE == paraQueue->head )
	{
		return true;
	}else
	{
		return false;
	}
}

bool is_empty(CIRCLE paraQueue)
{
	if(paraQueue->tail == paraQueue->head )
	{
		return true;
	}else
	{
		return false;
	}
}

判断空其实很简单,当我们的队首和队尾标记都相同时这个队列就空了。比较复杂的是判断满,我们先看图:
在这里插入图片描述
一开始感觉当我的队尾追上队首的时候就满了,但是队尾等于队尾的时候也有可能是空,所以这种判断方法就失效了。那我们可不可以少放一个元素,让rear+1等于队首的时候为满呢,就像这样:
在这里插入图片描述
那答案是可以的。所以判断满的方式就变成了:(paraQueue->tail+1)%MAX_SIZE == paraQueue->head。

入队

那我们又要想了,在入队的时候,我们能够一直让tail++吗?我们的数组是有大小的,当tail超过这个大小的时候我们应该如何让数组循环起来呢。
我们选择对tail取余。我们直接让tail%MAX_SIZE,这样得到的数值就会始终在MAX_SIZE的范围之内了

bool enCircleQueue(CIRCLE paraQueue,int data)
{
	if(is_full(paraQueue))
	{
		printf("the queue is full.\r\n");
		return false;
	}
	
	paraQueue->data[paraQueue->tail%MAX_SIZE] = data;
	paraQueue->tail ++ ;
	
	return true ;
}

出队

int deCiecleQueue(CIRCLE paraQueue)
{
	int val;
	
	if(is_empty(paraQueue))
	{
		printf("the queue is empty.\r\n");
		return -1;
	}
	
	val = paraQueue->data[paraQueue->head%MAX_SIZE];
	paraQueue->head ++ ;
	
	return val;
}

运行结果

the queue is full.
1 2 3 4
delete is 1
delete is 2
3 4
delete is 3
delete is 4
the queue is empty.
delete is -1

循环队列的时间复杂度也是O(1)。

总结

在理解了这两个算法之后我自己重新敲了这两个代码。我个人认为其实这两段代码都不算很复杂,最主要的是理解整个逻辑,以及注意自己对细节处的处理。
数据结构学习到现在我最大的心得就是要学会像计算机一样去思考。人的逻辑和计算机的逻辑是存在很大的差别的,应该尝试把人的逻辑转化成计算机的逻辑,用代码呈现出来。

### CentOS 7 中挂载名为 `data` 的磁盘分区教程 #### 准备工作 在开始挂载之前,需要确认目标磁盘的状态以及其是否已经存在分区。可以通过命令 `fdisk -l` 来查看当前系统的磁盘列表及其状态[^1]。 假设我们发现一块未使用的磁盘 `/dev/sdb` 并计划将其用于存储数据,命名为 `data` 分区,则需按照以下流程完成操作: --- #### 步骤一:新建分区 如果该磁盘尚未划分任何分区,可以使用 `fdisk` 工具来创建一个新的分区: ```bash fdisk /dev/sdb ``` 进入交互模式后执行如下指令: - 输入 `n` 创建新分区; - 按提示输入分区号(默认即可)、起始扇区位置(通常按回车接受默认值)和结束扇区大小(可指定具体容量或留空表示占用剩余全部空间); - 完成配置后保存更改退出工具前记得通过输入字母 `w` 提交修改到实际设备上生效[^2]。 --- #### 步骤二:格式化分区 一旦成功建立好新的分区比如说是 `/dev/sdb1`, 接下来就需要对该分区进行文件系统初始化处理以便能够正常读写数据。这里推荐采用支持良好且兼容性强的 ext4 文件系统作为例子演示过程: 运行下面这条命令实现上述目的: ```bash mkfs.ext4 /dev/sdb1 ``` 此动作会将选定的目标区域标记为可用作长期储存用途,并赋予相应属性结构使得后续步骤得以顺利开展下去[^3]. --- #### 步骤三:创建挂载点目录 为了方便管理和识别,在正式关联之前最好预先定义好一个专门用来接收对应资源映射关系的目的地路径名——即所谓的“挂载点”。在这里我们可以简单设立这样一个叫做 “/mnt/data” 的地方供稍后的连接指向之用: ```bash mkdir /mnt/data ``` 这一步非常重要因为它决定了之后访问这块新增加的空间时所遵循的标准地址形式是什么样子样的. --- #### 步骤四:临时挂载测试 现在终于来到了激动人心的一刻! 让我们将刚刚准备完毕的一切组合起来看看效果如何吧: ```bash mount /dev/sdb1 /mnt/data ``` 此时应该就可以立即体验到成果啦~ 不过请注意这种方式只会在当前 session 生命周期内有效; 如果重启机器或者断开电源再重新启动的话则需要再次手动重复以上操作才行哦~ 不过不用担心还有更持久的办法等着咱们呢! --- #### 步骤五:设置开机自动挂载 为了让每次开机都能自动加载我们的自定义配置而不必每次都亲力亲为期盼奇迹发生似的去敲那些繁琐无比却又必不可少的关键字串儿们... 我们得编辑一份特别重要的文档 —— fstab (filesystem table). 打开这个神秘而又强大的文本档: ```bash vi /etc/fstab ``` 然后追加一行记录描述刚才所做的安排详情, 形式大致像这样子的样子: ``` UUID=your-partition-uuid /mnt/data ext4 defaults 0 2 ``` 当然啦,"your-partition-uuid" 这部分可不是随便乱填就能奏效滴哟! 需要借助一个小技巧获取确切数值: ```bash blkid | grep sdb1 ``` 找到对应的 UUID 后替换进去就万事俱备只欠东风咯! 最后别忘了验证一下语法正确与否以防万一嘛~ ```bash mount -a ``` 如果没有报错说明一切安好无虞矣!🎉 --- ### 总结 至此为止你应该已经掌握了整个过程中涉及到的各项关键技术要点了吧?希望这份详尽指南能帮助你在 Linux 系统运维道路上迈出更加坚实稳健的步伐! ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值