两款开源.NET工作流引擎 Elsa 与ccflow使用比较

news2025/1/21 15:42:11

相对java开源的工作流程引擎.net开源的工作流程引擎相对较少,这里整理两款.net开源工作流引擎,做一下对比使用。

elsa示例代码:Githubd地址:https://github.com/zhenl/MyElsa

ccflow下载地址:https://gitee.com/opencc/ccflow

CCFlow

1.概述:

ccflow是国产的一款流程引擎,好在中文文档,名词概念符合中国人的理解习惯,文档视频教程较多,官网都是开放的。Ccflow对国产化支持较好,国内乱七八糟的数据库兼容。

2.特性:

ccflow与表单引擎结合在一起,深化了的应用场景的融合,配置大于代码开发这也是设计者的设计理念吧。可以作为中间件的模式与自己的系统开发框架集成,支持基础的以代码驱动流程运转。

3.正文:

安装与集成,参考他们的手册,下载下来,直接安装上即可,比较顺利与其它软件安装不同的是,自动生成数据库,没有提供数据库脚本,创建一个新的数据库修改一下数据库连接即可,按照向导执行安装。

参考视频教程一步步的创建一个流程,功能点太丰富,主要击中在节点属性,流程属性上,这也是国产软件的“通病”,猛地感觉上手困难,仔细理解功能点描述,才能体会到设计者的用心,都是从实际应用中来的。

4.接口定义:

4.1接口高级开发

Ccflow的接口在流程属性里有定义,分为Url调用接口,sdk开发接口。

登录与门户API

  1. 首先要进行代码集成与组织机构的集成

  1. 其次在自己的系统登录界面,登录成功后要执行ccbpm的框架登录。

  1. 所谓的登录就是调用ccbpm的登录接口,如左边的代码所示。

// 如下代码需要写入您的系统校验密码与用户名之后。

string userNo = "zhangsan";

BP.WF.Dev2Interface.Port_Login(userNo);菜单

  1. 发起:一个操作员可以发起的工作

  1. 待办:等待处理的工作。

  1. 在途:我参与的,但是这条流程还没有结束的流程。

  1. 抄送:不需要我处理,但是需要我知晓的工作。

发起:

//获得指定人员的可以发起的流程列表,调用这个接口返回一个datatable, 可以参考一个demo实现发起列表的输出。

System.Data.DataTable dtStart = BP.WF.Dev2Interface.DB_GenerCanStartFlowsOfDataTable("zhangsan");

待办:

//获得指定人员的待办,调用这个接口返回一个datatable, 可以参考一个demo实现发起列表的输出。

DataTable dtTodolist = BP.WF.Dev2Interface.DB_GenerEmpWorksOfDataTable();在途:

//获得指定人员的在途,调用这个接口返回一个datatable ,代码参考:。

DataTable dtRuning = BP.WF.Dev2Interface.DB_GenerRuning();查询:

//ccbpm给你提供了一个link ,您可以调用这个link ,也可以自己去根据代码实现。

实现列表输出代码,请参考:

运行Demo: 查询创建WorkID

  1. 创建工作ID是启动流程的开始。

  1. ccbpm的工作ID是一个Int64位的整数,始终是按照顺序号+1产生的。

  1. 该workid全局唯一,并且没有重复性,该信息记录到Sys_Serial,WorkID的生成从100开始。

  1. 该workid全局唯一,并且没有重复性,该信息记录到Sys_Serial,WorkID的生成从100开始。

//传入流程编号,调用创建一个工作ID。

Int64 workid = BP.WF. Dev2Interface.Node_CreateBlankWork("001");发送 - 简单发送

  1. 工作发送就是让节点向下运动。

  1. 调用接口执行发送后,返回一个执行结果的对象,该对象是流程引擎执行过程中的变量。

  1. 解析该变量,可以检查出流程是否完成,运行到那一个节点上去了,下一个节点谁可以处理工作?

  1. 它的流向,是根据流程设计的规则执行的。

  1. 它的接收人,是根据接受人的规则确定的。

//传入流程编号, WorkID执行发送.

BP.WF.SendReturnObjs objs= BP.WF.Dev2Interface.Node_SendWork("001",workid);

// 检查流程是否结束?

bool isFlowOver = objs.IsStopFlow;

// 获得发送到那个节点上去了?

int toNodeID = objs.VarToNodeID;

string toNodeName = objs.VarToNodeName;

// 获得发送给谁了? 注意:这里如果是多个接受人员就会使用逗号分开。

