遗传算法理解与代码实战(二)- demo(python+deap)

前文介绍了遗传算法,并且手动python代码进行了实践,但是在遇到复杂的问题时(遗传算法理解与代码实战(三)会介绍),手写代码很麻烦,所以需要借助专门的遗传算法库来实现,这里我们选择deap库

1、DEAP简介

1.1 核心模块

在DEAP库中,algorithmsbasecreatortools是核心模块,它们提供了构建和运行进化算法所需的各种组件和工具。下面是对这些模块的简要介绍和使用方法:

creator

creator模块用于创建新的类,这些类可以用于表示个体、适应度、策略等。通过使用creator.create函数,可以定义具有特定属性和方法的类。
使用方法:

from deap import creator
# 创建一个表示个体的新类
creator.create("Individual", list, fitness=creator.FitnessMax)
# 创建一个表示适应度的新类
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
# 创建一个具有特定属性和方法的类
creator.create("MyClass", object, attr1=value1, attr2=value2)
base

base模块提供了进化算法的基本工具和组件,如种群、个体、适应度等。它还提供了遗传操作的基本函数,如选择、交叉和变异。
使用方法:

from deap import base
# 创建一个个体类
ind_class = base.Toolbox()
# 注册一个个体创建函数
ind_class.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_float, n=5)
# 创建一个种群类
pop_class = base.Toolbox()
# 注册一个种群创建函数
pop_class.register("population", tools.initRepeat, list, ind_class.individual)
tools

tools模块提供了许多有用的工具和函数,用于执行遗传操作、统计信息收集、可视化等。
使用方法:

from deap import tools
# 注册一个评估函数
toolbox.register("evaluate", my_evaluation_function)
# 注册一个选择函数
toolbox.register("select", tools.selTournament, tournsize=3)
# 注册一个交叉函数
toolbox.register("mate", tools.cxTwoPoint)
# 注册一个变异函数
toolbox.register("mutate", tools.mutGaussian, mu=0, sigma=1, indpb=0.1)
# 创建一个统计数据对象
stats = tools.Statistics(key=lambda ind: ind.fitness.values)
stats.register("avg", np.mean)
stats.register("min", np.min)
stats.register("max", np.max)
# 创建一个名人堂对象,用于存储最佳个体
hof = tools.HallOfFame(1)
algorithms

algorithms模块提供了各种预定义的进化算法,如简单遗传算法(eaSimple)、遗传编程(eaGP)等。这些算法可以轻松地与toolbox中的组件结合使用。
使用方法:

from deap import algorithms
# 创建一个初始种群
pop = toolbox.population(n=50)
# 运行简单遗传算法
pop, logbook = algorithms.eaSimple(pop, toolbox, cxpb=0.7, mutpb=0.1, ngen=50, stats=stats, halloffame=hof, verbose=True)
# 打印最佳个体
print("Best individual: ", hof[0])

1.2 核心组件

DEAP的核心组件包括:

  • 个体(Individual):表示问题的一个潜在解决方案。
  • 种群(Population):个体的集合,表示一代中的所有解决方案。
  • 适应度(Fitness):评估个体质量的手段,通常是一个或多个数值。
  • 选择(Selection):从种群中选择个体以繁殖后代的过程。
  • 交叉(Crossover):交换两个个体的部分基因以创建新的后代。
  • 变异(Mutation):改变个体基因的过程,以增加种群的多样性。

1.3 主体流程

