当前位置: 首页 > news >正文

数据结构-栈和队列的应用

目录

  • 前言
  • 一、栈的应用(迷宫问题)
    • 1.1 问题描述
    • 1.2 算法选择
    • 1.3 算法精化
    • 1.4 算法实现
    • 1.5 问题结果
  • 二、队列的应用(农夫过河问题)
    • 2.1 问题描述
    • 2.2 算法选择
    • 2.3 算法精化
    • 2.4 算法实现
    • 2.5 问题结果
  • 总结

前言

本篇文章使用两个例子说明栈和队列的应用,
对于迷宫问题,使用栈实现深度优先策略解决迷宫问题;
对于农夫过河问题,使用队列实现广度优先策略解决农夫过河问题。

一、栈的应用(迷宫问题)

1.1 问题描述

从入口进入迷宫,如何可以尽快找到迷宫的出口?这是一个十分有趣的经典游戏。
迷宫可用如图1.1所示的方块表示,其中每个元素或为通道(以空白方块表示),或为墙(以带阴影的方块表示)。迷宫问题要求的是:从入口到出口的一个以空白方块构成的(无环路径)。
在这里插入图片描述

图1.1 迷宫的图形表示

1.2 算法选择

求解迷宫问题的简单方法是:从入口出发,沿某一方向进行探索,若能走通,则继续往前走;否则沿原路返回,换一方向再进行探索,直到找到了一个出口,或者所有可能的探索都以失败而告终。这类探索方法统称为回溯法,也可以称为深度优先探索方法。实现深度优先探索的工具是栈。
其算法的基本框架如下:

mazeFrame(void)
{创建一个(保存探索过程)空栈;把入口位置压入栈中;while(栈不为空){取栈顶位置并设置为当前位置;while(当前位置存在试探的可能性){取下一试探位置;if(下一位置是出口)打印栈中保存的探索过程然后返回;if(下一位置是通道)把下一位置进栈并且设置为当前位置;}}	
}

1.3 算法精化

在求解程序中,迷宫可用二维数组maze[m][n]表示,其中数组中元素是0表示通道,1表示墙。
入口坐标为(1,1)
出口坐标为(6,9)
在这里插入图片描述

图1.2 迷宫的二维数组表示

为了细化前面的框架,还要考虑试探方向的表示
假设某时刻所在迷宫的位置坐标为(i,j),相邻的四个位置分别标E、S、W、N表示东、南、西、北方向;
为了简化算法,可以建立一个数组direction,这个数组给出了相对于位置(i,j)的4个方向上,i和j的增量值
使用一个变量elem_d表示试探方向,
0-表示方向E
1-表示方向S
2-表示方向W
3-表示方向N
则某个方向的试探位置i和j的变化值为

new_i = i + direction[elem_d][0] (新的行坐标)
new_j = j + direction[elem_d][1] (新的列坐标)例如,当位置坐标为(3,4)时
elem_d = 0 表示试探方向为E
则试探坐标为
new_i = i + direction[0][0] = 3 + 0 = 3
new_j = j + direction[0][1] = 4 + 1  = 5
则新坐标为(3,5)

在这里插入图片描述

图1.3 迷宫中方向的表示

另外,为了避免走到已经试探过的位置(包括现在探索路径上的和曾经在探索路径上的位置),凡是已经探索过的位置都应该做上标记。根据约定,值为1表示墙,0表示通道,那么,凡是探索过的位置可以赋予一个既非0又非1的值,假设取值为2(这样做可以节省空间,缺点是破坏了maze数组的状态;否则要设置一个与迷宫那样大小的数组来保存标记)。一旦将某一位置(i,j)纳入到当前路径中,就将maze[i][j]设置为2。为了记录探索路径中当前位置以及在该位置上的试探方向,算法设置了一个栈,栈中元素包括三项,分别记录当前位置的行坐标、列坐标和以及在该位置上的试探方向。

//栈数据元素类型
struct ElemType {int x;			//行坐标int y;			//列坐标int direction;	//试探方向
};

1.4 算法实现

经过上述设计,求迷宫中一条路径上的算法可以从入口开始,对每个当前位置都从E方向(elem_d = 0)开始试探,若不能通过,则顺时针依次试探S方向、W方向和N方向。当选定一个可以前进的位置,要把当前所在的位置纳入探索路径中,并将当前所在位置以及试探方向记录下来,以便走不通时可以顺序原路一步步回退,每退一步以后接着试探在该位置上的其他未试探过的方向,如此循环,直到找到出口。