string toEmpID = objs.VarAcceptersID;

string toEmpName = objs.VarAcceptersName;

// 输出提示信息, 这个信息可以提示给操作员.

string infoMsg = objs.ToMsgOfHtml();

发送 - 要指定发送给谁?发送到那个节点?(万能发送接口)

  1. 如果程序员知道下一步要发送给谁,发送到那一个节点的情况下,就可以调用这个接口。

  1. 该接口就会摆脱流程引擎设计的网关规则与接受人规则。

//如果确定了(或者自己计算好了)下一步要达到的节点,下一步的接受人,就可以按照如下格式调用。

BP.WF.SendReturnObjs objs = null; objs = BP.WF.Dev2Interface.Node_SendWork("001", workid, 103, "zhangsan" );

//发送给一个人,如果发送给多个人用逗号分开比如: zhangsan,lisi,wangwu

//下面调用方式,是知道要发送到那一个节点,但是不知道要发送给谁,让当前的节点定义的接受人规则来确定。

objs = BP.WF.Dev2Interface.Node_SendWork("001", workid, 103, null);

//下面调用方式,是知道要发送到那些人,但是不知道要发送到那个节点,让当前的节点定义的网关来确定。

objs = BP.WF.Dev2Interface.Node_SendWork("001", workid, 103,"zhangsan");

// 输出提示信息, 这个信息可以提示给操作员.

string infoMsg = objs.ToMsgOfHtml();

撤销

  1. 撤销是发送的逆向操作。

  1. 撤销可以调用ccbpm提供的撤销窗口完成,这是最简单的方式。

  1. 地址为:/WF/WorkOpt/UnSend.htm 参数为: FK_Flow,FK_Node,WorkID,FID,当前流程的4大参数。

  1. 如果需要在其他设备上工作,或者要自己写一个移交界面,请参考。

  1. 能否被撤销,是有当前活动节点的撤销规则所决定的。

  1. 撤销的功能显示在,在途的流程列表里,只有在途的工作才能被撤销。

  1. 在途工作:顾名思义,就是我参与的工作,并且工作尚未完成。

  1. 回滚流程,是在流程结束后需要重新在指定的节点,让指定的人员从新向下走。

/*

*执行撤销,返回撤销是否成功信息,如果抛出异常就说明撤销失败。

*撤销失败的原因多种,最有可能的是因为当前活动节点不允许撤销规则决定的。

*/

string msg= BP.WF.Dev2Interface.Flow_DoUnSend( workID);

回滚

  1. 回滚与撤销不同的是回滚是在流程完成以后的操作,并且回滚是由管理员操作的。

  1. 回滚流程,是在流程结束后需要重新在指定的节点,让指定的人员从新向下走。

//执行回滚,返回的是回滚执行信息,如果回滚失败,则会抛出异常。

string msg= BP.WF.Dev2Interface.Flow_DoRebackWorkFlow("001", workID, 103, "因为审批错误,需要回滚,从节点103重新开始审批。");退回

  1. 退回可以调用ccbpm提供的退回窗口完成,这是最简单的方式。

  1. 地址为:/WF/WorkOpt/ReturnWork.htm 参数为: FK_Flow,FK_Node,WorkID,FID,当前流程的4大参数。

  1. 如果需要在其他设备上工作,或者要自己写一个退回界面,请参考。

/*

* 1, 获得当前节点可以退回的节点,该接口返回一个datatable。

* 2, 一个节点能够退回到那写节点是由当前节点的退回规则确定的。

* 3, 调用退回需要三个参数:节点编号,工作ID, 流程ID, 对于线性流程FID始终等于0.

*/

System.Data.DataTable dtCanReturnNodes = BP.WF.Dev2Interface.DB_GenerWillReturnNodes(103, workid, 0);

// 返回的是可以退回的节点。

//执行退回,当前的节点是103,要退回的节点是105,

string msg = BP.WF.Dev2Interface.Node_ReturnWork("001", workid, 0, 103, 105, "您的申请信息不完整,请修改后重新发送。", false);

移交

  1. 移交也可以调用ccbpm提供的移交窗口完成,这是最简单的方式。

  1. 地址为:/WF/WorkOpt/Shift.htm 参数为: FK_Flow,FK_Node,WorkID,FID,当前流程的4大参数。

  1. 移交就是把自己所要做的工作交给其他人处理。

  1. 如果需要在其他设备上工作,或者要自己写一个移交界面,请参考。

/*

* 调用移交接口,传入必要的参数执行移交.

* FID 在线性流程上始终等于0.

*/

