【算法导论】摊还分析

news2025/3/1 1:31:41

目录

      • 一、摊还分析简介
      • 二、分析的两个问题
        • 1.栈操作
        • 2. 二进制计数器递增
      • 三、分析方法
        • 1. 聚合分析
          • 1.1 栈操作
          • 1.2 二进制计数递增
        • 2.核算法
          • 2.1 栈操作
          • 2.2 二进制计数器递增
        • 3. 势能法
          • 3.1 栈操作
          • 3.2 二进制计数器递增

一、摊还分析简介

  在摊还分析中,我们求数据结构的一个序列操作中所执行的所有操作的平均时间,来评价操作的代价。这样,我们就可以说明一个操作的平均代价是很低的,即使序列中某个单一操作的代价很高。摊还分析不同于平均情况,它并不涉及概率,它可以保证最坏情况下每个操作的平均性能

二、分析的两个问题

  本文我们将用三种方法求解以下两个问题的摊还代价。

1.栈操作

最原始的栈有两种基本操作分别是:

  • PUSH(S,x):将对象 x 压入栈 S 中。
  • POP(S):将 S 的栈顶对象弹出,并返回该对象。

  由于两个操作的时间都是 O ( 1 ) O(1) O(1) 的,我们假定其代价为均为1,因此 n 个PUSH和POP操作的序列的总代价为 n,而 n 个操作的实际运行时间为 θ ( n ) \theta(n) θ(n)
  现在我们增加一个新的栈操作 MULTIPOP(S,k),它删除栈 S 栈顶的 k 个对象,如果栈中对象数小于k,则将整个栈中的的内容都弹出以下是其执行伪代码:

MULTIPOP(S,k)
	while not STACK-EMPTY(S) and k > 0 //STACK-EMPTY(S)判断S栈是否为空,空则返回false
		POP(S)
		k = k - 1

  在一个包含s个对象的栈上执行 MULTIPOP(S,k) 操作有两种结果,当 s > k时,则执行 k 次 POP 操作,当 s < k 时,则执行 s 次操作。由以上分析可知 MULTIPOP 的总代价为 m i n ( s , k ) min(s,k) min(s,k)
  在下文中,我们将用三种方式来分析一个由 n 个PUSH、POP和 MULTIPOP 组成的操作序列在一个空栈上的摊还代价。

2. 二进制计数器递增

  该问题为 k 位二进制计数器的递增问题,计数器的初值为0。我们用一个位数组 A [ 0... k − 1 ] A[0...k-1] A[0...k1]最为计数器,其中 A . l e n g t h = k A.length = k A.length=k。当计数器中保存的二级制为 x 时,x的最低位保存在 A [ 0 ] A[0] A[0] 中,而最高位保存在 A [ k − 1 ] A[k-1] A[k1] 中,因此 x = ∑ i = 0 k − 1 A [ i ] ∗ 2 i x = \sum_{i=0}^{k-1}A[i]*2^i x=i=0k1A[i]2i。计数器的一次递增过程用一下代码来实现:

INCREMENT(A)
	i = 0
	while i < A.length and A[i] == 1
		A[i] = 0
		i = i + 1
	if i < A.length
		A[i] = 1

计数器计数过程:
在这里插入图片描述
  通过代码和图示我们可知,位数组 A 的变化过程为从下标为0开始向高位遍历,将值为1的位反转为0,将第一次出现的值为0的位反转为1。
  在下文中,我们将用三种方式来分析该二进制递增计数器的摊还代价。

三、分析方法

1. 聚合分析

  利用聚合分析,我们证明对所有 n,一个操作的序列最坏情况下花费的总时间为 T ( n ) T(n) T(n)。因此,在最坏情况下,每个操作的平均代价,或摊还代价为 T ( n ) / n T(n)/n T(n)/n