/*
int(*maze)[11] 数组指针类型,表示传入迷宫数组
int(*direction)[2] 数组指针类型,表示传入direction数组
int entrance_x  入口行坐标
int entrance_y  入口列坐标
int eixt_x		出口行坐标
int exit_y 		出口纵坐标
*/
void mazePath(int (*maze)[11], int(*direction)[2], int entrance_x, int entrance_y, int exit_x, int exit_y)
{int elem_x = 0;int elem_y = 0;int elem_d = 0;int newDirection_x = 0;int newDirection_y = 0;//初始化栈SeqStack stack = { 0 };initSeqStack(&stack);//初始化入口坐标元素SElemType element = { 0 };maze[entrance_x][entrance_y] = 2; //从入口开始标记element.x = entrance_x;			 element.y = entrance_y;element.direction = -1;		     //未试探任何方向if (!pushSeqStack(&stack, element))	 //将入口点进栈{destroySeqStack(&stack);return;}while (!isEmptySeqStack(&stack))   //走不通时,一步步回退{if (!popSeqStack(&stack, &element))  //获取栈顶元素并出栈{destroySeqStack(&stack);return;}elem_x = element.x;elem_y = element.y;elem_d = element.direction+1;while (elem_d <= 3)  //一次试探一个方向{newDirection_x = elem_x + direction[elem_d][0];newDirection_y = elem_y + direction[elem_d][1];if (newDirection_x == exit_x && newDirection_y == exit_y && maze[newDirection_x][newDirection_y] == 0)//走到出口{element.x = elem_x;element.y = elem_y;element.direction = elem_d;if (!pushSeqStack(&stack, element)){destroySeqStack(&stack);return;}element.x = newDirection_x;element.y = newDirection_y;element.direction = 4;if (!pushSeqStack(&stack, element)){destroySeqStack(&stack);return;}printf("The revers path is:\n"); //打印路径while (!isEmptySeqStack(&stack)){if (!popSeqStack(&stack, &element)){destroySeqStack(&stack);return;}printf("The node is: (%d %d)\n", element.x, element.y);}//销毁栈destroySeqStack(&stack);return;}if (maze[newDirection_x][newDirection_y] == 0) //走到没走过的点{maze[newDirection_x][newDirection_y] = 2;   //标记走过的点element.x = elem_x;element.y = elem_y;element.direction = elem_d;if (!pushSeqStack(&stack, element))  //进栈{destroySeqStack(&stack);return;}elem_x = newDirection_x;  //下一点转换成当前点elem_y = newDirection_y;elem_d = -1;}elem_d++;}}printf("The path has not been found!\n");//销毁栈destroySeqStack(&stack);
}

注意: 顺序栈的代码已经省略

1.5 问题结果

二、队列的应用(农夫过河问题)

2.1 问题描述

一个农夫带着一只狼、一只羊和一颗白菜,身处河的南岸。农夫要把这些东西全部运到河的北岸。问题是农夫只有一条小船,船小到只能容下农夫和一件物品,当然,船只有农夫能撑。另外,因为狼能吃羊,而羊能吃白菜,所以,农夫不能留下羊和狼或者羊和白菜单独在河一边,自己离开。好在狼属于食肉动物,它不吃白菜。请问农夫该采取什么方案,才能将所有的东西安全运过河呢?

2.2 算法选择

求解这个问题的最简单的方法是逐步进行试探。每一步都在前一步选择基础上搜素下一步的所有可能的状态。用计算机实现上述系统搜索过程,可以采用两种不同的策略,一种是广度优先搜索(breadth first);另一种是深度优先搜索(depth first)。实现广度优先搜索的工具是队列;实现深度优先搜索的工具是栈。本节讨论队列的应用,所以重点介绍广度优先搜索策略。
广度优先搜索的思想就是,在搜索过程中,总是首先搜索下面一步的所有可能情况,然后再进一步考虑更后面的各种情况。要实现广度优先搜索,一般都采用队列作为辅助结构,把每一步所有可能达到的状态都列举出来,放在这个队列中,然后顺序取出来分别进行处理,在处理中又再把下一步的情况全部放在队列里。由于队列的操作原则是先进先出,所以,只有在前一步的所有情况都处理完后,才能开始后面一步各情况的处理。
以遍历二叉树为例,使用广度优先搜索策略,进行层序遍历。
在这里插入图片描述