BP.WF.Dev2Interface.Node_Shift("001", 103, workid, 0, "zhangsan", "因我需要出差,所以特把工作移交给您。");

/*

* 撤销移交

* 如果在移交之后,发现不需要移交,就需要撤销回来,调用撤销移交接口。

*/

BP.WF.Dev2Interface.Node_ShiftUn("001", workid);加签

  1. 加签也可以调用ccbpm提供的加签窗口完成,这是最简单的方式。

  1. 地址为:/WF/WorkOpt/Shift.htm 参数为: FK_Flow,FK_Node,WorkID,FID,当前流程的4大参数。

  1. 加签就是把自己所要做的工作参考其他人意见,或者让其他人处理。

  1. 加签有两种模式:1,加签后由加签人发送到下一个节点。2,加签后由让加签人发送给当前人,由当前人发送给下一个节点。

  1. 如果需要在其他设备上工作,或者要自己写一个加签界面,请参考。

/*

* 调用加签接口,传入必要的参数执行.

* FID 在线性流程上始终等于0.

*/

//技术人员zhangsan接受工作后,点击发送还会发送给当前人员,由当前人员发送给下一节点。

string info1= BP.WF.Dev2Interface.Node_Askfor(workid, BP.WF.AskforHelpSta.AfterDealSendByWorker, "zhangsan", "这里需要您出具技术鉴定意见.");

//技术人员填写后,直接就发送了下一节点.

string info2 = BP.WF.Dev2Interface.Node_Askfor(workid, BP.WF.AskforHelpSta.AfterDealSend, "zhangsan", "这里需要您出具技术鉴定意见.");

//技术人员回复加签,在由当前人发送到下一个节点。

string infoReply = BP.WF.Dev2Interface.Node_AskforReply("001", 103, workid,0, "我已经出具了技术鉴定意见,请参考.");结束流程

  1. 流程结束有三种方式

  1. 第一种走到最后一个节点正常结束。

  1. 第二种在特定的节点上,用户需要终止流程向下运动(与删除流程不同)。

  1. 第三种在特定的节点上,用户需要删除流程。

/* * 手工的结束流程,这种方式会记录日志.

*/

string overInfo = BP.WF.Dev2Interface .Flow_DoFlowOver( workID, "该供应商找不到了,要结束掉该流程。");

/* * 删除流程,

* 删除流程有多种方式,用户可以根据自己的需求,调用不同的方式.

* 最后一个参数是是否删除子流程.

*/

//按照标记删除流程

string delInfo0 = BP.WF.Dev2Interface .Flow_DoDeleteFlowByFlag( workID, "我不需要请假了", true);

//彻底的删除流程,无日志记录.

string delInfo1 = BP.WF.Dev2Interface .Flow_DoDeleteFlowByReal( workID, "我不需要请假了", true);

//彻底的删除流程,有日志记录.

string delInfo2 = BP.WF.Dev2Interface .Flow_DoDeleteFlowByWriteLog("001", workID, "我不需要请假了", true);

4.2 代码事件定义

在流程属性里提供了开发接口demo, 这是提供开发者用的,需要写一个子类,然后编译里ddl里面去,通过反射,流程在运行的过程中,可以调用它。

开发人员只要重写这些事件方法即可,比如发送前,发送成功时,发送失败时,流程结束前,结束后,退回前,退回后等等。

Elsa

    • 概述

微软的Workflow Foundation基于.NET Framework,并且没有向.NET Core迁移的计划。

我们的很多项目使用了工作流引擎,这些项目向.NET Core以及更高版本迁移时遇到了不少问题,一直在寻找/开发适合的工作流引擎。

找到一些开源的项目,可以解决一些问题,还有些项目不是基于.NET生态的,但我希望能有一个长期稳定的基于.NET生态的项目,能够满足多种场景,可以替换原来的Workflow Foundation。

2.特性

1、同时支持编程工作流定义和配置工作流定义,最好有图形化的管理工具。

2、支持长期工作流。

3、支持有限状态机类型的工作流定义。

4、工作流引擎可以集成在应用中,也可以独立部署为工作流服务器,采用Web API的方式调用。

在我们跟踪的工作流相关项目中,Elsa一直在稳步发展,最新的版本(2.9)已经基本可以满足我们的上述要求了,在以后的版本也会增加对有限状态机的支持。

这里简单介绍一下如何创建工作流服务器和图形化的工作流配置管理应用。

3.正文