1.1 栈操作

  我们来分析一下一个由 n 个PUSH、POP和 MULTIPOP 组成的操作序列在一个空栈上的执行情况。因为栈的大小最大为 n,所以序列中一个MULTIPOP操作的最坏情况(执行n次POP)代价为 O ( n ) O(n) O(n),所以 n 个操作的序列的最坏情况代价为 O ( n 2 ) O(n^2) O(n2)(在操作序列为 O ( n ) O(n) O(n)个MULTIPOP操作的情况下),这种分析是正确的,但显然在实际情况下不可能实现(因为不可能一直都是退栈操作),所以我们将使用聚合分析来得到一个更好的分析结果。
  当将一个对象压入栈后,我们至多将其弹出一次。因此对于一个非空的栈,可以执行的POP操作的次数(包括了MULTIPOP中调用的POP的次数)最多与PUSH的次数相当,即最多 O ( n ) O( n ) O(n)次。因此对任意的n值,任意一个由 n 个PUSH、POP和MULTIPOP组成的操作序列,最多花费 O ( n ) O(n) O(n)的时间。一个操作的平均时间为 O ( n ) / n = O ( 1 ) O(n)/n=O(1) O(n)/n=O(1)。在聚合分析中,我们将每个操作的摊还代价设定为平均代价。因此,在此例中,所有三种栈操作的摊还代价都是 O ( 1 ) O(1) O(1)

1.2 二进制计数递增

  当数组A所有位都是1时,INCREMENT执行一次花费的时间为 θ ( k ) \theta(k) θ(k),因此对于初值为0的计数器执行n个INCREMENT操作最坏情况下花费 O ( n k ) O(nk) O(nk)
  我们用聚合分析得到一个更紧的界—最坏情况下代价为 O ( n ) O(n) O(n),因为不可能每次INCREMENT操作都反转所有的二进制位,如问题中的图所示,每次调用INCREMENT时 A [ 0 ] A[0] A[0]都会反转,而下一位的 A [ 1 ] A[1] A[1]是每两次调用翻转一次,这样,对一个初值为0的计数器执行一个n个INCREMENT操作的序列,只会使 A [ 1 ] A[1] A[1]反转 ⌊ n / 2 ⌋ \left\lfloor n/2 \right\rfloor n/2次,类似的 A [ 2 ] A[2] A[2]每四次调用才反转一次,执行一个n个INCREMENT操作的序列的过程中只会反转 ⌊ n / 4 ⌋ \left\lfloor n/4 \right\rfloor n/4次,所以一般情况下,对一个初值为0的计数器,执行n个INCREMENT操作的序列的过程中, A [ i ] A[i] A[i]会反转 ⌊ n / 2 i ⌋ \left\lfloor n/2^i \right\rfloor n/2i次,对 i ≥ k i\geq k ik A [ i ] A[i] A[i]不存在,因此也就不会反转。综上所述,在执行INCREMENT序列的过程中进行的反转操作的总数为:
∑ i = 0 k − 1 ⌊ n 2 i ⌋ < n ∑ i = 0 ∞ ⌊ 1 2 i ⌋ = 2 n \sum_{i=0}^{k-1}\left\lfloor \frac{n}{2^i} \right\rfloor<n \sum_{i=0}^{\infty}\left\lfloor \frac{1}{2^i} \right\rfloor=2n i=0k12in<ni=02i1=2n
  因此,对一个初值为0的计数器,执行一个n个INCREMENT操作的序列的最坏情况时间为 O ( n ) O(n) O(n)。每个操作的平均代价,即摊还代价为 O ( n ) / n = O ( 1 ) O(n)/n=O(1) O(n)/n=O(1)

2.核算法

  在用核算法进行摊还分析时,我们对不同操作赋予不同费用,赋予某些操作的费用可能多于或少于其实际代价。我们将赋予一个操作的费用称为它的 摊还代价。当一个操作的摊还代价超过其实际代价时,我们将差额存入数据结构中的特定对象,存入的差额称为 信用。对于后续操作中摊还代价小于实际代价的情况,信用可以用来支付差额。因此,我们可以将一个操作的摊还代价分解为其实际代价和信用(存入的或用掉的)。

2.1 栈操作

其中栈操作中的三个操作的的实际代价为:

  • PUSH     1
  • POP     1
  • MULTIPOP    m i n ( k , s ) min(k,s) min(k,s)  k 为MULTIPOP中的参数,s为调用时栈的规模。

