Я считаю, что наиболее эффективной формой для записи функций для древовидных структур в целом является следующий формат псевдокода.
function someActionOnTree() {
return someActionOnTree(root)
}
function someActionOnTree (Node current) {
if (current is null) {
return null
}
if (current is not the node I seek) {
//logic for picking the next node to move to
next node = ...
next node = someActionOnTree(next node)
}
else {
// do whatever you need to do with current
// i.e. give it a child, delete its memory, etc
current = ...
}
return current;
}
Эта рекурсивная функция рекурсивно пересекает множество вершин структуры данных. Для каждой итерации алгоритма он либо ищет узел для рекурсии функции, либо перезаписывает ссылку структуры данных на этот узел со значением итерации алгоритма на этом узле. В противном случае он перезаписывает значение узла (и, возможно, выполняет другой набор логик). Наконец, функция возвращает ссылку на узел параметра, который необходим для этапа перезаписи.
Это, как правило, самая эффективная форма кода, которую я нашел для структур данных дерева в C++. В концепциях применяются и другие структуры: вы можете использовать рекурсию этой формы, где возвращаемое значение всегда является ссылкой на фиксированную точку в плоском представлении вашей структуры данных (в основном, всегда возвращайте все, что должно быть на том месте, где вы «смотрю»).
Вот приложение этого стиля для функции удаления двоичного дерева поиска, чтобы украсить мою точку.
function deleteNodeFromTreeWithValue(value) {
return deleteNodeFromTree(root, value)
}
function deleteNodeFromTree(Node current, value) {
if (current is null) return null
if (current does not represent value) {
if (current is greater than my value) {
leftNode = deleteNodeFromTree(leftNode, value)
} else {
rightNode = deleteNodeFromTree(rightNode, value)
}
}
else {
free current's memory
current = null
}
return current
}
Очевидно, что есть много других способов, чтобы написать этот код, но из моего опыта, это оказалось наиболее эффективным способом. Обратите внимание, что производительность на самом деле не пострадает от указателей перезаписи, поскольку оборудование уже кэшировало узлы. Если вы изучаете улучшенную производительность своего дерева поиска, я бы рекомендовал посмотреть на специализированные деревья, такие как самобалансирующие (деревья AVL), B-деревья, красно-черные деревья и т. Д.
Дополнительный код НИКОГДА не плохая вещь. – Aziz
@ Азиз: Да, это так. Больше кода означает большую сложность, что означает больше ошибок, что означает, что это сложно сделать правильно. Первый проход выбирает меньшую сложность и простое решение. Если время (профилирование) указывает, что это недостаточно, то оптимизируйте (никогда раньше). –