I've written a pretty basic algorithm to convert a string to a binary hash tree of its characters, where each character represents a leaf node. The hash tree itself is being stored in a vector.
If the number of leaf nodes is not a power of 2, I'm padding the number leaf nodes with empty substrings until the number of leaves is a power of 2.
I know there's likely a much better way to achieve this, but I'm having trouble picturing what that would look like. What are some alternate, potentially more performant approaches I may have overlooked?
Please disregard the chosen hash function (DJB2()).
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <math.h>
#include "../code/hash.h"
using namespace std;
struct Node {
unsigned int hash;
};
bool IsPowerOfTwo(int c) {
int a = ceil(log2(c));
int b = floor(log2(c));
return a == b;
}
int NextPowerOfTwo(int c) {
int a = ceil(log2(c));
return pow(2, a);
}
int main(int argc, char* argv[])
{
string str = "abc34";
vector<shared_ptr<Node>> nodes;
int leaves = IsPowerOfTwo(str.length()) ? str.length() : NextPowerOfTwo(str.length());
int total_nodes = 2 * leaves - 1;
int non_leaves = total_nodes - leaves;
// Add root + internal nodes to vector
for(int i = 0; i < non_leaves; i++) {
shared_ptr<Node> new_node(new Node);
nodes.push_back(new_node);
}
// Generate the hash for leaf nodes + add to vector
for (int i = 0; i < leaves; i++) {
shared_ptr<Node> new_node(new Node);
string substr = (i >= str.length()) ? "" : string (1, str[i]);
new_node->hash = DJB2(substr);
nodes.push_back(new_node);
}
// Generate the hash for internal and root nodes
for (int i = non_leaves - 1; i >= 0; i--) {
int left_child_index = 2 * i + 1;
int right_child_index = 2 * i + 2;
string left_child_hash = to_string(nodes[left_child_index]->hash);
string right_child_hash = to_string(nodes[right_child_index]->hash);
string child_hashes = left_child_hash + right_child_hash;
nodes[i]->hash = DJB2(child_hashes);
}
// Output index of node in vector/tree and its corresponding hash value
for (int i = 0; i < nodes.size(); i++) {
cout << i << " : " << nodes[i]->hash << endl;
}
return 0;
}