x-blog之算法建模简单介绍

前言

这里的算法建模知识简单的建模。等同于数学公式,利用某种语言编好算法,利用一定逻辑存取,然后正确展示。里面涉及的细节包括对算法的理解和编写,数据模型的建立,高效存取,用户输入,编程规范以及涉及到web的一些知识等等。如下图所示。
Alt text

数据库设计

为了方便直接贴出截图(以下是按照自己的想法建的结构,仅作为项目说明,如不合理,请谅解)
设计到三张表t_algotithms_info(算法建模表),t_algotithms_type(算法类型名称),t_algotithms_type_info_rel(算法-类型-关系表)

  1. t_algotithms_type 由于类型极少,就没必要建立索引,各含义如字段所示,这里说明一下,最后七个字段,原则上是每个表都应该加上的。
    Alt text

  2. t_algotithms_info
    算法建模核心表,其中,algotithms_code算法最核心底层代码,controller_code交互代码,func_name请求的唯一函数名,也就是每个算法都有唯一的函数名,func_index唯一索引,主要有两个用处,一、快速定位函数详情记录,二、用于redis中定位记录,因为主键可能各种原因变化导致不能与redis中正确对应。
    Alt text
  3. t_algotithms_type_info_rel
    Alt text
    ok,表已建好,下面就是数据的建立,存与取了

笔者一直坚信算法是程序的灵魂。好了,不贼多说了,这里建立我按照算法来源归类为不同类,比如原生的数据结构( DataStructService),剑指offer(OfferAlgorithmsService),目前就建了这两个类,还有其他像数学建模类,LeetCode类等等。
另一方面,这里可以按照微服务思想,将该模块单独抽象成一个微服务,然后通过dubbo服务发布与调用。目前版本为了方便,直接作为core包下接口,然后实现。
就以约瑟夫环为例,从数据的建立->存数据库->页面展示->按条件从数据库取出->应用算法->计算返回结果

算法建立

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/**
* 约瑟夫环
*
* @param total 总人数
* @param n 每次需要处死的第n位置人
* @return 最后被赦免的人的位置
* @Auther: slycmiaoxi
* @Date: 2019/6/20
*/
int CountnQuit(int total, int n);
@Override
public int CountnQuit(int total, int n) {
boolean[] arr = new boolean[total];
for (int i = 0; i < total; i++) {
arr[i] = true;
}
int count = 0;
int index = 0;
int len = arr.length;
while (len > 1) {
if (arr[index] == true) {
count++;
if (count == n) {
count = 0;
arr[index] = false;
len--;
}
}
index++;
if (index == arr.length) {
index = 0;
}
}
for (int i = 0; i < arr.length; i++) {
if (arr[i] == true) {
return i + 1;
}
}
return 0;
}

存数据库

首先需要在后台里先初始化算法类型,然后在算法建模,如图所示
Alt text
点击算法建模后,通过dto对象传数据->controller->service->dao->mysql
另外这里的事务也需要注意和处理,目前没处理好

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Override
public boolean add(AlgotithmsInfoDto dto) {
// 1.校验参数
boolean checkParams = convert(dto);
if (!checkParams) {
return false;
}
// 2.dto -> po
TAlgotithmsInfo po = getPoByDto(dto);
// 3.入数据库
tAlgotithmsInfoMapper.insert(po);
itAlgotithmsTypeInfoRelService.add(po.getAlgotithmsInfoId(), po.getAlgotithmsTypeId());
// 4.入redis(存dto)
Integer algotithmsInfoId = po.getAlgotithmsInfoId();
long funcIndex = po.getFuncIndex();
dto.setAlgotithmsInfoId(CodecUtils.encodeData(String.valueOf(algotithmsInfoId)));
dto.setFuncIndex(funcIndex);
// 4.1 算法建模详情(集合数据结构)
jedisClient.lpush(REDIS_ALGORITHMS_LIST_KEY, JSON.toJSONString(dto));
return true;
}

页面加载

对于数据加载,一次性加载肯定效率不高,目前由于前端短板和数据并不多,先从redis中取出,异常本地取出
。而数据的显示结果类似于[string,list]类型的json数据格式,在将部分显示格式转化下,其中listDtoByTypeGroupWithLocal()就是直接从数据库中取出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
@Override
public List<TBean<String>> listGroupDto() {
final List<TBean<String>> resultList = new ArrayList<>();
// 1.获得所有算法类型
List<TAlgotithmsType> typeList = itAlgotithmsTypeService.listPojo();
if (CollectionUtils.isEmpty(typeList)) {
return resultList;
}
// 2.从redis中取出数据
List<String> list = jedisClient.lrange(REDIS_ALGORITHMS_LIST_KEY, 0, -1);
if (CollectionUtils.isEmpty(list)) {
return listDtoByTypeGroupWithLocal(typeList);
}
// 3.String -> dto
final List<AlgotithmsInfoDto> dtos = new LinkedList<>();
try {
list.stream().filter(x -> x != null).forEach(x -> {
AlgotithmsInfoDto dto = JSON.parseObject(x, AlgotithmsInfoDto.class);
dtos.add(dto);
});
}
catch (Exception e) {
return listDtoByTypeGroupWithLocal(typeList);
}
// 4.分类组合
typeList.stream().filter(k -> k != null).forEach(k -> {
List<AlgotithmsInfoDto> newDtos = new ArrayList<>();
dtos.stream().filter(dto -> dto != null).forEach(dto -> {
String encodeTypeId = CodecUtils.encodeData(String.valueOf(k.getAlgotithmsTypeId()));
if (dto.getAlgotithmsTypeId().equals(encodeTypeId)) {
// 排序后的集合
newDtos.add(dto);
}
});
resultList.add(new TBean<>(newDtos, k.getAlgotithmsTypeName()));
});
return resultList;
}

按条件从数据库取出

利用索引直接取出函数详情,如约瑟夫环。得到函数名,然后通过校验用户输入格式,最后返回结果给页面,
至此一个简单的算法建模完成。

踩坑

前端页面不好弄,和起始之初会遇到前端出现一些列问题,后端代码格式,另外就是核心算法的理解和实现起来会很伤脑筋。当然,里面还有很多不完善的地方,由于个人经验受限,请谅解!

热评文章