图2.1 广度优先遍历二叉树

2.3 算法精化

要模拟农夫过河问题,首先需要选择一个对问题中每个角色的位置进行描述的方法。一个很方便的方法是用4位二进制数顺序分别表示农夫、狼、白菜和羊的位置。例如,用0表示农夫或某物品在河的南岸,1表示在河的北岸。因此,整数5(其二进制表示为0101)表示农夫和白菜在河的南岸,而狼和羊在北岸。这时,农夫不在,因此狼会把羊吃掉,所以是一种不安全的状态。问题的初始状态是整数0(其二进制为0000);而问题的终结状态是整数15(其二进制表示为1111)。
在这里插入图片描述

图2.2 二进制位置表示图

用整数location表示用上述方法描述的状态,可以用下面的4个函数从上述状态得到每个角色所在位置的代码。函数返回值为真(1)表示农夫或物品的位置在河的北岸,否则在南岸。

//农夫过河问题
//个体判断函数
/*	四位二进制数分别表示农夫,狼,白菜,羊的位置0 表示在南岸  1 表示在北岸初始状态 location = 0000(二进制) 表示农夫,狼,白菜,羊都位于河的南岸使用按位 & 操作,取出每个位置的信息,例如 location & 0x08 取出农夫的位置信息
*///取出农夫位置信息
int farmer(int location)
{return (0 != (location & 0x08));
}//取出狼位置信息
int wolf(int location)
{return (0 != (location & 0x04));
}//取出白菜位置信息
int cabbage(int location)
{return (0 != (location & 0x02));
}//取出羊位置信息
int goat(int location)
{return (0 != (location & 0x01));
}

此外,还应该分析问题中的所有角色构成的状态,确定其中那些状态是安全的,哪些是不安全的。因为,单独留下白菜和羊或单独留下狼和羊在某一岸是不安全的,所以安全状态的判断可以使用下面的函数实现。

//安全状态的判断函数
/*不能单独留下狼和羊,例如 location = 0101 是一种不安全的状态不能单独留下白菜和羊,例如 location = 1100 是一种不安全的转态安全返回 1不安全返回 0
*/int safe(int location)
{//判断羊和白菜是否单独if ((goat(location) == cabbage(location)) && (farmer(location) != goat(location))){return 0;}//判断狼和羊是否单独if ((wolf(location) == goat(location)) && (farmer(location) != goat(location))){return 0;}return 1;   //其他状态安全
}

2.4 算法实现

完成了上面的准备工作后,现在的问题变成:从初始状态二进制0000出发,寻找一种全部由安全状态构成的、能够实现的状态变迁序列(序列中的每状态都可以从前一状态通过农夫带东西划船过河到达),到达最终状态二进制1111.为避免不必要的重复,在序列中不应该出现重复的状态。
根据广度优先搜索的思想,算法中需要使用一个整数队列moveTo,把搜索过程中每一步所有可能到达的状态都保存起来。队列中的每个元素表示可以安全到达的中间状态。
另外,使用一个整数数组rooute记录已被访问过的各个状态,以及已被发现的能够到达这些状态的前驱状态。由于在这个问题中需要列举的所有状态(二进制0000~1111)一共16种,所以route数组只需要使用16个元素。route的每个元素初始化为-1,每当在队列中加入一个新的状态时,就把route中以该状态作下标的元素的值改为达到这个状态的前一转态的下标值。所以数组的第i个元素不仅记录了状态i是否已经被访问过,同时对于以及被访问过的状态,还保存了这个状态的前驱状态下标。算法结束后,可以利用route数组元素的值生成一个正确的路径。
在这里插入图片描述

图2.3 route数组

代码实现如下:

