Untitled

 avatar
unknown
c_cpp
10 months ago
5.4 kB
0
Indexable
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// MurmurOAAT32 hash function
unsigned int MurmurOAAT32(char *key) {
    unsigned int h = 3323198485u;
    for (; *key; ++key) {
        h ^= *key;
        h *= 0x5bd1e995;
        h ^= h >> 15;
    }
    return h;
}

// Function to convert unsigned int to string
void unsigned_int_to_string(unsigned int num, char *str) {
    sprintf(str, "%u", num);
}

// Function to merge and hash two values in the binary tree
unsigned int merge_and_hash(unsigned int a, unsigned int b) {
    unsigned int sum = a + b;
    char buffer[11]; // enough to hold a 32-bit unsigned int
    unsigned_int_to_string(sum, buffer);
    return MurmurOAAT32(buffer);
}

// Definition of tree node
typedef struct Node {
    unsigned int data;
    struct Node *left;
    struct Node *right;
} Node;

// Function to create a new tree node
Node* create_tree_node(unsigned int data) {
    Node *new_node = (Node *)malloc(sizeof(Node));
    new_node->data = data;
    new_node->left = NULL;
    new_node->right = NULL;
    return new_node;
}

// Recursive function to build the Merkle tree and collect hash values
Node* build_merkle_tree(Node** leaves, int n) {
    if (n == 1) {
        return leaves[0];
    }

    int new_n = (n + 1) / 2;
    Node** new_leaves = (Node**)malloc(new_n * sizeof(Node*));

    for (int i = 0; i < new_n; i++) {
        if (2 * i + 1 < n) {
            unsigned int combined_hash = merge_and_hash(leaves[2 * i]->data, leaves[2 * i + 1]->data);
            Node* parent = create_tree_node(combined_hash);
            parent->left = leaves[2 * i];
            parent->right = leaves[2 * i + 1];
            new_leaves[i] = parent;
        } else {
            unsigned int adjusted_hash = merge_and_hash(leaves[2 * i]->data, leaves[2 * i]->data);
            Node* parent = create_tree_node(adjusted_hash);
            parent->left = leaves[2 * i];
            new_leaves[i] = parent;
        }
    }

    Node* root = build_merkle_tree(new_leaves, new_n);
    free(new_leaves);

    return root;
}

// Definition of the correct tree node
typedef struct TreeNode {
    unsigned long long value;
    struct TreeNode *left;
    struct TreeNode *right;
} TreeNode;

// Function to create a new correct tree node
TreeNode* createTreeNode(unsigned long long value) {
    TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));
    newNode->value = value;
    newNode->left = NULL;
    newNode->right = NULL;
    return newNode;
}

// Function to free the correct tree
void freeTree(TreeNode* root) {
    if (root == NULL) return;
    freeTree(root->left);
    freeTree(root->right);
    free(root);
}

// Function to compare two trees and find the wrong data string
void compareTrees(Node* root1, TreeNode* root2, char** data, int* dataIndex, int level) {
    if (root1 == NULL && root2 == NULL) {
        return;
    }

    if (root1 == NULL || root2 == NULL) {
        return;
    }

    if (root1->data != root2->value) {
        printf("%-15u != %llu\n", root1->data, root2->value);
        if (root1->left && root2->left) {
            compareTrees(root1->left, root2->left, data, dataIndex, level + 1);
        }
        if (root1->right && root2->right) {
            compareTrees(root1->right, root2->right, data, dataIndex, level + 1);
        }
    } else {
        printf("%-15u == %llu\n", root1->data, root2->value);
        if (level == 0) { // This is a leaf node
            printf("wrong data %s\n", data[*dataIndex]);
            (*dataIndex)++;
        }
    }
}

int main() {
    int n;
    scanf("%d", &n);

    char **strings = (char **)malloc(n * sizeof(char *));
    Node **leaves = (Node **)malloc(n * sizeof(Node *));
    unsigned int *hashes = (unsigned int *)malloc(n * sizeof(unsigned int));

    for (int i = 0; i < n; i++) {
        strings[i] = (char *)malloc(101 * sizeof(char)); // 100 chars + null terminator
        scanf("%s", strings[i]);
        hashes[i] = MurmurOAAT32(strings[i]);
        leaves[i] = create_tree_node(hashes[i]);
    }

    Node *root = build_merkle_tree(leaves, n);

    int m;
    scanf("%d", &m);

    TreeNode **currentLevel = (TreeNode**)malloc(sizeof(TreeNode*));
    TreeNode **nextLevel;
    int *levelSizes = (int*)malloc(m * sizeof(int));

    int k;
    scanf("%d", &k);
    if (k != 1) {
        fprintf(stderr, "根節點必須只有一個。\n");
        return 1;
    }
    unsigned long long value;
    scanf("%llu", &value);
    TreeNode* root2 = createTreeNode(value);
    currentLevel[0] = root2;
    levelSizes[0] = k;

    for (int i = 1; i < m; ++i) {
        scanf("%d", &k);
        levelSizes[i] = k;
        nextLevel = (TreeNode**)malloc(k * sizeof(TreeNode*));

        for (int j = 0; j < k; ++j) {
            scanf("%llu", &value);
            nextLevel[j] = createTreeNode(value);
        }

        int parentIndex = 0;
        for (int j = 0; j < levelSizes[i - 1]; ++j) {
            if (parentIndex >= k) break;
            currentLevel[j]->left = nextLevel[parentIndex++];
            if (parentIndex >= k) break;
            currentLevel[j]->right = nextLevel[parentIndex++];
        }

        free(currentLevel);
        currentLevel = nextLevel;
    }

    int dataIndex = 0;
    compareTrees(root, root2, strings, &dataIndex, 0);

    freeTree(root2);
    free(currentLevel);
    free(levelSizes);

    free(leaves);
    free(hashes);

    return 0;
}
Editor is loading...
Leave a Comment