使用DEAP(Distributed Evolutionary Algorithms in Python)库进行建模的流程通常包括以下几个步骤:

  1. 导入库和模块:
    首先,你需要导入DEAP库以及你将使用的具体模块,如basecreatortoolsalgorithms
  2. 定义问题:
    • 创建个体类和适应度类。使用creator模块创建适应度类(如FitnessMaxFitnessMin),以及个体类(如Individual),这些类将用于表示遗传算法中的个体和它们的适应度。
    • 确定问题的目标是最小化还是最大化,并相应地设置适应度类的权重。
  3. 初始化工具箱:
    • 使用base.Toolbox类创建一个工具箱实例,工具箱将包含所有用于生成和操作个体的工具。
    • 注册基因生成器(如attr_boolattr_float等),个体生成器(如individual),种群生成器(如population)等。
  4. 定义适应度函数:
    • 编写一个函数,用于评估个体的适应度。这个函数将接受一个个体作为输入,并返回一个表示其适应度的值(对于FitnessMax,通常是一个正值;对于FitnessMin,通常是一个负值)。
  5. 注册遗传操作:
    • 使用工具箱注册遗传操作,如选择(select)、交叉(mate)、变异(mutate)等。
    • 你可以选择DEAP提供的预定义操作,也可以自定义自己的操作。
  6. 实现遗传算法主循环:
    • 编写一个主函数(如main),在其中创建初始种群,并执行遗传算法的迭代过程。
    • 在每次迭代中,对种群进行选择、交叉、变异,并评估新生个体的适应度。
    • 更新种群,并记录所需的统计数据或最佳个体。
  7. 分析和可视化结果:
    • 在遗传算法运行结束后,分析结果,可能包括最佳个体的适应度、种群的进化趋势等。
    • 使用DEAP提供的工具或第三方库(如Matplotlib)进行可视化。
  8. 调优和测试:
    • 根据结果调整遗传算法的参数,如种群大小、交叉和变异概率等。
    • 进行多次实验,以验证算法的稳定性和性能。

2、代码实战

目标函数: y = x 2 y=x^2 y=x2
x的取值范围是[0,31]

我们根据前面的流程来尽心操作

2.1 定义问题

# 定义问题:求最大化问题
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
creator.create("Individual", list, fitness=creator.FitnessMax)

2.2 初始化工具箱

# 初始化
toolbox = base.Toolbox()

# 定义如何生成一个属性(即基因),这里使用0到1的随机整数
toolbox.register("attr_bool", random.randint, 0, 1)

# 定义个体如何生成:创建一个个体,其中包含5个基因
toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_bool, n=5)

# 定义种群如何生成:种群由个体组成
toolbox.register("population", tools.initRepeat, list, toolbox.individual)

  • attr_bool:
    attr_bool通常用于生成布尔值(True或False)的基因。在遗传算法中,这通常代表个体的一个二进制特征。
    例如,你可以使用attr_bool来生成一个由随机布尔值组成的个体,这些值可以表示遗传算法中的二进制字符串。

  • attr_float:
    attr_float用于生成浮点数的基因。这在处理连续优化问题时非常有用,其中个体的特征需要是实数值。
    你可以指定浮点数的范围,例如,attr_float(0.0, 1.0)将生成一个在0.0到1.0之间均匀分布的随机浮点数。

  • tools.initRepeat是一个函数,用于创建一个个体,其中包含重复的基因。这个函数可以接受以下参数:

    • container:一个用于创建个体的类或类型。通常,这是使用creator模块定义的个体类。
    • func:一个函数,用于生成个体的单个基因。这个函数可以是toolbox.attr_bool、toolbox.attr_float等。
    • n:一个整数,表示个体中基因的数量。
    • *args:额外的位置参数,将传递给func。
    • **kwargs:额外的关键字参数,将传递给func。
toolbox.individual()
[1, 0, 0, 0, 1]

toolbox.population(10)
[[1, 0, 0, 1, 1],
 [1, 0, 1, 0, 0],
 [0, 1, 1, 1, 0],
 [1, 1, 0, 1, 1],
 [1, 0, 1, 0, 1],
 [0, 0, 0, 1, 0],
 [1, 1, 0, 1, 1],
 [0, 1, 1, 1, 1],
 [0, 0, 0, 0, 0],
 [0, 1, 1, 1, 0]]

2.3 定义适应度函数

# 定义适应度函数
def evalOneMax(individual):
    # 将二进制转换为十进制
    x = int("".join(str(i) for i in individual), 2)
    # 计算适应度
    return x**2,
# 将适应度函数与个体评估过程绑定
toolbox.register("evaluate", evalOneMax)

这个与之前一样不过多介绍

2.4 注册遗传操作