首先,使用Visual Studio 2022创建一个空的ASP.NET Core Web应用,名称为MyElsaServer。

项目创建完成后,使用NuGet包管理器,安装如下程序包:

Install-Package Elsa

Install-Package Elsa.Activities.Http

Install-Package Elsa.Persistence.EntityFramework.Sqlite

Install-Package Elsa.Server.Api

然后,修改项目的Properties/launchSettings.json,去掉通过IIS Express启动的选项:

{

"profiles": {

"MyElsaServer": {

"commandName": "Project",

"dotnetRunMessages": true,

"launchBrowser": true,

"applicationUrl": "http://localhost:5298",

"environmentVariables": {

"ASPNETCORE_ENVIRONMENT": "Development"

}

}

}

}

最后,修改Program.cs:

using Elsa.Persistence.EntityFramework.Core.Extensions;

using Elsa.Persistence.EntityFramework.Sqlite;

var builder = WebApplication.CreateBuilder(args);

var elsaSection = builder.Configuration.GetSection("Elsa");

// Elsa services.

builder.Services

.AddElsa(elsa => elsa

.UseEntityFrameworkPersistence(ef => ef.UseSqlite())

.AddConsoleActivities()

.AddHttpActivities(elsaSection.GetSection("Server").Bind)

.AddJavaScriptActivities()

);

// Elsa API endpoints.

builder.Services.AddElsaApiEndpoints();

// Allow arbitrary client browser apps to access the API.

// In a production environment, make sure to allow only origins you trust.

builder.Services.AddCors(cors => cors.AddDefaultPolicy(policy => policy

.AllowAnyHeader()

.AllowAnyMethod()

.AllowAnyOrigin()

.WithExposedHeaders("Content-Disposition"))

);

var app = builder.Build();

app

.UseCors()

.UseHttpActivities()

.UseRouting()

.UseEndpoints(endpoints =>

{

// Elsa API Endpoints are implemented as regular ASP.NET Core API controllers.

endpoints.MapControllers();

})

.UseWelcomePage();

app.Run();

最后,在appSettings.json中增加服务器地址的定义:

"Elsa": {

"Http": {

"BaseUrl": "http://localhost:5298"

}

}

启动项目,会出现欢迎界面:

服务器可以运行了,但还没有定义工作流,现在我们创建图形化的工作流定义和管理应用,向工作流服务器发布工作流,并查看工作流的执行情况。

在解决方案中增加一个新的ASP.NET Core Web空项目,命名为MyElsaDashboard,修改Properties/launchSettings.json,将项目改为自启动:

{

"profiles": {

"MyElsaDashboard": {

"commandName": "Project",

"dotnetRunMessages": true,

"launchBrowser": true,

"applicationUrl": "http://localhost:5060",

"environmentVariables": {

"ASPNETCORE_ENVIRONMENT": "Development"

}

}

}

}

在项目中添加如下程序包:

Install-Package Elsa.Designer.Components.Web

修改Program.cs:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

var app = builder.Build();

app.UseStaticFiles();

app.UseRouting();

app.UseEndpoints(endpoints => { endpoints.MapFallbackToPage("/_Host"); });

app.Run();

然后在项目中创建Pages文件夹,在文件夹中添加两个Razepage页面,名称为_ViewImports.cshtml和_Host.cshtml,_ViewImports的内容如下:

@ addTagHelper *, Microsoft .AspNetCore.Mvc.TagHelpers

_Host.cshtml的内容如下:

@page "/"

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8"/>

<meta name="viewport" content="width=device-width, initial-scale=1.0"/>

<title>Elsa Workflows</title>

<link rel="icon" type="image/png" sizes="32x32" href="/_content/Elsa.Designer.Components.Web/elsa-workflows-studio/assets/images/favicon-32x32.png">

<link rel="icon" type="image/png" sizes="16x16" href="/_content/Elsa.Designer.Components.Web/elsa-workflows-studio/assets/images/favicon-16x16.png">

<link rel="stylesheet" href="/_content/Elsa.Designer.Components.Web/elsa-workflows-studio/assets/fonts/inter/inter.css">

<link rel="stylesheet" href="/_content/Elsa.Designer.Components.Web/elsa-workflows-studio/elsa-workflows-studio.css">

<script src="/_content/Elsa.Designer.Components.Web/monaco-editor/min/vs/loader.js"></script>

<script type="module" src="/_content/Elsa.Designer.Components.Web/elsa-workflows-studio/elsa-workflows-studio.esm.js"></script>

</head>

<body>

