通过与 Jira 对比,让您更全面了解 PingCode

  • 首页
  • 需求与产品管理
  • 项目管理
  • 测试与缺陷管理
  • 知识管理
  • 效能度量
        • 更多产品

          客户为中心的产品管理工具

          专业的软件研发项目管理工具

          简单易用的团队知识库管理

          可量化的研发效能度量工具

          测试用例维护与计划执行

          以团队为中心的协作沟通

          研发工作流自动化工具

          账号认证与安全管理工具

          Why PingCode
          为什么选择 PingCode ?

          6000+企业信赖之选,为研发团队降本增效

        • 行业解决方案
          先进制造(即将上线)
        • 解决方案1
        • 解决方案2
  • Jira替代方案

25人以下免费

目录

平均查找长度与时间复杂度的区别

平均查找长度与时间复杂度的区别:平均查找长度更关注于具体算法查找某个元素需要比较的次数,而时间复杂度则更强调算法执行时间与数据规模之间的关系。因此,两者虽然有些相似之处,但实际上是不同的概念。

一、平均查找长度与时间复杂度的区别

平均查找长度(Average Search Length,ASL)和时间复杂度(Time Complexity)都是衡量算法效率的指标,但它们从不同角度出发。ASL反映了查找过程中平均需要比较的关键字数,而时间复杂度则描述了算法运行时间与问题规模之间的关系。具体来说ASL更关注具体算法查找某个元素需要比较的次数,而时间复杂度更强调算法执行时间与数据规模之间的关系;ASL的计算涉及到顺序查找、折半查找和哈希表等算法,而时间复杂度通常使用大O符号来表示算法执行所需时间随着问题规模n的增加而增长的上限;ASL和时间复杂度都可以用来衡量算法效率,但它们的主要应用场合略有不同。

二、如何计算散列表的平均查找长度

1、查找成功

查找成功意味着需要查找的元素一定在表中,所以需要计算表中的每个元素通过 散列法&处理冲突的方法 得出的查找次数,求和再除以元素个数。

查询目标:散列表中的每个元素

查询过程

  • 通过散列函数查询该元素地址;
  • 访问地址,此次元素的查找次数+1;
  • 若地址元素和目标元素不等,通过解决冲突的方法得到下一个地址,并转向第二步(解决冲突的方法 考试常用线性探测法);
  • 若地址元素和目标元素相等,停止此元素的查找。

计算方法:散列表中所有元素的查找次数之和/元素个数

2、查找失败

查找不成功意味着查找的元素一定不在表中,所以与表中元素个数无关。每次查询查到地址为空为止,查到空意味着不需要再查询,也就是失败。

查询目标:使用散列函数可能得到的所有地址(数组下标),假设H(key)=7,则意味着查找失败时可能对应的地址有7个。

查询过程

  • 访问地址,此次元素的查找次数+1;
  • 若地址不为空,通过解决冲突的方法得到下一个地址,并转向名列前茅步;
  • 若地址为空则停止。

计算方法:散列函数对应所有地址元素的查找次数之和/散列值

3、易混淆

为何查找成功除以散列表元素个数,而查找失败除以散列值呢?

  • 假设把所有元素对应的关键字分为两类,一类是在散列表中的数(查找会成功),一类是不在散列表中的数(查找会失败)。
  • 要求查找成功的平均查找长度时,意味着这个数一定在散列表中,所以我们只需要考虑散列表中的元素即可。
  • 要求查找不成功的平均查找长度时,意味着这个数一定不在散列表中,这个时候我们需要将不在散列表中的数再次分类,假设散列值为p,就可以将不在散列表中的数再次分为p 类,每一类分别为地址映射到i(0≤i≤p-1)的数,分别计算p类中每一类的查找次数即可。

为何查找成功以地址元素和目标元素相等为停止, 而查找失败以地址为空为停止?

  • 查找成功意味着目标元素一定在散列表中,即一定会查到。
  • 查找失败意味着目标元素不在散列表中,若地址元素不为空,那地址元素肯定和目标元素不等。但只有到地址为空,才能断定查找失败。

三、时间复杂度的分析与计算方法

1、循环次数非常多原则

当n变得越来越大时,公式中的低阶,常量,系数三部分影响不了其增长趋势,可以直接忽略他们,只记录一个最大的量级就可以了。因此我们在计算时间复杂度时,只需关注循环次数非常多的那段代码即可

int sumFunc(int n) {
    int sum = 0;     //执行1次,忽略不计
    for (int i = 0; i < n; i++) {
        sum += i;   // 循环内执行次数非常多,执行次数为n次,因此时间复杂度记为O(n)
    }  
    return sum;     //执行1次,忽略不计
}

2、加法原则

int sumFunc(int n) {
    int sum = 0;     //常量级,忽略
    for (int i = 0; i < 99; i++) {
        sum += i;   //执行100次,还是常量级,忽略
    }  

    for (int i = 0; i < n; i++) {
        sum += i;   //执行n次
    }  

    for (int i = 0; i < n; i++){
        for (int j = 0; j < n; j++) {
            sum += i;   //执行n*n次
        }
    }
    return sum;
}

上述例子中,最大的两块代码时间复杂度分别为 O(n)和 O(n*n),其结果本应该是:T(n)=O(n)+O(n * n),我们取其中最大的量级,因此整段代码的复杂度为:O(n * n)。所以得出结论:量级最大的那段代码时间复杂度=总的时间复杂度

3、乘法原则

嵌套代码的复杂度等于嵌套内外代码复杂度的乘积。

void Func1(int n) {
    for (int i = 0; i < n; i++) {
        Func2(n);   //执行n次,每次都会调用Func2函数执行n次
    }
}
void Func2(int n) {
    int sum = 0;
    for (int i = 0; i < n; i++)
    {
        sum += 1;   //执行n次
    }
}

因此这段代码时间复杂度为O(n) * O(n) = O(n*n) = O(n*n),同理,如果将其中一个n换成m,那么它的时间复杂度就是O(n*m)

延伸阅读1:时间复杂度定义

在计算机科学中,时间复杂性,又称时间复杂度,算法的时间复杂度是一个函数,它定性描述该算法的运行时间。这是一个代表算法输入值的字符串的长度的函数。时间复杂度常用大O符号表述,不包括这个函数的低阶项和首项系数。使用这种方式时,时间复杂度可被称为是渐近的,亦即考察输入值大小趋近无穷时的情况。

相关文章