我们为这些操作赋予如下摊还代价:

  • PUSH     2
  • POP     0
  • MULTIPOP   0

  假定使用1美元来表示一个单位操作的代价,我们将一美元用来支付压栈操作的实际代价,将剩余的一美元存为信用(共缴费2美元),在任何时间点,栈中的元素都存储了与之对应的一美元的信用,该信用用来作为将来它被弹出栈时代价的预付费,当执行一个POP操作时,并不会缴纳任何费用,而是使用存储在栈中的信用来支付其实际代价,对于MULTIPOP操作,我们也可以不缴纳任何费用。
  由于栈中的元素是非负的,所以信用值也是非负的,因此,对于任意 n n n 个PUSH、POP、MULTIPOP操作组成的序列,总摊还代价为实际总代价的上界。由于总摊还代价为 O ( n ) O(n) O(n) ,因此总实际代价也为 O ( n ) O(n) O(n)

2.2 二进制计数器递增

  对于该例,我们仍使用1美元表示一个单位的代价,对于一次置位操作,我们设其摊还代价为2美元,当置位时,用1美元支付置位操作的实际代价,并将另1美元置为信用,用来支付复位操作时的代价。
  由代码可知,INCREMENT过程之多置位一次,因此其摊还代价最多为2美元,计数器中1的个数永远不会为负因此,任何时刻信用值都是非负的。所以,对于 n n n 个INCREMENT操作,总的摊还代价为 O ( n ) O(n) O(n),为总实际代价的上界。

3. 势能法

  我们将对一个初始数据结构 D 0 D_0 D0 执行 n n n 个操作。对每个 i = 1 , 2 , 3... , n i=1,2,3...,n i=1,2,3...,n,令 c i c_i ci 为第 i i i 个操作的实际代价,令 D i D_i Di为在数据结构 D i − 1 D_{i-1} Di1 上执行第 i i i 个操作得到的结果数据结构。势函数 ϕ \phi ϕ 将每个数据结构 D i D_i Di映射到一个实数 ϕ ( D i ) \phi(D_i) ϕ(Di) ,此即为关联到数据结构 D i D_i Di 的势。第 i i i 个操作的摊还代价 c i ^ \hat{c_i} ci^ 用势函数定义为:
c i ^ = c i + ϕ ( D i ) − ϕ ( D i − 1 ) \hat{c_i}=c_i+\phi(D_i)-\phi(D_{i-1}) ci^=ci+ϕ(Di)ϕ(Di1)因此,每个操作的摊还代价等于其实际代价加上此操作引起的势能变化,由此可得,n个操作的总摊还代价为 ∑ i = 1 n c i ^ = ∑ i = 1 n ( c i + ϕ ( D i ) − ϕ ( D i − 1 ) ) = ∑ i = 1 n c i + ϕ ( D n ) − ϕ ( D 0 ) \begin{aligned}\sum_{i=1}^n\hat{c_i}&=\sum_{i=1}^n(c_i+\phi(D_i)-\phi(D_{i-1}))\\&=\sum_{i=1}^nc_i+\phi(D_n)-\phi(D_0) \end{aligned} i=1nci^=i=1n(ci+ϕ(Di)ϕ(Di1))=i=1nci+ϕ(Dn)ϕ(D0)

3.1 栈操作

  我们将栈的势函数定义为其中的对象的数量。对于初始的空栈 D 0 D_0 D0,我们有 ϕ ( D 0 ) = 0 \phi(D_0)=0 ϕ(D0)=0,由于栈中的对象数目不可能为负,因此,第 i i i 步操作具有非负的势,即
ϕ ( D i ) ≥ 0 = ϕ ( D 0 ) \phi(D_i)\geq0=\phi(D_0) ϕ(Di)0=ϕ(D0)因此用 ϕ \phi ϕ 定义的 n 个操作的总摊还代价即为实际代价的一个上界。