<elsa-studio-root server-url="http://localhost:5298" monaco-lib-path="_content/Elsa.Designer.Components.Web/monaco-editor/min">

<elsa-studio-dashboard></elsa-studio-dashboard>

</elsa-studio-root>

</body>

</html>

请注意上面的server-url属性,这里指向我们前面创建的Elsa服务器地址。

现在我们修改解决方案的启动项目,设置为两个项目同时启动:

在Visual Studio中执行启动,管理界面如下:

选择Workflow Definitions进入流程定义管理界面,点击“Create Workflow”创建新的流程:

点击Start,然后选择Http->Http EndPoint,定义流程的入口url:

设置完成后按Save保存,可以看到多个一个环节,在这个环节下点击“+”图标可以继续添加环节,这里选择HttpResponse:

在Advanced选择卡中,选择Status Code为Ok,添加完成后,流程如下:

流程定义完成了,点击Publish发布流程到流程服务器。

流程发布后,可以在流程服务器执行流程。

我们在浏览器访问http://localhost:5298/hello-world,可以看到流程执行的结果:

回到流程管理应用,选择Workflow Instances,可以看到刚刚执行完成的流程实例:

点击流程Id,可以查看流程执行的详细过程:

到此,我们完成了工作流服务和管理应用的创建。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/151790.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java笔记021-异常-Exception

异常-Exception看个实际问题和一段代码运行下面的代码&#xff0c;看看有什么问题->引出异常和异常处理机制package com12.exception_;/*** author 甲柒* version 1.0* title Exception01* package com12.exception_* time 2023/1/9 14:38*/ public class Exception01 {publ…

Mask RCNN网络源码解读(Ⅳ) --- Mask R-CNN论文解读

目录 1.Mask R-CNN简介 2.Mask分支 3.Mask R-CNN损失 4Mask分支预测使用 1.Mask R-CNN简介 回顾我们之前所说的图像分类、目标检测、语义分割的内容&#xff1a; 我们来看一下实例分割和语义分割的差别&#xff1a; Mask R-CNN不仅能够同时进行目标检测与分割&#xff0c;…

查找算法之二分查找

目录 二分查找 算法实现 “双闭区间”实现 算法实现 python C 两种表示对比 大数越界处理 优点与缺点 二分查找 二分查找&#xff0c;利用数据的有序性&#xff0c;通过每轮缩小一半搜索区间来查找目标元素。 使用二分查找有两个前置条件&#xff1a; 要求输入数据…

如何在GitLab上传本地项目

上传前需准备&#xff1a;需要安装Git&#xff0c;点击进入官网下载&#xff1a;Git 在本地上传GitLab项目的步骤目录介绍&#xff1a; 一、配置SSH秘钥&#xff08;仅针对本机首次上传GitLab项目&#xff09; 二、上传项目 1、新建一个空文件夹&#xff0c;并在该文件夹下右键…

Deque

Deque&#xff1a; “double ended queue&#xff08;双端队列&#xff09;”的缩写&#xff0c;通常读为“deck”&#xff1b; Deque是一个线性集合&#xff0c;支持在两端插入和移除元素。 Deque有三种用途&#xff1a; 双端队列(两端都可进出) Deque< Integer> de…

机器学习实战教程(十三):树回归基础篇

一、前言本篇文章将会讲解CART算法的实现和树的剪枝方法&#xff0c;通过测试不同的数据集&#xff0c;学习CART算法和树剪枝技术。二、将CART&#xff08;Classification And Regression Trees&#xff09;算法用于回归在之前的文章&#xff0c;我们学习了决策树的原理和代码实…

成功上岸字节全靠这份Redis技术笔记,深入浅出值得一看

前言 正如标题所说&#xff0c;我现在已经如愿以偿地进了字节&#xff01;之前自己一直待在一个不大不小的外包公司&#xff0c;每天做着重复的层删改查工作。直到22年年底&#xff0c;自己通过朋友的介绍拿到了字节的面试机会&#xff0c;自己在家复习了3个月&#xff0c;成功…

decltype类型指示符

decltype类型指示符一、什么是decltype类型指示符二、typeid运算符三、使用decltype指示符四、decltype和引用五、decltype(auto)六、本章代码汇总一、什么是decltype类型指示符 有时会遇到这种情况&#xff1a;希望从表达式的类型推断出要定义的变量的类型&#xff0c;但是不…

超实用的实用Shell脚本

