Почему в .NET нет класса Tree <T>?

87

Библиотека базовых классов в .NET имеет отличные структуры данных для коллекций (List, Queue, Stack, Dictionary), но, как ни странно, не содержит никаких структур данных для двоичных деревьев. Это очень полезная структура для определенных алгоритмов, например для тех, которые используют преимущества различных путей обхода. Ищу правильно написанную бесплатную реализацию.

Я просто слепой и не нахожу его ... где-то в BCL? Если нет, может ли кто-нибудь порекомендовать бесплатную или открытую библиотеку C # /. NET для двоичных деревьев? Желательно тот, который использует дженерики.

РЕДАКТИРОВАТЬ: чтобы уточнить, что я ищу. Меня не интересуют упорядоченные коллекции словарей, которые внутренне используют дерево. На самом деле меня интересует двоичное дерево - такое, которое раскрывает свою структуру, чтобы вы могли делать такие вещи, как извлечение поддеревьев или выполнение обхода узлов после исправления. В идеале такой класс может быть расширен для обеспечения поведения специализированных деревьев (например, красный / черный, AVL, сбалансированный и т. Д.).

Л.Бушкин
источник
Согласовано. Иногда мне нужно найти (за время O (Log N)) два узла, которые связывают значение (когда значение не найдено в коллекции). Например, коллекция (дерево) содержит 13 и 17 (среди прочих), и я ищу наибольшее число меньше и меньше 16. Дерево могло бы это сделать, но словари, отсортированные списки и хеш-таблицы принимают O (N) .
Les

Ответы:

31

Вы правы, в BCL ничего нет. Я подозреваю, что это связано с тем, что выбор использования дерева обычно является деталью реализации, а в остальном - нетрадиционным способом доступа к данным. То есть вы не говорите «двоичный поиск элемента № 37»; вместо этого вы говорите: «Дайте мне элемент №37».

Но вы смотрели на C5 ? Это очень удобно, и у них есть несколько реализаций дерева ( 1 , 2 , 3 ).

Джон Феминелла
источник
3
C5 поддерживает красно-черные деревья, но не B-Tree. Это различия, о которых люди должны знать. B-Tree более оптимально для дерева на основе диска или дерева на основе большой памяти. Больше узлов хранится в том же месте, поэтому вы получаете лучшую производительность кеш-памяти процессора и ускоряете чтение и запись на диск.
AnthonyLambert
68

Вы можете определить свое собственное:

public class MyTree<K, V> : Dictionary<K, MyTree<K, V>>
{
    public V Value { get; set; }
}

Или без ключа:

public class MyTree<V> : HashSet<MyTree<V>>
{
    public V Value { get; set; }
}
Джейсон
источник
Однако для этого нужно знать, сколько уровней дерева вы будете обрабатывать во время компиляции, я ошибаюсь?
Veverke 03
1
Нет, компилятор C # поддерживает этот синтаксис.
Джейсон
2
Остерегайтесь, чтобы элементы не упорядочивались таким образом
Себастьян
@Veverke Возможно, вы думали о шаблонах C ++. Дженерики .NET - это типы среды выполнения.
Tom Blodget
Мне любопытно. Как вы это используете? Практически? Любой образец?
Syaiful Nizam Yahya
39

Что бы вы хотели от такой реализации?

Двоичное дерево? Красно-черный? Радиксное дерево? B-дерево? R-дерево? R * -дерево?

Дерево - это больше шаблон, чем структура данных, и они, как правило, используются там, где важна производительность (поэтому детали реализации, вероятно, тоже имеют значение). Если бы BCL включал какой-то древовидный класс, вам все равно нужно было бы свернуть свой собственный

Алан Харфорд
источник
1
Лучший ответ на часть вопроса "почему".
Joel Coehoorn 02
И это только деревья поиска. Есть также деревья выражений, прядь решения, ...
Хенк Холтерман
Действительно, важны детали реализации. В моем случае я хочу реализовать некоторые алгоритмы, которые выполняли бы различные обходы (инфиксный, постфиксный) на организованном наборе данных в рамках серии преобразований. Древовидная структура - самый элегантный способ решения моей проблемы.
Л.Бушкин 02.06.2009,
11
В параллельной вселенной кто-то задается вопросом: «Почему в .Net нет типов списков?», И они получают ответ: «Что бы вы хотели от такой реализации? Массив? Связанный список? Очередь? толковый словарь?" Я думаю, что это несоответствующий ответ.
rymdsmurf
12

SortedSet<T>реализовано как двоичное дерево поиска исх . SortedDictionary<TKey, TValue>внутренне использует, SortedSet<T>так что это тоже бинарное дерево поиска ref .

Мэтт Брунелл
источник
5
К сожалению, это просто реализации упорядоченных карт и списков. Ни то, ни другое бесполезно для повторного использования в качестве двоичного дерева - эти древовидные структуры являются просто деталью реализации коллекции. Я действительно ищу класс, который предоставляет древовидную структуру.
LBushkin 02
9

Нет, Tree<T>в BCL нет никакого « -подобного» типа (что меня тоже всегда озадачивало), но вот хорошая статья, которая проведет вас через реализацию вашего собственного на C #.

Я думаю, вы могли бы привести аргумент, что древовидные структуры данных реже используются в приложениях, для которых обычно используется .NET (бизнес-приложения, приложения для перемещения данных и т. Д.). Тем не менее, я согласен с вами, странно, что BCL вообще не имеет реализации.

Эндрю Хэйр
источник
-5

Там в TreeNode вы можете использовать. Он не является общим и скрытым в формах Windows и используется с элементом управления treeview, но вы можете использовать его и в другом месте.

Джоэл Кохорн
источник
Да, но у него просто свойство Tag типа System.Object ype. Параметр Generic <T> отсутствует
Хенк Холтерман
3
Я всегда чувствую себя странно из-за таких вещей. Это менее заметно в вашем конкретном примере, но если люди регулярно перенаправляют классы, скажем, из зависимостей, это может привести к труднообъяснимым зависимостям и может вызвать проблемы, если повторно назначенный класс изменится неожиданным образом через версии зависимостей.
Пол Мори
4
Какая польза от его использования? Узел дерева обычно не имеет соответствующей функциональности. Он просто содержит ссылки на потомков и, в конечном итоге, на родителя. Нет причин использовать для этого класс System.Windows.Forms! Просто напишите сами - через минуту или меньше.
user492238