//农夫问题求解/*从初始状态二进制0000出发,寻找一种全部由安全状态构成、能够实现的状态变迁序列(序列中的每个状态都可以从前一状态通过农夫带东西划船过河到达)到达最终的状态1111。为避免不必要的重复,在序列中不应该出现重复的状态整数队列moveTo:把搜索过程中每一步所有可能到达的状态都保存起来。队列中的每个元素表示可以安全到达的中间状态整数数组route:用于记录已被访问过的各个状态,以及已被发现的能够到达这些状态的前驱状态由于在这个问题中需要列举的状态(二进制0000~1111)一共16种,则数组长度大小为16每个数组的元素值初始化为-1每当在队列中加入一个新的状态时,就把route中以该状态做下标的元素的值改为达到这个状态的下标值数组的第i个元素不仅记录状态i是否已被访问过,同时对于已被访问过的状态,还保存了这个状态的前驱状态算法结束后,可以利用route数组元素的值生成一个正确的状态路径
*/void farmerProblem()
{int movers, location, newlocation;int route[16];				//用于记录已考虑的状态路径struct SeqQueue moveTo;		//用于记录可以安全到达的中间状态initSeqQueue(&moveTo);		//初始化队列enSeqQueue(&moveTo, 0x00);	//初始状态二进制0000入队for (int i = 0; i < 16; i++)//初始化数组route{route[i] = -1;}route[0] = 0;while (!isEmptySeqQueue(&moveTo) && (route[15] == -1)){getQElemSeqQueue(&moveTo, &location);	//取出队头状态为当前状态QElemType e;deSeqQueue(&moveTo, &e);//循环值依次表示羊、白菜、狼、农夫的移动情况//movers的值用二进制表示依次为0001(羊)、0010(白菜)、0100(狼)、1000(农夫)for (movers = 1; movers <= 8; movers <<= 1){if ((0 != (location & 0x08)) == (0 != (location & movers))) //农夫与移动的物品在同一岸{// 0x08 | movers 得到的结果表明农夫或物品应该在船上,物品无法单独过河// location ^ (0x08 | movers) 把坐船过河的农夫与物品的状态翻转newlocation = location ^ (0x08 | movers);			//计算新状态if (safe(newlocation) && route[newlocation] == -1)	//新状态安全且未处理{route[newlocation] = location;					//记录旧状态且作为新状态的前驱enSeqQueue(&moveTo, newlocation);				//将新状态入队}}}}if (route[15] != -1){printf("The reverse path is :\n");for (location = 15; location >= 0; location = route[location]){printf("The location is : %d\n", location);if (location == 0){exit(0);}}}else{printf("No solution\n");}
}

注意:这里实现队列的代码已省略,感兴趣可查看文章:https://blog.csdn.net/pyc68/article/details/145093486?spm=1001.2014.3001.5501

算法开始时,把初始状态为0(表明人和物都在南岸)放入队列中。while循环时,只要队列不为空便取出队头元素,for循环用于列举所有可以移动的角色(包括农夫本身,用movers表示),for循环的增量表达式里使用了左移位操作,循环值依次为1、2、4、8,分别表示羊、白菜、狼和农夫的移动情况。由于在每一次移动时,农夫都必须改变状态,所以只有农夫与被移动的东西在同一岸时,农夫才可以将其带走。当然,农夫可以什么都不带,单独过河。将变量movers与二进制0x08进行按位异或运算,所得结果为1,表明相应的农夫或物品应该在船上,再将原有状态与这个结果进行一次按位异或运算,得到移动后的一个新状态。最后检验新状态是否安全,是否未被处理过。如果成立,就确认这个状态转换可行(把这个状态放入队列中,并且修改route数组的值)

2.5 问题结果

图2.4标出了送入队列的各个状态(位置)和广度优先搜索的顺序编号。
通过图2.4得出一条从0000到达1111的路径:
0000-1001:农夫把羊从南岸带到北岸
1001-0001:农夫独自从北岸回到南岸
0001-1011:农夫把白菜从南岸带到北岸
1011-0010:农夫把羊从北岸带回南岸
0010-1110:农夫把狼从南岸带到北岸
1110-0110:农夫独自从北岸回到南岸
0110-1111:农夫把羊从南岸带到北岸

在这里插入图片描述

图2.4 广度优先搜索的结果和顺序图

总结

迷宫问题完整代码: https://gitee.com/PYSpring/data-structure/tree/master/maze_code
农夫过河问题完整代码:https://gitee.com/PYSpring/data-structure/tree/master/queue_code

相关文章:

数据结构-栈和队列的应用