一、Dos 攻击防范&#xff08;自动屏蔽攻击 IP&#xff09; 代码&#xff1a; #!/bin/bash DATE$(date %d/%b/%Y:%H:%M) LOG_FILE/usr/local/nginx/logs/demo2.access.log ABNORMAL_IP$(tail -n5000 $LOG_FILE |grep $DATE |awk {a[$1]}END{for(i in a)if(a[i]>10)print…

Spring 学习笔记2

1.spring设置JDBC链接池 classpath:jdbc.properties是有多个连接池时的写法&#xff0c;一般都用这种 还有就是配置文件里不要直接使用username&#xff0c;会被覆盖 使用${}来从文件里读取属性 <beans xmlns"http://www.springframework.org/schema/beans"xmlns…

bitmap原理+性能优化实践

目录 背景 总体结构 从RoaringBitmp说起 3.1arraycontainer 1.3.2 bitmapcontainer 1.3.3 runcontainer 上源码 Roaring64NavigableMap RoaringBitmap RoaringArray 三种Container ArrayContainer BitmapContainer RunContainer 工作应用 需求 分析 能否多线…

ArcGIS基础实验操作100例--实验75气体扩散空间分析

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 高级编辑篇--实验75 气体扩散空间分析 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff08;1&…

MySQL常用基础 - 小白必看(二)

MySQL数据库基本操作 一、DDL 概念&#xff1a;是一个数据定义语言 该语言部分包括&#xff1a; 1、对数据库的常用操作 创建数据库&#xff1a; 1、create database 数据库名 (直接删除) 2、create database if not exists 数据库名 &#xff08;判断数据库是否存在&…

视频的水印怎样去掉?这些去水印的方法值得你试试看

喜欢视频剪辑的你会不会经常遇到这种情况&#xff1a;每次上网查找的视频素材&#xff0c;保存下来后总是带有一些水印&#xff0c;这些水印不仅不够美观&#xff0c;而且还会遮挡住视频的一些部分&#xff0c;实在是烦人。如果你遇到这种情况&#xff0c;会很想知道“给视频无…

86、【栈与队列】leetcode ——39. 滑动窗口最大值:单调队列+滑动窗口(C++版本)

题目描述 239. 滑动窗口最大值 一、单调队列滑动窗口方法 本题的特点是维护一个窗口&#xff0c;在窗口不断向前移动时&#xff0c;获取其中的最大值。由于窗口在向前移动过程中&#xff0c;元素存在着进入和出去的连续顺序&#xff0c;与FIFO的特点类似。 故可考虑用队列实…

【数据结构】初识数据结构,十分钟带你玩转算法复杂度

目录 &#x1f34a;前言&#x1f34a;&#xff1a; &#x1f95d;一、初识数据结构&#x1f95d;&#xff1a; 1.数据结构&#xff1a; 2.算法&#xff1a; &#x1f353;二、算法效率&#x1f353;&#xff1a; &#x1f348;三、算法复杂度&#x1f348;&#xff1a; 1.时…

4-1文件管理-文件系统基础

文章目录一.文件的基本概念二.文件的逻辑结构&#xff08;一&#xff09;无结构文件/流式文件&#xff08;二&#xff09;有结构文件1.顺序文件2.索引文件3.索引顺序文件4.直接文件/散列文件三.文件目录四.文件的物理结构/文件分配方式1.连续分配2.链接分配3.索引分配五.文件存…

数据结构与算法基础(王卓)(8)附:关于new的使用方法详解

part 1&#xff1a; C中new的用法&#xff08;不过就是&#xff09;如下&#xff08;几种用法&#xff09;&#xff1a; 1&#xff1a; new<数据类型> 分配&#xff1a; 指定类型的&#xff0c;大小为1的&#xff0c;内存空间&#xff1b; int *i new int;//注意&am…

13_3、Java的IO流之节点流的使用

一、FileReader和FileWriter的使用1、数据读入操作说明&#xff1a;①read():返回读入的第一个字符&#xff0c;当读到文档末尾&#xff0c;返回-1②异常的处理&#xff1a;为了保证流资源一定会执行关闭操作&#xff0c;要对异常进行try-catch-finally处理③对于读入操作&…

【PWA学习】1. 初识 PWA

什么是PWA PWA(Progressive Web Apps&#xff0c;渐进式 Web 应用)运用现代的 Web API 以及传统的渐进式增强策略来创建跨平台 Web 应用程序。这些应用无处不在、功能丰富&#xff0c;使其具有与原生应用相同的用户体验优势 我们需要理解的是&#xff0c;PWA 不是某一项技术&am…