# 注册遗传算法操作:交叉、变异、选择
toolbox.register("mate", tools.cxTwoPoint)
toolbox.register("mutate", tools.mutFlipBit, indpb=0.05)
toolbox.register("select", tools.selTournament, tournsize=3)

  • toolbox.register("mate", tools.cxTwoPoint)
    这一行将两点交叉操作(cxTwoPoint)注册到工具箱中,键为"mate"。两点交叉是一种常用的交叉操作,它选择两个交叉点,并交换两个父代个体在这两点之间的基因段来创建两个子代个体。
  • toolbox.register("mutate", tools.mutFlipBit, indpb=0.05)
    这一行将位翻转变异操作(mutFlipBit)注册到工具箱中,键为"mutate"。位翻转变异会随机选择个体的基因位并进行翻转(0变为1,1变为0)。indpb参数是每个基因发生变异的概率,这里是0.05,意味着每个基因有5%的概率发生变异。
  • toolbox.register("select", tools.selTournament, tournsize=3)
    这一行将锦标赛选择操作(selTournament)注册到工具箱中,键为"select"。锦标赛选择是一种选择方法,它从种群中随机选择一定数量的个体(这里由tournsize参数指定为3个),然后选择其中适应度最高的个体作为父代。这种方法有助于增加种群的多样性并防止过早收敛。

2.5 实现遗传算法主循环

def main():
    random.seed(64)
    # 创建初始种群
    pop = toolbox.population(n=50)

    # CXPB 为交叉概率,MUTPB 为变异概率
    CXPB, MUTPB, NGEN = 0.5, 0.2, 40

    # 初始种群的适应度评估
    fitnesses = list(map(toolbox.evaluate, pop))
    for ind, fit in zip(pop, fitnesses):
        ind.fitness.values = fit

    # 遗传算法循环
    for g in range(NGEN):
        # 选择下一代
        offspring = toolbox.select(pop, len(pop))
        offspring = list(map(toolbox.clone, offspring))

        # 交叉和变异
        for child1, child2 in zip(offspring[::2], offspring[1::2]):
            if random.random() < CXPB:
                toolbox.mate(child1, child2)
                del child1.fitness.values
                del child2.fitness.values

        for mutant in offspring:
            if random.random() < MUTPB:
                toolbox.mutate(mutant)
                del mutant.fitness.values

        # 重新评估变异和交叉后个体的适应度
        invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
        fitnesses = map(toolbox.evaluate, invalid_ind)
        for ind, fit in zip(invalid_ind, fitnesses):
            ind.fitness.values = fit

        # 新的种群
        pop[:] = offspring

        # 输出当前代的最佳个体
        fits = [ind.fitness.values[0] for ind in pop]
        length = len(pop)
        mean = sum(fits) / length
        max_fit = max(fits)
        print(f"代 {g}, 最大适应度 {max_fit}")

    best_ind = tools.selBest(pop, 1)[0]
    print("最佳个体是 %s, %s" % (best_ind, best_ind.fitness.values))
# 初始种群的适应度评估
fitnesses = list(map(toolbox.evaluate, pop))
for ind, fit in zip(pop, fitnesses):
    ind.fitness.values = fit

初始化一个种群并计算这个种群中每个个体的适应度,为遗传算法的后续迭代过程做准备。
遍历完成后我们可以打印下种群的数据

for ind in pop:
    print(ind, ind.fitness.values)

[0, 0, 1, 0, 1] (25.0,)
[0, 1, 0, 1, 1] (121.0,)
[0, 0, 0, 1, 1] (9.0,)
[1, 0, 1, 0, 1] (441.0,)
[1, 0, 1, 1, 0] (484.0,)
[1, 0, 1, 0, 1] (441.0,)
[1, 1, 1, 0, 0] (784.0,)
……
  • toolbox.select(pop, len(pop)) 这行代码的作用是从当前种群(pop)中选择出新的后代种群,选择的数量与当前种群数量(len(pop))相同。选择过程通常基于个体的适应度,适应度高的个体有更大的概率被选中。
  • offspring = list(map(toolbox.clone, offspring)) 这行代码的作用是对选中的后代个体进行克隆。在DEAP库中,个体(Individual)是通过列表(list)实现的,而在遗传算法中,为了避免在操作过程中修改原始种群,通常会对选中的个体进行克隆。map(toolbox.clone, offspring) 对 offspring 中的每个个体执行 toolbox.clone 函数,返回一个克隆个体的迭代器。list() 函数将这个迭代器转换为列表,从而得到一个包含克隆个体的新种群。