目录 前言一、栈的应用&#xff08;迷宫问题&#xff09;1.1 问题描述1.2 算法选择1.3 算法精化1.4 算法实现1.5 问题结果 二、队列的应用&#xff08;农夫过河问题&#xff09;2.1 问题描述2.2 算法选择2.3 算法精化2.4 算法实现2.5 问题结果 总结 前言 本篇文章使用两个例子…...

SpringBoot Bug 日志

Spring 循环依赖问题 Bug如下 wxMpConfiguration → subscribeHandler → wxMsgServiceImpl → wxMpConfiguration 解决方案 方案实施方式注意事项接口抽象定义 WxMpService 接口&#xff0c;通过接口注入最佳设计实践 Setter 注入对非必要依赖使用 setter 方法降低耦合度 L…...

halo发布文章的插件问题分析

前言 在准备发文到 halo 系统的时候提示错误如下&#xff0c;全是乱码 尝试将 halo 插件卸载后&#xff0c;再将插件目录下的文件全部删除 插件目录在 C:\Users\Administrator\.vscode\extensions\halo-dev.halo-1.3.0 然后再重新安装插件&#xff0c;在进行初始化的时候依然…...

2.5 模块化迁移策略:从传统项目到模块化系统

模块化迁移策略&#xff1a;从传统项目到模块化系统 将传统 Java 项目迁移至 JDK 9 模块化系统是一项系统性工程&#xff0c;需分阶段实施以降低风险。以下是详细的迁移策略、工具使用和实战示例。 1. 迁移阶段划分 阶段目标关键操作阶段1&#xff1a;兼容性验证确保项目能在…...

java商城解决方案

数字化时代&#xff0c;电子商务已成为企业拓展市场的重要渠道。对于想要建立在线商店的企业来说&#xff0c;选择正确的技术堆栈至关重要。 Java作为一种成熟且广泛使用的编程语言&#xff0c;为构建购物中心提供了强大的功能和灵活性。 商城Java源码&#xff1a;商城开发的核…...

算法-哈希表篇05-四数相加II

四数相加II 力扣题目链接 题目描述 给你四个整数数组 nums1、nums2、nums3 和 nums4 &#xff0c;数组长度都是 n &#xff0c;请你计算有多少个元组 (i, j, k, l) 能满足&#xff1a; 0 < i, j, k, l < n nums1[i] nums2[j] nums3[k] nums4[l] 0 解题思路 把数…...

WPS或word接入智能AI

DeepSeek接入WPS 配置WPS &#xff08;1&#xff09;下载 OfficeAl助手插件: 插件下载地址:https://www.office-ai.cn/。 安装插件后&#xff0c;打开WPS&#xff0c;菜单栏会新增"OfficeAl助手”选项卡。 如果没有出现&#xff0c; 左上找到文件菜单 -> 选项 ,在…...

Leetcode:学习记录

一、滑动窗口 1. 找出数组中元素和大于给定值的子数组的最小长度 右指针从左到右遍历&#xff0c;在每个右指针下&#xff0c;如果去掉左边元素的元素和大于等于给定值则左指针右移一次&#xff0c;直到小于给定值&#xff0c;右指针右移一个。 2.找到乘积小于给定值的子数组…...

86.在 Vue 3 中使用 OpenLayers 自定义组件(放大、缩小、长度测量、面积测量)

摘要 在 WebGIS 开发中&#xff0c;OpenLayers 是一个非常强大的开源地图库&#xff0c;它可以在 Web 应用中渲染高效的地图。本篇文章将介绍如何在 Vue 3 中使用 OpenLayers&#xff0c;并封装一个自定义地图控件组件&#xff0c;实现地图的放大、缩小、长度测量和面积测量功能…...

http 与 https 的区别?

HTTP(超文本传输协议)和 HTTPS(安全超文本传输协议)是互联网通信的基础协议。随着网络技术的发展和安全需求的提升,HTTPS变得越来越重要。本文将深入探讨HTTP与HTTPS之间的区别,包括其工作原理、安全性、性能、应用场景及未来发展等。 1. HTTP与HTTPS的基本概念 1.1 HT…...

SAIL-RK3576单板运行7b的deepseek对话模型

大概流程&#xff1a; 使用ollama工具进行deepseek的模型部署和使用&#xff0c;先安装ollama工具&#xff0c;在使用ollama工具拉去deepseek模型&#xff0c;最后使用ollama工具加载deepseek模型进行对话...

