C# 时间复杂度-这两种算法中哪一种更快?

C# 时间复杂度-这两种算法中哪一种更快?,c#,algorithm,performance,foreach,C#,Algorithm,Performance,Foreach,说明 foreach(User u in userList) { foreach(Order o in u.orders) { orderList.Add(o); foreach(Product p in o.products) { productList.Add(p); } } } foreach(User u in userList) { foreach(Order o in u.orders)

说明

foreach(User u in userList) {
    foreach(Order o in u.orders) {
        orderList.Add(o);
        foreach(Product p in o.products) {
            productList.Add(p);
        }
    }
}
foreach(User u in userList) {
    foreach(Order o in u.orders) {
        orderList.Add(o);
    }
}

foreach(Order o in orderList) {
    foreach(Product p in o.products) {
        productList.Add(p);
    }
}
此程序的目标是从用户中填充订单列表 订单和每个订单的productList。(请忽略此伪C代码中可能出现的语法错误)

数据结构

class User {
    List<Order> orders; 
}

class Order {
    List<Product> products;
}

class Product {
    int price;
}

List<User> userList = GetUsersFromDB();

List<Order> orderList     = new List<Order>();  
List<Product> productList = new List<Product>();
第二版

foreach(User u in userList) {
    foreach(Order o in u.orders) {
        orderList.Add(o);
        foreach(Product p in o.products) {
            productList.Add(p);
        }
    }
}
foreach(User u in userList) {
    foreach(Order o in u.orders) {
        orderList.Add(o);
    }
}

foreach(Order o in orderList) {
    foreach(Product p in o.products) {
        productList.Add(p);
    }
}
我的想法

class User {
    List<Order> orders; 
}

class Order {
    List<Product> products;
}

class Product {
    int price;
}

List<User> userList = GetUsersFromDB();

List<Order> orderList     = new List<Order>();  
List<Product> productList = new List<Product>();
  • 第一程序T(n)=O(n^3)
  • 第二程序T(n)=O(n^2)+O(n^2)
因此第二个程序更快,对吗


概述

你对第二个案例的分析是错误的。由于第一个循环的每个内部内容在orderlist中都有一个条目,
foreach(orderlist中的Order o)
在n^2个项目上循环。话虽如此,有一个免责声明,n在这里不是很有意义,因为它代表多个事物

最好用u,o和p来代替

案例1

第一个显然是
O(uop)

案例2

此案例有两组循环。第一对循环是
O(uo)
,正如您所期望的那样

然后,第二对循环以
uo
项的循环开始,然后是O(p)的内部循环,因此第二对循环是
O(uop)
。总的来说,这使得其
O(uo)+O(uop)
相当于
O(uop)
,与案例1相同

从本质上讲,第二种情况只是稍微改变了一下,实际上根本没有改变基本算法

现实世界


一如既往,如果你真正关心的是现实世界的性能,而不仅仅是理论上的算法复杂性(这在查看特定情况时并不总是有用),那么请对你的两种技术的性能进行基准测试。

概述

你对第二个案例的分析是错误的。由于第一个循环的每个内部内容在orderlist中都有一个条目,
foreach(orderlist中的Order o)
在n^2个项目上循环。话虽如此,有一个免责声明,n在这里不是很有意义,因为它代表多个事物

最好用u,o和p来代替

案例1

第一个显然是
O(uop)

案例2

此案例有两组循环。第一对循环是
O(uo)
,正如您所期望的那样

然后,第二对循环以
uo
项的循环开始,然后是O(p)的内部循环,因此第二对循环是
O(uop)
。总的来说,这使得其
O(uo)+O(uop)
相当于
O(uop)
,与案例1相同

从本质上讲,第二种情况只是稍微改变了一下,实际上根本没有改变基本算法

现实世界



一如既往,如果你真正关心的是真实世界的性能,而不仅仅是理论上的算法复杂性(这在查看具体案例时并不总是有用),那么请对你的两种技术的性能进行基准测试。

你尝试过吗?n表示什么?添加操作是在固定时间内执行的吗?@YvesDaoust Im假设列表的长度。从技术上讲,它应该是
O(u*O*p)
@Mitchel0022:对不起,我是在问OP。作为一个完整的旁白,如果效率是游戏的名称,你最好为
foreach
上的
循环实现香草
,因为
foreach
将创建枚举数实例。一个小的开销,但仍然有…你试过了吗?n表示什么?添加操作是在固定时间内执行的吗?@YvesDaoust Im假设列表的长度。从技术上讲,它应该是
O(u*O*p)
@Mitchel0022:对不起,我是在问OP。作为一个完整的旁白,如果效率是游戏的名称,你最好为
foreach
上的
循环实现香草
,因为
foreach
将创建枚举数实例。虽然开销很小,但是……第二种情况不是
uo
+
op
?@FatihAkici:第二种情况有两组循环。第一对循环是
uo
,正如您所期望的那样。第二对遍历orderList,我们知道它包含
uo
项,因此它实际上是
uop
。因此,总体而言,它是
uo+uop
,相当于
uop
。我会看看能否在我的答案中更好地解释这一点。@FatihAkici:我已经更新了答案,希望能更清楚。如果您认为它还需要更多的工作,请告诉我。哦,最后一个循环是在orderList上迭代,而不是在orders上。我的错,谢谢你澄清CA+1on@法蒂哈奇:没问题。第一次读这个问题时我也被弄糊涂了——我觉得“这根本不是在做同样的事情!”:)第二个例子不是
uo
+
op
?@FatihAkici:第二个例子有两组循环。第一对循环是
uo
,正如你所预料的那样。第二对遍历orderList,我们知道它包含
uo
项,因此它实际上是
uop
。因此,总体而言,它是
uo+uop
,相当于
uop
。我会看看能否在我的答案中更好地解释这一点。@FatihAkici:我已经更新了答案,希望能更清楚。如果您认为它还需要更多的工作,请告诉我。哦,最后一个循环是在orderList上迭代,而不是在orders上。我的错,谢谢你澄清CA+1on@法蒂哈奇:没问题。我第一次读到这个问题时也感到困惑——我觉得“这根本不是在做同样的事情!”