# 交叉和变异
for child1, child2 in zip(offspring[::2], offspring[1::2]):
    if random.random() < CXPB:
        toolbox.mate(child1, child2)
        del child1.fitness.values
        del child2.fitness.values
  • zip(offspring[::2], offspring[1::2]) 创建了一个迭代器,它将 offspring 列表中的个体两两配对。offspring[::2] 表示选择 offspring 列表中的所有偶数索引个体,而 offspring[1::2] 表示选择所有奇数索引个体。这样,每次迭代都会得到一对个体(child1 和 child2)。
  • if random.random() < CXPB: 检查一个随机数是否小于交叉概率(CXPB)。如果条件为真,则执行交叉操作;否则,不执行交叉,这对个体将保持不变。
  • toolbox.mate(child1, child2) 调用注册到工具箱中的交叉操作函数(在这个例子中是 tools.cxTwoPoint,两点交叉),对 child1 和 child2 进行交叉,生成新的后代。这个函数会修改 child1 和 child2 的基因(即它们的属性)。
  • del child1.fitness.values 和 del child2.fitness.values 删除 child1 和 child2 的适应度值。这是因为交叉操作改变了个体的基因,因此它们之前的适应度值不再有效。在后续的代码中,需要重新评估这些个体的适应度。
for mutant in offspring:
   if random.random() < MUTPB:
        toolbox.mutate(mutant)
        del mutant.fitness.values
  • for mutant in offspring: 这个循环遍历所有后代个体(offspring 列表中的每个个体)。
  • if random.random() < MUTPB: 检查一个随机数是否小于变异概率(MUTPB)。如果条件为真,则对当前遍历到的个体(mutant)执行变异操作;否则,不执行变异,该个体将保持不变。
  • toolbox.mutate(mutant) 调用注册到工具箱中的变异操作函数,对 mutant 进行变异。在这个例子中,变异操作函数是 tools.mutFlipBit,它随机翻转个体基因中的一个位(bit)。
  • del mutant.fitness.values 删除 mutant 的适应度值。这是因为变异操作改变了个体的基因,因此它们之前的适应度值不再有效。在后续的代码中,需要重新评估这些个体的适应度。

在这里插入图片描述

# 重新评估变异和交叉后个体的适应度
invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
fitnesses = map(toolbox.evaluate, invalid_ind)
for ind, fit in zip(invalid_ind, fitnesses):
    ind.fitness.values = fit
  • invalid_ind = [ind for ind in offspring if not ind.fitness.valid] 这行代码使用列表推导式创建一个新列表,包含所有适应度无效的个体。在DEAP库中,个体的适应度可以通过 ind.fitness.valid 属性来检查是否有效。如果个体经历了交叉或变异,其适应度通常会标记为无效。
  • fitnesses = map(toolbox.evaluate, invalid_ind) 使用 map 函数和工具箱中的 evaluate 函数来计算 invalid_ind 列表中所有个体的适应度。toolbox.evaluate 是之前注册的适应度函数,用于评估个体的适应度。
  • for ind, fit in zip(invalid_ind, fitnesses): 这个循环遍历所有无效个体和它们的适应度值。
    • ind.fitness.values = fit 将计算出的适应度值赋给对应的个体。这样,每个经过交叉或变异的个体的适应度就被更新为最新的值。
pop[:] = offspring

  # 输出当前代的最佳个体
  fits = [ind.fitness.values[0] for ind in pop]
  length = len(pop)
  mean = sum(fits) / length
  max_fit = max(fits)
  print(f"代 {g}, 最大适应度 {max_fit}")

这段代码是将新的后代种群(offspring)替换当前的种群(pop),并输出当前种群中最佳个体的适应度。下面是这段代码的详细解释:

  1. pop[:] = offspring 这行代码将新的后代种群(offspring)替换当前的种群(pop)。在Python中,pop[:] 表示对整个种群列表的引用,而 offspring 是通过选择、交叉和变异操作产生的新种群。这行代码实际上是更新了 pop 列表的内容,使其包含新一代的个体。
  2. fits = [ind.fitness.values[0] for ind in pop] 这行代码使用列表推导式来创建一个新列表,包含当前种群(pop)中每个个体的适应度值。在DEAP库中,个体的适应度值通常是一个元组,即使对于单目标优化问题也是如此。因此,ind.fitness.values[0] 用于获取适应度元组中的第一个元素,即实际的适应度值。
  3. length = len(pop) 获取当前种群的大小(个体数量)。
  4. mean = sum(fits) / length 计算当前种群的平均适应度。sum(fits) 计算所有个体适应度的总和,然后除以种群大小(length)得到平均值。
  5. max_fit = max(fits) 找出当前种群中的最佳适应度值。
  6. print(f"代 {g}, 最大适应度 {max_fit}") 这行代码打印出当前代数(g)和种群中的最大适应度值(max_fit)。这是为了监控算法的进度和性能。