独立C++ asio库实现的UDP Server

以下是一个使用独立的 C Asio 库实现的 UDP 服务器的示例代码。这个 UDP 服务器可以监听指定端口&#xff0c;接收客户端发送的数据&#xff0c;并将接收到的数据原样返回给客户端。 #include <iostream> #include <asio.hpp> #include <array>class UdpSer…...

SQL Server STUFF 函数的用法及应用场景

在 SQL Server 中&#xff0c;STUFF 函数是一种强大的字符串处理工具&#xff0c;常用于删除指定位置的字符并插入新的字符。通过这个函数&#xff0c;开发者能够灵活地修改字符串&#xff0c;从而在数据处理、字符串拼接和格式化等方面大显身手。本文将深入探讨 STUFF 函数的语…...

MongoDB进阶篇-索引

文章目录 1. 索引概述 2. 索引的类型 2.1 单字段索引 2.2 复合索引 2.3 其他索引 2.3.1 地理空间索引(Geospatial Index) 2.3.2 文本索引(Text Indexes) 2.3.3 哈希索引(Hashed Indexes) 3. 索引相关操作 3.1 查看索引 3.2 创建索引 3.3.1 创建单字段索引 3.3.2 创建复合…...

《机器学习数学基础》补充资料:柯西—施瓦茨不等式以及相关证明

《机器学习数学基础》 153 页&#xff0c;针对图 3-4-3&#xff0c;提出了一个问题&#xff1a;“点 A A A 到 W \mathbb{W} W 上的一个点的距离有无穷多个。现在&#xff0c;我们最关心的是其中最短的那个&#xff0c;怎么找&#xff1f;请参阅 3.6 节。”并且&#xff0c;在…...

VisionPro 划痕检测小练习

划痕检测,我这里用到的是Sobel算子和blob斑点匹配以及blob里面的形态学调整 Sobel 是一种在数字图像处理和计算机视觉领域广泛应用的算法&#xff0c;主要用于边缘检测 脚本展示 #region namespace imports using System; using System.Collections; using System.Drawing; …...

解析 2025 工业边缘计算:三大技术风向的影响力

工业数字化转型的加速&#xff0c;工业边缘计算市场正呈现出蓬勃发展的态势。展望 2025 年&#xff0c;以下三大技术将成为引领工业边缘计算发展的重要风向标。 其一&#xff0c;人工智能与边缘计算的深度融合。人工智能技术将更广泛地应用于工业边缘设备&#xff0c;实现更智…...

企语企业管理系iFair(F23.2_a0)在Debian操作系统中的安装

起因&#xff1a;在安装了F24.8版本后&#xff0c;发现生产用环境和测试、开发用环境还是分开的好。 旧版的用来实验、测试&#xff0c;新版的一步一步小心的配置、使用是比较稳妥的操作。因此&#xff0c;决定在KVM虚拟机上搭建一个F23.2版本的企语系统。 一、 存在的问题 而…...

如何在Flask中处理静态文件

哈喽,大家好,我是木头左! 本文将详细介绍如何在Flask中处理静态文件,包括如何配置静态文件夹、如何访问静态文件以及如何处理静态文件的缓存问题。 配置静态文件夹 在Flask中,你可以通过static_folder参数来指定静态文件夹。默认情况下,Flask会在项目的根目录下寻找名为…...

无人机飞行试验大纲

‌无人机飞行试验大纲‌ ‌编制日期‌&#xff1a;2025年02月11日 ‌一、试验目的与背景‌ 本次无人机飞行试验旨在验证无人机的飞行性能、控制系统稳定性、机体结构强度以及各项任务执行能力。随着无人机技术在各个领域的广泛应用&#xff0c;对其性能进行全面、系统的测试显得…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

《C++ 模板》

目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板&#xff0c;就像一个模具&#xff0c;里面可以将不同类型的材料做成一个形状&#xff0c;其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式&#xff1a;templa…...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型&#xff08;Primitive&#xff09; 和 对象类型&#xff08;Object&#xff09; 两大类&#xff0c;共 8 种&#xff08;ES11&#xff09;&#xff1a; 一、原始类型&#xff08;7种&#xff09; 1. undefined 定…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...