Я готовлюсь к собеседованию. Я застрял в одном из вопросов двоичного дерева:
Как мы можем вычислить сумму значений, присутствующих во всех узлах двоичного дерева?
Я готовлюсь к собеседованию. Я застрял в одном из вопросов двоичного дерева:
Как мы можем вычислить сумму значений, присутствующих во всех узлах двоичного дерева?
Элегантное рекурсивное решение (в псевдокоде):
def sum (node):
if node == NULL:
return 0
return node->value + sum (node->left) + sum (node->right)
то просто используйте:
total = sum (root)
Это правильно обрабатывает случай NULL root node.
И если вы хотите увидеть его в действии на С++, здесь некоторый код использует этот алгоритм. Во-первых, структура для функции node и sum
:
#include <iostream>
typedef struct sNode {
int value;
struct sNode *left;
struct sNode *right;
} tNode;
int sum (tNode *node) {
if (node == 0) return 0;
return node->value + sum (node->left) + sum (node->right);
}
Затем приведенный ниже код - это тестовый код жгута проводов для вставки узлов:
static tNode *addNode (tNode *parent, char leftRight, int value) {
tNode *node = new tNode();
node->value = value;
node->left = 0;
node->right = 0;
if (parent != 0) {
if (leftRight == 'L') {
parent->left = node;
} else {
parent->right = node;
}
}
return node;
}
И, наконец, главная функция для построения следующего дерева, которая охватывает все допустимые возможности (пустой node, node с двумя дочерними элементами node без детей, node с одним правом child и node с одним левым дочерним элементом):
10
/ \
7 20
/ \
3 99
\
4
\
6
Здесь показан код для построения этого дерева и представления суммы в разных точках:
int main (void) {
// Empty tree first.
tNode *root = 0;
std::cout << sum (root) << '\n';
// Then a tree with single node (10).
root = addNode (0, ' ', 10);
std::cout << sum (root) << '\n';
// Then one with two subnodes (10, 7, 20).
addNode (root,'L',7);
addNode (root,'R',20);
std::cout << sum (root) << '\n';
// Then, finally, the full tree as per above.
addNode (root->left,'L',3);
addNode (root->left->left,'R',4);
addNode (root->left->left->right,'R',6);
addNode (root->right,'R',99);
std::cout << sum (root) << '\n';
return 0;
}
Этот вывод (правильный):
0
10
37
149
Поверните дерево в любом порядке (pre, post, in). Вместо печати node вычислите общее количество.
void sum(Node* root, int& total)
{
if(root == NULL)
{
return;
}
sum(root->left, total);
total = total + root->value;
sum(root->right, total);
}
int main()
{
int total =0;
sum(root,total);
cout << total;
}
Точно так же, как вы просматриваете дерево или показываете каждую node или любую другую операцию по всему дереву: посетите текущий node, перейдите в левое поддерево (рекурсивно) и перейдите в правое поддерево (рекурсивно).
По существу, что-то вроде этого:
int TreeNode::calculateSum() const
{
int sum = this->value;
if (this->left != NULL) sum += this->left ->calculateSum();
if (this->right != NULL) sum += this->right->calculateSum();
return sum;
}
Из-за проверки if
рекурсия будет в конечном итоге снижаться, когда она достигнет узлов без левого или правого дочерних элементов (листовых узлов).
В то время как у STL есть более сложные и сжатые механизмы для этого, он очень быстро ездил на производительность, чтобы научиться использовать ручной цикл над контейнером, например:
Tree::value_type total = Tree::value_type();
for (Tree::const_iterator i = tree.begin(); i != tree.end(); ++i)
total += *i;
Это предполагает, что ваше двоичное дерево является STL:: map, или если вы не предоставите концепцию итератора для своей собственной реализации....
Используйте один из методов Traversal Tree (In-order, Pre-Order, Post-order), чтобы посетить каждый node и сохранить сумму в переменной.
Вы можете найти более подробную информацию об обходе дерева в этом wiki
50 / \ 30 70 / \ / \ 20 40 60 80
возвращает: 350
int Sum(struct node *root)
{
if(root->left == NULL && root->right== NULL)
return root->key;
int lvalue,rvalue;
lvalue=Sum(root->left);
rvalue=Sum(root->right);
return root->key+lvalue+rvalue;
}
public int sum(Node root){
if(root==null){
return 0;
}
if(root.left == null && root.right==null){
return root.key;
}
return sum(root.left)+sum(root.right)+root.key;
}