0, 最大适应度 961.01, 最大适应度 961.02, 最大适应度 961.03, 最大适应度 961.04, 最大适应度 961.05, 最大适应度 961.06, 最大适应度 961.07, 最大适应度 961.08, 最大适应度 961.09, 最大适应度 961.0
最佳个体是 [1, 1, 1, 1, 1], (961.0,)

本篇是遗传算法系列的第二篇,计划总共写三篇,最后会写利用遗传算法来优化Kmeans算法的介绍

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用Python快速提取PPT中的文本内容

直接提取PPT中的文本内容可以方便我们进行进一步处理或分析&#xff0c;也可以直接用于其他文档的编撰。通过使用Python程序&#xff0c;我们可以快速批量提取PPT中的文本内容&#xff0c;从而实现高效的信息收集或对其中的数据进行分析。本文将介绍如何使用Python程序提取Powe…

Vue | 基于 vue-admin-template 项目的跨域问题解决方法

目录 一、现存问题 二、解决方法 2.1 修改的第一个地方 2.2 修改的第二个地方 2.3 修改的第三个地方 自存 一、现存问题 报错截图如下&#xff1a; 二、解决方法 2.1 修改的第一个地方 在 .env.development 文件中&#xff1a; # base api # VUE_APP_BASE_API /d…

阿里云服务器地域和可用区选择及关系说明

阿里云服务器地域和可用区怎么选择&#xff1f;地域是指云服务器所在物理数据中心的位置&#xff0c;地域选择就近选择&#xff0c;访客距离地域所在城市越近网络延迟越低&#xff0c;速度就越快&#xff1b;可用区是指同一个地域下&#xff0c;网络和电力相互独立的区域&#…

如何使用Python的Open3D 库LAS对点云进行重建

在 Python 中对点云进行重建也可以使用 PCL 库&#xff0c;不过更为常见的是使用 Open3D 库。Open3D 是一个开源的现代化 3D 数据处理库&#xff0c;提供了许多用于点云和三维几何数据处理的功能&#xff0c;包括点云重建。 下面是一个简单的示例代码&#xff0c;演示了如何使…

人工智能|机器学习——k-近邻算法(KNN分类算法)

1.简介 k-最近邻算法&#xff0c;也称为 kNN 或 k-NN&#xff0c;是一种非参数、有监督的学习分类器&#xff0c;它使用邻近度对单个数据点的分组进行分类或预测。虽然它可以用于回归问题&#xff0c;但它通常用作分类算法&#xff0c;假设可以在彼此附近找到相似点。 对于分类…

灵魂指针,教给(二)

欢迎来到白刘的领域 Miracle_86.-CSDN博客 系列专栏 C语言知识 先赞后看&#xff0c;已成习惯 创作不易&#xff0c;多多支持&#xff01; 目录 一、数组名的理解 二、使用指针访问数组 三、一维数组传参本质 四、冒泡排序 五、二级指针 六、指针数组 七、指针数组…

Go语言物联网开发安科瑞ADW300/4G电能表数据上传mqtt平台-电表接线到传输数据完整流程

电能表功能说明 ADW300是方便用户进行用电监测、集抄和管理&#xff0c;可灵活安装在配电箱中&#xff0c;可用于电力运维、环保监管等在线监测类平台中。我们本案例是用于工业售电公司对出售电的管理&#xff0c;设备可以监控用电情况、故障监控及警报&#xff0c;售电公司可…

LeetCode的使用方法

LeetCode的使用方法 一、LeetCode是什么&#xff1f;1.LeetCode简介2.LeetCode官网 二、LeetCode的使用方法1.注册账号2.力扣社区力扣编辑器 2.1 讨论发起讨论参与讨论关注讨论 2.2 文章撰写文章关注文章 3.力扣面试官版测评面试招聘竞赛 4.力扣学习LeetBook 书架我的阅读猜您喜…

使用Opencv库直接进行人脸检测