下面计算不同栈操作的摊还代价:

  • 如果第 i 个操作是 PUSH 操作,此时栈中包含 s 个对象,则势差为:
    ϕ ( D i ) − ϕ ( D i − 1 ) = ( s + 1 ) − s = 1 \phi(D_i)-\phi(D_{i-1})=(s+1)-s=1 ϕ(Di)ϕ(Di1)=(s+1)s=1所以其摊还代价为: c i ^ = c i + ϕ ( D i ) − ϕ ( D i − 1 ) = 1 + 1 = 2 \hat{c_i}=c_i+\phi(D_i)-\phi(D_{i-1})=1+1=2 ci^=ci+ϕ(Di)ϕ(Di1)=1+1=2
  • 如果第 i 个操作是 MULTIPOP(S,k),将 k ′ = m i n ( k , s ) k^{'}=min(k,s) k=min(k,s) 个对象弹出栈。对象的实际代价为 k ′ k^{'} k,势差为 ϕ ( D i ) − ϕ ( D i − 1 ) = − k ′ \phi(D_i)-\phi(D_{i-1})=-k^{'} ϕ(Di)ϕ(Di1)=k因此,其摊还代价为 c i ^ = c i + ϕ ( D i ) − ϕ ( D i − 1 ) = k ′ − k ′ = 0 \hat{c_i}=c_i+\phi(D_i)-\phi(D_{i-1})=k^{'}-k^{'}=0 ci^=ci+ϕ(Di)ϕ(Di1)=kk=0类似的,普通POP操作的摊还代价也为0。

  每个操作的摊还代价都是 O ( 1 ) O(1) O(1),因此,n 个操作的总摊还代价为 O ( n ) O(n) O(n)。由于我们已经论证了 ϕ ( D i ) ≥ ϕ ( D 0 ) \phi(D_i)\geq\phi(D_0) ϕ(Di)ϕ(D0),因此,n个操作的总摊还代价为实际总摊还代价的上界。所以 n 个操作的最坏情况时间为 O ( n ) O(n) O(n)

3.2 二进制计数器递增

   这一次,我们将计数器执行 i i i 次INCREMENT操作后的势定义为 b i b_i bi i i i 次操作后计数器中 1 的个数。
   假设第 i i i 个INCREMENT操作将 t i t_i ti 个位复位,则其实际代价至多为 t i + 1 t_i+1 ti+1,因为除了复位 t i t_i ti 个位之外,还至多置位 1 位。如果 b i = 0 b_i=0 bi=0,则第 i 个操作将所有 k k k 位复位了,因此 b i = t i = k b_i=t_i=k bi=ti=k。如果 b i > 0 b_i>0 bi>0,则 b i = b i − 1 − t i + 1 b_i=b_{i-1}-t_i+1 bi=bi1ti+1。无论哪种情况, b i ≤ b i − 1 − t i + 1 b_i\leq b_{i-1}-t_i+1 bibi1ti+1,势差为:
ϕ ( D i ) − ϕ ( D i − 1 ) ≤ ( b i − 1 − t i + 1 ) − b i − 1 = 1 − t i \phi(D_i)-\phi(D_{i-1})\leq (b_{i-1}-t_i+1)-b_{i-1}=1-t_i ϕ(Di)ϕ(Di1)(bi1ti+1)bi1=1ti因此,其摊还代价为 c i ^ = c i + ϕ ( D i ) − ϕ ( D i − 1 ) ≤ ( t i − 1 ) + ( 1 − t i ) = 2 \hat{c_i}=c_i+\phi(D_i)-\phi(D_{i-1})\leq(t_i-1)+(1-t_i)=2 ci^=ci+ϕ(Di)ϕ(Di1)(ti1)+(1ti)=2如果计数器从 0 开始,则 ϕ ( D 0 ) = 0 \phi(D_0)=0 ϕ(D0)=0。由于对所有的 ϕ ( D i ) ≥ 0 \phi(D_i)\geq0 ϕ(Di)0,因此,一个从 n n n 个INCREMENT操作的序列的总摊还代价是总实际代价的上界,所以 n 个INCREMENT操作的最坏情况时间为 O ( n ) O(n) O(n)

  即使计数器不是从0开始也可以分析。假设计数器初始时包含 b 0 b_0 b0 个 1,经过 n 个INCREMENT操作后包含 b n b_n bn个 1,其中 0 ≤ b 0 , b n ≤ k 0\leq b_0,b_n\leq k 0b0bnk 于是可以将公式改写为 ∑ i = 1 n c i = ∑ i = 1 n c i ^ − ϕ ( D n ) + ϕ ( D 0 ) \sum_{i=1}^nc_i=\sum_{i=1}^n\hat{c_i}-\phi(D_n)+\phi(D_0) i=1nci=i=1nci^ϕ(Dn)+ϕ(D0)对所有 1 ≤ i ≤ n 1\leq i\leq n 1in,我们有 c i ^ ≤ 2 \hat{c_i}\leq2 ci^2。由于 ϕ ( D 0 ) = b 0 \phi(D_0)=b_0 ϕ(D0)=b0 ϕ ( D n ) = b n \phi(D_n)=b_n ϕ(Dn)=bn,n 个INCREMENT操作的总实际代价为 ∑ i = 1 n c i ≤ ∑ i = 1 n 2 − b n + b 0 = 2 n − b n + b 0 \sum_{i=1}^nc_i\leq \sum_{i=1}^n2-b_n+b_0=2n-b_n+b_0 i=1ncii=1n2bn+b0=2nbn+b0由于 b 0 ≤ k b_0\leq k b0k ,因此只要 k = O ( n ) k=O(n) k=O(n),总实际代价就是 O ( n ) O(n) O(n)。换句话说,如果至少执行 n = Ω ( k ) n=\Omega(k) n=Ω(k) 个INCREMENT操作,不管计数器初值是什么,总代价都是 O ( n ) O(n) O(n)

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

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

相关文章

爬取某音乐榜单歌曲

一、打开网页https://music.163.com/&#xff0c;进入榜单&#xff08;热歌榜&#xff09; 二、右键检查、刷新网页&#xff0c;选择元素&#xff08;点击歌曲名&#xff09; 三、相关代码 import requests #正则表达式模块内置模块 import re import osfilename music\\ if …

手写redux的connect方法, 使用了subscribe获取最新数据

一. 公共方法文件 1. connect文件 import React, { useState } from "react"; import MyContext from "./MyContext"; import _ from "lodash";// 模拟react-redux的 connect高阶函数 const connect (mapStateToProps, mapDispatchToProps) &…

都2023了!别再问我,UI自动化测试怎么做了……

本文关键词&#xff1a;移动端UI自动化思路 大家好&#xff0c;我是老司机。之前测试交流群里有同学问“有没有自动化测试在工作中的案例可以分享“&#xff0c;有是有的。 今天我会详细的描述一个【UI自动化实战在实际工作中的应用】&#xff0c;这是之前贝壳找房我们团队做…

vue单向绑定和双向绑定

一、单向绑定就是&#xff1a;修改视图&#xff0c;数据不变&#xff1b;修改数据&#xff08;app.name"1234"&#xff09;&#xff0c;视图会变 二、双向绑定&#xff1a;修改视图&#xff0c;数据会变&#xff1b;修改数据&#xff0c;视图会变 demo&#xff1a; …

屋顶太阳能光伏系统的性能分析指标研究

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

基于晶体结构优化的BP神经网络(分类应用) - 附代码

基于晶体结构优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录 基于晶体结构优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.晶体结构优化BP神经网络3.1 BP神经网络参数设置3.2 晶体结构算法应用 4.测试结果…

实现vue导出excel和echart图形分别在不同工作表

背景 实现一键导出excel 并且区分图表和表格为不同的sheet工作表 最终效果为 代码实现 功能实现 <script lang"ts">import * as echarts from echarts;import ExcelJS from exceljs;import { saveAs } from file-saver; import {getAsyncTempCurrentData} …

基于社交网络优化的BP神经网络(分类应用) - 附代码

基于社交网络优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录 基于社交网络优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.社交网络优化BP神经网络3.1 BP神经网络参数设置3.2 社交网络算法应用 4.测试结果…

linux进阶(脚本编程/软件安装/进程进阶/系统相关)

一般市第二种,以bash进程执行 shelle脚本编程 env环境变量 set查看所有变量 read设置变量值 echo用于控制台输出 类似java中的sout declear/typeset声明类型 范例 test用于测试表达式 if/else case while for 函数 脚本示例 软件安装及进阶 fork函数(复制一个进程(开启一个进…

TS 泛型你还不会?来!我教你

前言&#xff1a;最近遇到了一些写作上的烦恼&#xff0c;自己好像陷入了程序员的通病想法&#xff0c;“这个知识点这么简单&#xff0c;大家应该都会吧&#xff0c;我说出来是不是显得我很笨。” 思考了近一个月&#xff0c;又翻了翻自己最开始写作的文章&#xff0c;文笔虽…

python二次开发Solidworks:方程式驱动曲线

如果按照维度去划分&#xff0c;SOLIDWORKS中曲线可以划分为平面曲线和空间曲线&#xff0c;并且在二维草图还是3D草图中都提供了“方程式驱动曲线”。但是从使用方法来讲&#xff0c;方程式驱动的曲线分为两种定义方式:“显性”和“参数式”。“显式方程”在定义了起点和终点处…

核酸管外观缺陷检测(一)

1.1 应用示例思路 (1) 对核酸管图像进行灰度化、阈值分割和连通域分析&#xff1b; (2) 筛选出待检测的区域&#xff0c;并对该区域进行变换校正&#xff1b; (3) 进一步获取待检测的ROI区域&#xff0c;并根据几何特征和阈值条件&#xff0c;来对核酸管外观进行检测&#x…

openGauss学习笔记-103 openGauss 数据库管理-管理数据库安全-客户端接入之SSL证书管理-证书生成

文章目录 openGauss学习笔记-103 openGauss 数据库管理-管理数据库安全-客户端接入之SSL证书管理-证书生成103.1 操作场景103.2 前提条件103.3 自认证证书生成过程 openGauss学习笔记-103 openGauss 数据库管理-管理数据库安全-客户端接入之SSL证书管理-证书生成 openGauss默认…

【密评】商用密码应用安全性评估从业人员考核题库(十)

商用密码应用安全性评估从业人员考核题库&#xff08;十&#xff09; 国密局给的参考题库5000道只是基础题&#xff0c;后续更新完5000还会继续更其他高质量题库&#xff0c;持续学习&#xff0c;共同进步。 2251 单项选择题 根据 GM/T 0030《服务器密码机技术规范》&#xff0…

系统架构师备考倒计时17天(每日知识点)

一、数据库设计阶段以及相应的产物 需求分析阶段&#xff1a;数据流图、数据字典、需求说明书&#xff1b;概念结构设计阶段&#xff1a;ER模型&#xff1b;逻辑结构设计阶段&#xff1a;关系模式&#xff1b;物理设计阶段&#xff1a;包括存储结构和存取方法的物理结构。 &…

35岁左右的项目经理,这5种能力一定要有​

大家好&#xff0c;我是老原。 经常有项目经理和我吐槽&#xff0c;现在不管是做项目&#xff0c;还是做管理&#xff0c;都太难了。 上有甲方和和老板给压力&#xff0c;下有团队成员叫苦连天&#xff0c;最后里外不是人。 刚毕业20多岁的时候还好&#xff0c;随着年龄的增…

(矩阵) 289. 生命游戏 ——【Leetcode每日一题】

❓ 289. 生命游戏 难度&#xff1a;中等 根据 百度百科 &#xff0c; 生命游戏 &#xff0c;简称为 生命 &#xff0c;是英国数学家约翰何顿康威在 1970 年发明的细胞自动机。 给定一个包含 m n 个格子的面板&#xff0c;每一个格子都可以看成是一个细胞。每个细胞都具有一…

【算法设计与分析qwl】伪码——顺序检索,插入排序

伪代码&#xff1a; 例子&#xff1a; 改进的顺序检索 Search(L,x)输入&#xff1a;数组L[1...n]&#xff0c;元素从小到大排序&#xff0c;数x输出&#xff1a;若x在L中&#xff0c;输出x位置下标 j ,否则输出0 j <- 1 while j<n and x>L[j] do j <- j1 if x<…

2022年全网最全最细最流行的自动化测试工具有哪些?

一&#xff1a;前言 随着测试工程师技能和工资待遇的提升&#xff0c;甚至有一部分的开发人员开始转入测试岗位&#xff0c;跨入自动化领域的测试攻城狮越来越多。在自动化测试领域&#xff0c;自动化工具肯定占据了核心的位置。 本文总结了常用的测试自动化工具和框架&#x…

QT_day2

使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c;密码是否为…