Когда использовать предзаказ, обратном порядке, и симметричного бинарного дерево поиска обход стратегий
недавно я понял, что, используя множество BST в моей жизни, я никогда даже не рассматривал использование чего-либо, кроме обхода Inorder (в то время как я знаю и знаю, как легко адаптировать программу для использования обхода до/после заказа).
какие примеры того, когда использовать preorder/postorder практически? Когда в этом больше смысла, чем в порядке вещей?
5 ответов
когда использовать стратегию обхода предзаказа, In-Order и Post-Order
прежде чем вы сможете понять, при каких обстоятельствах использовать pre-order, in-order и post-order для двоичного дерева, вы должны точно понять, как работает каждая стратегия обхода. В качестве примера используйте следующее дерево.
корень дерева 7, самый левый узел -0, самый правый узел 10.
предварительный заказ обхода:
сводка: начинается с корня (7), заканчивается на самом правом узле (10)
последовательность обхода: 7, 1, 0, 3, 2, 5, 4, 6, 9, 8, 10
в порядке обхода:
сводка: начинается с самого левого узла (0), заканчивается на крайнем правом узле (10)
обход Последовательность: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
обход в обратном порядке:
резюме: начинается с самого левого узла (0), заканчивается корневой (7)
последовательность обхода: 0, 2, 4, 6, 5, 3, 1, 8, 10, 9, 7
когда использовать Pre-Order, in-order или Post-Order?
стратегия обхода, которую выбирает программист, зависит от конкретных потребностей разрабатываемого алгоритма. Цель-скорость, поэтому выберите стратегию, которая приносит вам узлы, которые вам нужны быстрее всего.
Если вы знаете, что вам нужно исследовать корни, прежде чем проверять любые листья, вы выбираете предзаказ потому что вы столкнетесь со всеми корнями до всех листьев.
Если вы знаете, что вам нужно исследовать все листья перед любыми узлами, вы выбираете после того потому что вы не тратите время на проверку корней в поисках листья.
Если вы знаете, что дерево имеет неотъемлемую последовательность в узлах, и вы хотите сгладить дерево обратно в исходную последовательность, чем в порядке обход должен быть использован. Дерево будет расплющено точно так же, как было создано. Обход перед заказом или после заказа может не разматывать дерево обратно в последовательность, которая использовалась для его создания.
рекурсивные алгоритмы для предварительного порядка, в порядке и Post-order (C++):
struct Node{
int data;
Node *left, *right;
};
void preOrderPrint(Node *root)
{
print(root->name); //record root
if (root->left != NULL) preOrderPrint(root->left); //traverse left if exists
if (root->right != NULL) preOrderPrint(root->right);//traverse right if exists
}
void inOrderPrint(Node *root)
{
if (root.left != NULL) inOrderPrint(root->left); //traverse left if exists
print(root->name); //record root
if (root.right != NULL) inOrderPrint(root->right); //traverse right if exists
}
void postOrderPrint(Node *root)
{
if (root->left != NULL) postOrderPrint(root->left); //traverse left if exists
if (root->right != NULL) postOrderPrint(root->right);//traverse right if exists
print(root->name); //record root
}
Если бы я хотел просто распечатать иерархический формат дерева в линейном формате, я бы, вероятно, использовал предзаказ. Например:
- ROOT
- A
- B
- C
- D
- E
- F
- G
Pre-Order /in-order / Post-order использование: простые слова
предзаказ: используется для создания копии дерева Пример: если вы хотите создать реплику дерева и вам нужны значения узлов в массиве, и когда вы вставляете эти значения из индекса 0 в новое дерево, вы получаете реплику
по порядку:: получить значения узла в нерастущем порядке
Post-order: : когда вы хотите удалить дерево из от листа к корню
есть тонны мест, где вы видите, что эта разница играет реальную роль.
один большой я укажу в генерации кода для компилятора. Рассмотрим утверждение:
x := y + 32
способ генерации кода для этого (наивно, конечно) сначала генерировать код для загрузки y в регистр, загрузки 32 в регистр, а затем генерировать инструкцию для добавления двух. Потому что что-то должно быть в регистре, прежде чем манипулировать им (предположим, вы всегда можете делать постоянные операнды, но что угодно), вы должны сделать это таким образом.
В общем, ответы, которые вы можете получить на этот вопрос, в основном сводятся к следующему: разница действительно имеет значение, когда существует некоторая зависимость между обработкой разных частей структуры данных. Вы видите это при печати элементов, при создании кода (внешнее состояние имеет значение, вы можете просмотреть это монадически, конечно) или при выполнении других типов вычислений над структура, которая включает вычисления в зависимости от детей, обрабатываемых в первую очередь.
Pre-и post-order относятся к рекурсивным алгоритмам сверху вниз и снизу вверх соответственно. Если вы хотите написать данный рекурсивный алгоритм на двоичных деревьях итеративным образом, это то, что вы по существу сделаете.
кроме того, обратите внимание, что последовательности до и после заказа вместе полностью определяют дерево под рукой, давая компактное кодирование (для разреженных деревьев как минимум).