import cv2abs_path cv2.__file__ xml_path abs_path.rsplit("/",1)[0] "/data/haarcascade_frontalface_default.xml"# 加载人脸检测器 face_cascade cv2.CascadeClassifier(xml_path)# 加载图像 img cv2.imread(/media/datasets/face/liuyigei_duo.…

C++vector的使用方法

文章目录 一、vector的介绍1. 文档链接2. 简要介绍 二、vector的使用1.vector的定义&#xff08;1&#xff09;构造函数&#xff08;2&#xff09;拷贝构造函数&#xff08;2&#xff09;赋值重载 2. vector 增删查改&#xff08;1&#xff09;operator []&#xff08;2&#x…

地址分词 | EXCEL批量进行地址分词,标准化为十一级地址

一 需求 物流需要对用户输入地址进行检查&#xff0c;受用户录入习惯地址可能存在多种问题。 地址标准化是基于地址引擎和地址大数据模型&#xff0c;自动将地址信息标准化为省、市、区市县、街镇、小区、楼栋、单元、楼层、房屋、房间等元素&#xff0c;补充层级缺失数据、构建…

C语言从入门到精通 第十一章(文件操作)

写在前面&#xff1a; 本系列专栏主要介绍C语言的相关知识&#xff0c;思路以下面的参考链接教程为主&#xff0c;大部分笔记也出自该教程。除了参考下面的链接教程以外&#xff0c;笔者还参考了其它的一些C语言教材&#xff0c;笔者认为重要的部分大多都会用粗体标注&#xf…

【学习笔记】微信运营工具

办公工具 在线 http://uzer.meMindMaster即刻&#xff08;APP&#xff09;收趣&#xff08;APP&#xff09;MindMaster&#xff08;app&#xff09; 安装 文字工具 Mega Emoji 文字云 石墨文档 giftools 音频工具 变声实验室&#xff08;APP&#xff09; 录音APP&am…

本鲸多方位助力创业者高效对接创新创业机遇

在科技创新的浪潮中&#xff0c;创业者们不断探索着新的商业机会&#xff0c;寻求着创新创业的道路。然而&#xff0c;面对复杂多变的市场环境和激烈的竞争压力&#xff0c;如何高效对接创新创业机遇成为了摆在创业者面前的重要课题。 本鲸依托海南本鲸投资有限公司和重庆本鲸…

Flink 物理执行图

文章目录 物理执行图一、Task二、ResultPartition三、ResultSubpartition四、InputGate五、InputChannel 物理执行图 JobManager根据ExecutionGraph对作业进行调度&#xff0c;并在各个TaskManager上部署任务。这些任务在TaskManager上的实际执行过程就形成了物理执行图。物理…

Leetcode - 周赛387

目录 一&#xff0c;3069. 将元素分配到两个数组中 I 二&#xff0c;3070. 元素和小于等于 k 的子矩阵的数目 三&#xff0c;3071. 在矩阵上写出字母 Y 所需的最少操作次数 四&#xff0c;3072. 将元素分配到两个数组中 II 一&#xff0c;3069. 将元素分配到两个数组中 I 本…

[递归、搜索、回溯]----递归

前言 作者&#xff1a;小蜗牛向前冲 专栏&#xff1a;小蜗牛算法之路 专栏介绍&#xff1a;"蜗牛之道&#xff0c;攀登大厂高峰&#xff0c;让我们携手学习算法。在这个专栏中&#xff0c;将涵盖动态规划、贪心算法、回溯等高阶技巧&#xff0c;不定期为你奉上基础数据结构…

freeRTOS20240308

1.总结任务的调度算法&#xff0c;把实现代码再写一下 2.总结任务的状态以及是怎么样进行转换的

音视频学习笔记——c++多线程(一)

✊✊✊&#x1f308;大家好&#xff01;本篇文章主要整理了部分多线程相关的内容重点&#x1f607;。首先讲解了多进程和多线程并发的区别以及各自优缺点&#xff0c;之后讲解了Thead线程库的基本使用。 本专栏知识点是通过<零声教育>的音视频流媒体高级开发课程进行系统…

react的diff源码

react 的 render 阶段&#xff0c;其中 begin 时会调用 reconcileChildren 函数&#xff0c; reconcileChildren 中做的事情就是 react 知名的 diff 过程 diff 算法介绍 react 的每次更新&#xff0c;都会将新的 ReactElement 内容与旧的 fiber 树作对比&#xff0c;比较出它们…