Худшая сложность случая создания HashSet <интервал> из коллекции

I have a collection of int values with which I populate a HashSet in the following manner -

var hashSet = new HashSet(myIEnumerable);

Assuming that iterating the IEnumerable is O(n), what will be the worst case complexity of creating a HashSet in such a way?

10
nl ja de

3 ответы

Документация на самом деле указывает:

Этот конструктор - O (n) операция, где n - количество элементы в параметре коллекции.

http://msdn.microsoft.com/en-us/library/bb301504.aspx

7
добавлено
И да, доктора неправы, как удивление...
добавлено автор usr, источник
Конечно, различный ints может столкнуться. Если есть 7 ведер тогда, ints n и n+7 сталкиваются. => Этот ответ не обращается к работе худшего случая.
добавлено автор usr, источник
@UghSegment, Чтобы добавить к CodeInChaos' ответ, это - и худший случай и амортизируемая сложность. (Учитывая, что он объяснил почему it' s возможный для него, чтобы быть обоими, I' m заявление that' s на самом деле случай здесь.)
добавлено автор Servy, источник
@UghSegment Вы имеете в виду "среднюю" сложность, не "амортизируемую". "Амортизируемый" используется для операций, которые являются иногда дорогими (например, удвоение запоминающего устройства) и дешевыми для остальных. То понятие ортогональное к среднему числу против worstcase.
добавлено автор CodesInChaos, источник
@UghSegment Действительно охлаждаются. CodesInChaos ожидал это в его комментарии к одному из других ответов.
добавлено автор Jeppe Stig Nielsen, источник
Отладка Попытки @UghSegment и осмотр , частный области HashSet <> с отладчиком. Вы будете, вероятно, видеть, какие "ведра" или модуль выбран. Возможно, для данного размера вашей входной коллекции, можно выяснить, какие ведра используются. Тогда сделайте свою коллекцию того же самого размера, но выберите участников злым способом. Это должно быть возможно. Таким образом, возможно, it' s хуже, чем O (n), в конце концов, для "злого" входа.
добавлено автор Jeppe Stig Nielsen, источник
@UghSegment Как люди написали в другом месте на этой странице, для интервал , GetHashCode() , метод просто возвращается это . Например (-987654321).GetHashCode() ==-987654321 . Поэтому вы никогда не получаете столкновения с интервал . Согласно документации, перегрузка конструктора вы используете наборы способность к необходимому размеру немедленно, поэтому возможно, HashSet <> won' t должны изменить размеры себя. В этом случае я подозревал бы, что сложность худшего случая - O (n).
добавлено автор Jeppe Stig Nielsen, источник
@UghSegment, Что делает вас, думают, худший случай. Алгоритм проверяет первый элемент myIEnumerable , проверки если it' s уже в словаре (that' s в постоянное время), и в противном случае добавляет его. Тогда проверяет второй элемент myIEnumerable , посмотрите если it' s уже в словаре, и иначе добавляет его. То, что вы думаете, является худшим случаем? Возможно, это, все элементы отличны, но хэш-коды сталкиваются каждый раз? Попытайтесь делать класс, который отвергает GetHashCode() , чтобы всегда возвратиться 0, и отвергает , Равняется (возражают) , чтобы возвратиться ReferenceEquals . Тогда мера для себя!
добавлено автор Jeppe Stig Nielsen, источник
Нет, в общем худшем случае квадратное, конечно, но это - для объектов с тем же самым GetHashCode() продукция. I' m задающийся вопросом о int' s.
добавлено автор SergeyS, источник
@JeppeStigNielsen Мой вопрос является определенно о худшей сложности случая HashSet <интервал> , не HashSets в целом.
добавлено автор UghSegment, источник
@JeppeStigNielsen, которые я использовал.NET Отражатель, чтобы узнать, как HashSet получает модуль, оценивают его использование в вычислении хеширования. Я использовал эту информацию, чтобы предоставить конструктору различные ценности, которые всю осень в тот же самый индекс и исполнительную деградацию в моих тестах, казалось, были почти совершенно квадратными. Кажется, в конце концов, что худшая сложность случая действительно O (n^2) , даже без столкновений в значениях хэш-функции.
добавлено автор UghSegment, источник
@JeppeStigNielsen, Именно это я думал. Однако я полагаю, что несмотря на наличие никаких хэш-коллизий все еще возможно произвести столкновения с индексом элемента в ведрах - и это - то, что заставляет меня думать, что эта операция могла бы быть выше, чем O (n) в определенных ситуациях. Я мог бы быть неправым хотя, так как я don' t знают очень хорошо, как HashSet осуществляется в.NET.
добавлено автор UghSegment, источник
@Servy я понимаю, что оба могут быть тем же самым; но это doesn' t действительно затрагивают мой вопрос - худший случай сложность O (n) ?
добавлено автор UghSegment, источник
Но это - сложность худшего случая или амортизируемая сложность?
добавлено автор UghSegment, источник

Можно принести худший случай к O (N^2) , поставляя объекты, что вся мешанина к тому же самому ведру , когда набор достигает своего максимального размера . Например, если вы передаете последовательность 17519 интервал s построенный как

x[i] = i * 17519

