正在添加到集合 O(n)

Is adding to a set O(n)?

本文关键字:集合 添加      更新时间:2023-10-16

既然集合只能有唯一的值,这是否意味着每次将元素添加到集合时,它都必须检查它是否等于那里的每个元素,因此是O(n)?

如果是这种情况,这将使它们比 arrayLists 慢得多,因此您唯一应该实际使用它们的时间是确保您的元素都是唯一的还是它们还有其他优点?

这取决于set的实现。

C++

C++中的std::set通常实现为红黑树,并保证插入复杂度为 O(log(n))(源)。

std::set 是一个关联容器,其中包含一组排序的 Key 类型的唯一对象。排序是使用键比较功能比较完成的。搜索、删除和插入操作具有对数复杂性。

C++11的std::unordered_set的插入复杂度为O(1)(来源)。

无序集是一个关联容器,其中包含 Key 类型的唯一对象集。搜索、插入和删除具有平均恒定时间复杂度。

.JAVA

在 Java 中,向HashSet添加元素是 O(1)。从文档中:

此类为基本操作(添加、删除、包含和大小)提供恒定的时间性能,假设哈希函数在存储桶中正确分散元素

将元素插入TreeSet是 O(log(n))。

此实现为基本操作(添加、删除和包含)提供有保证的 log(n) 时间成本。

所有实现Set的类都可以在文档中找到。

结论

在大多数情况下,添加到set并不比添加到ArrayListstd::vector慢。但是,set不一定按插入顺序保留项目。此外,访问集合的第 N 个元素比对 ArrayListstd::vector的相同操作更复杂。每种方法都有其优点和缺点,应相应地使用。

你标记了这个 Java 和C++,所以我会回答这两个问题:

在C++ std::set中是一个有序的容器,可能实现为树。无论实现如何添加到集合并检查集合中的元素是否保证为 O(log n)。对于 C++11 中新增的 std::unordered_set,这些操作是 O(1)(给定适当的哈希函数)。

在Java中,java.util.Set是一个接口,可以有许多不同的类来实现它们。操作的复杂性取决于这些类。最常用的集合是 TreeSetHashSet 。前者的运算是O(log n),后者的运算是O(1)(再次给出适当的哈希函数)。

C++ std::set通常实现为黑红树。这意味着添加到它将是 O(log n)。

C++ std::unordered_set插入作为哈希表实现,因此插入为 O(1)。

您忘记了集合可能不是元素的批量列表; 它可以以搜索比O(N)快得多的方式排列(确实如此)。

http://en.wikipedia.org/wiki/Set_(abstract_data_type)#Implementations

这取决于。不同的语言提供不同的实现。甚至Java也有2个不同的集合:TreeSet和HashSet。添加是树集是O(logn),因为元素已经按顺序排列。

在 CPP 中,集合通常实现为二叉搜索树。 话虽如此,插入将需要 O(log(N)) 时间复杂度。 当涉及到唯一键时,您可以尝试在 CPP 中hash_map,它在插入时具有恒定的时间复杂度。

时间复杂度:包装类与基元。

  • 当值更改时,尤其是多次更改时,基元会提供更好的时间。

例:

   int counter = 0; 
     while (x>y){ 
     counter++; 
     }

比以下速度快得多:

Integer counter = 0; 
 while (x>y){ 
 counter++; 
 }
  • 当值保持不变时,包装类会提供更好的时间,因为只有指向包装类的指针传递给算法。它在定义不更改其值的方法的参数时非常方便。

例:

 public int sum (Integer one, Integer two, Integer three){ 
 int sum = one+two+three; 
 return sum; 
 }

public int sum (int one, int two, int three){ 
 int sum = one+two+three;
 return sum; 
 }

传递给方法的值可能是原始的,重要的是方法本身参数的定义,也就是说:

 public int sum (Integer one, Integer two, Integer three){ 
 int sum = one+two+three;                                               
 return sum; 
 } 
 int a = 1; int b = 2; int c = 3;                                       
 public int sum (a, b, c){ 
 int sum = a+b+c; 
 return sum; 
 }

如上所述使用包装类的累积效应可以显著提高程序的性能。

正如其他人所说,集合通常是树O(logn)或哈希表O(1)。但是,有一件事您可以确定:任何健全的映射实现都不会具有 O(n) 行为。