for i between 1 and 17519, inclusive, all numbers will hash to the initial bucket on Microsoft's implementation of HashSet, taking O(N^2) to insert:

var h = new HashSet(Enumerable.Range(1, 17519).Select(i => i*17519));

Установите кир kpoint и исследуйте h в отладчике. Взгляд на Сырое Представление/Непубличные участники/m_buckets. Заметьте, что у начального ведра есть 17519 элементов, в то время как оставление 17518 у всех есть ноли.

5
добавлено
@Servy Мой пункт - это, так как вы не имеете никакого контроля над.NET' s GetHashCode Int32 , который вы не можете вызвать новый HashSet <интервал> (myIEnumerable) от OP в O (N^2) территория. Когда вы управляете GetHashCode , можно вызвать HashSet , чтобы заблокировать неопределенно:) HashSet <долго> является серединой дороги: худшее, которое можно сделать, O (N^2) , поставляя особенно плохую последовательность для.NET внедрения Int64. GetHashCode .
добавлено автор dasblinkenlight, источник
@CodesInChaos Вы правы, можно вызвать O (N^2) . Я не понял, что достаточно рассмотреть только последний размер, думая, что необходимо попробовать 3, 7, 17, 37, 89, и так далее. Спасибо за наконечник!
добавлено автор dasblinkenlight, источник
Можно вызвать хуже, чем O (n^2) время, если вы принимаете таможенное время с бедными или злонамеренный GetHashCode . У вас мог быть GetHashCode , который никогда не возвращается, например, и никогда не быть в состоянии выполнить задачу, или у вас мог быть GetHashCode метод, который берет O (n^2) время, чтобы вычислить, таким образом делая HashSet методы... хуже, чем это.
добавлено автор Servy, источник
Для интервал s вы все еще может создать столкновения индекса ведра. Просто добавьте ints, которые являются кратным числом Способность . Я ожидаю O (n^2) дополнительное выполнение в таком сценарии, но I' m слишком ленивый, чтобы выяснить предпочтительные мощности HashSet .
добавлено автор CodesInChaos, источник
Я wouldn' t быть удивленным, если it' s O (N^2)
добавлено автор CodesInChaos, источник
Но что относительно неамортизируемой, худшей сложности случая?
добавлено автор UghSegment, источник

Быстрый эксперимент с выродившимся хэш-кодом (константа) показывает, что это квадратное.

for(int n=0;n<100;n++)
{
    var start=DateTime.UtcNow;
    var s=new HashSet(Enumerable.Range(0,n*10000).Select(_=>new Dumb()));
    Console.Write(n+" ");
    Console.WriteLine((int)((DateTime.UtcNow-start).TotalSeconds*10));
}

продукция:

0 0
1 8
2 34
3 73
4 131

Now some claim that you don't get multi collisions of the HashCode for ints. While that's technically true, what matters for performance isn't a collision of the HashCode, but a collision of the bucket index. I think HashSet uses something like bucket = (hash&0x7FFFFFFF)%Capacity. So if you add a sequence of integers that's a multiple of a preferred bucket size, it'll still be very slow.

2
добавлено
@SergeyS , интервал является одним из просто горстки типов, у которого нет столкновений. Количество возможных интервал ценности не больше, чем количество возможных интервал ценности, таким образом, хэш-код для интервал ценности на самом деле уникален для различных ценностей. (Другими словами, it' s хэш-код может просто возвратить себя.) Другие типы, такие как байт и случайная работа также имеет меньше ценностей, чем интервал и, никогда не сталкиваются - также.
добавлено автор Servy, источник
Даже с ним it' s возможный вызвать столкновения индекса ведра. It' s просто более раздражающий, чтобы осуществить. | @UghSegment it' s то же самое с конструктором. См. обновленный код.
добавлено автор CodesInChaos, источник
Если все объекты возвращают тот же самый хэш-код, чем да, это - O (n*n) из-за столкновений. Но OP' s вопрос был о коллекции int' s. Так I' m задающийся вопросом, как трудный (возможный?) должен был бы выбрать пару int' s с равными хэш-кодами.
добавлено автор SergeyS, источник
Пожалуйста, предоставьте код
добавлено автор SergeyS, источник
Я don' t думают тест, который вы выполнили, совпадает с тем, что я описал в своем вопросе. Я определенно интересуюсь худшей сложностью случая прохождения коллекции с известной суммой элементов к HashSet конструктор, не, сложность многократных Добавляет требования.
добавлено автор UghSegment, источник
Microsoft Stack Jobs
Microsoft Stack Jobs
1 788 участник(ов)

Work & freelance only Microsoft Stack. Feed https://t.me/Microsoftstackjobsfeed Чат про F#: @Fsharp_chat Чат про C#: @CSharpChat Чат про Xamarin: @xamarin_russia Чат общения:@dotnettalks

Microsoft Developer Community Chat
Microsoft Developer Community Chat
584 участник(ов)

Чат для разработчиков и системных администраторов Microsoft Developer Community. __________ Новостной канал: @msdevru __________ Баним за: оскорбления, мат, рекламу, флуд, флейм, спам, NSFW контент, а также большое количество оффтоп тем. @banofbot