📜  默克尔树简介

📅  最后修改于: 2022-05-13 01:57:05.147000             🧑  作者: Mango

默克尔树简介

默克尔树也称为哈希树,是一种用于数据验证和同步的数据结构。
它是一个树数据结构,其中每个非叶节点都是其子节点的哈希。所有的叶子节点都在相同的深度,并且尽可能地向左。
它维护数据完整性并为此使用散列函数。
哈希函数:
因此,在了解 Merkle 树的工作原理之前,我们需要了解哈希函数的工作原理。
散列函数将输入映射到固定输出,该输出称为散列。
每个输入的输出都是唯一的,这可以对数据进行指纹识别。
因此,可以通过它们的哈希轻松识别大量数据。

这是一棵二叉默克尔树,顶部哈希是整棵树的哈希。

  • 树的这种结构允许有效映射大量数据,并且可以轻松识别对数据所做的微小更改。
  • 如果我们想知道数据变化发生在哪里,那么我们可以检查数据是否与根哈希一致,我们不必遍历整个结构,而只需遍历结构的一小部分。
  • 根哈希用作整个数据的指纹。

对于二叉默克尔树

OperationComplexity
SpaceO(n)
SearchingO(logn)
TraversalO(n)
InsertionO(logn)
DeletionO(logn)
SynchronizationO(logn)

应用:

  • Merkle 树在分布式系统中很有用,在这些系统中,相同的数据应该存在于多个地方。
  • 默克尔树可用于检查不一致。
  • Apache Cassandra 使用 Merkle 树来检测整个数据库副本之间的不一致。
  • 它用于比特币和区块链。

此代码由 Amit Das 提供。

C++
// CPP code for the above data structure
#include
using namespace std;
 
/* determines the maximum capacity of
   Hash Tree */
int maxim = 10;        
 
/* determines the number of elements
   present in Hash Tree */
int size = 0;         
 
/* node for storing an item in a Binary Tree */
struct node
{
  int key;
  int value;
  struct node *left;
  struct node *right;
};
 
/* for storing a Binary Tree at each index
   of Hash Tree */
struct bst
{
   
  /* head pointing to the root of Binary Tree */
  struct node *head;
};
 
 
 
struct bst *arr;
 
 
 
void insert_element(struct node *tree,
                          struct node *item);
 
struct node* find(struct node *tree, int key);
 
struct node* remove_element(struct node *tree,
                                     int key);
 
void display_tree(struct node *tree);
 
/* this function creates an index corresponding
   to the every given key */
int hashcode(int key)
{
  return (key % maxim);
}
 
void add(int key, int value)
{
  int index = hashcode(key);
 
  /* extracting Binary Tree at the given index */
  struct node *tree = (struct node*) arr[index].head;
   
  /* creating an item to insert in the hashTree */
  struct node *new_item = (struct node*)
                         malloc(sizeof(struct node));
 
  new_item->key = key;
  new_item->value = value;
  new_item->left = NULL;
  new_item->right = NULL;
 
  if (tree == NULL)
  {
 
    /* absence of Binary Tree at a given
       index of Hash Tree */
    cout << "Inserting " << key << " and " <<
                                 value << endl;
    arr[index].head = new_item;
    size++;
  }
 
  else
  {
 
    /* a Binary Tree is present at given index
       of Hash Tree */
    struct node *temp = find(tree, key);
 
    if (temp == NULL)
    {
 
      /*
       * Key not found in existing Binary Tree
       * Adding the key in existing Binary Tree
       */
 
      cout << "Inserting " << key << "and" <<
                                value << endl;
 
      insert_element(tree, new_item);
      size++;
    }
 
    else
    {
 
      /*
        * Key already present in existing Binary Tree
        * Updating the value of already existing key
       */
      
      temp->value = value;
    }
  }
}
 
/*
 * this function finds the given key in the Binary Tree
 * returns the node containing the key
 * returns NULL in case key is not present
 */
struct node* find(struct node *tree, int key)
{
  if (tree == NULL)
  {
    return NULL;
  }
  if (tree->key == key)
  {
    return tree;
  }
  else if (key < tree->key)
  {
    return find(tree->left, key);
  }
  else
  {
    return find(tree->right, key);
  }
}
 
/* this function inserts the newly created node
   in the existing Binary Tree */
void insert_element(struct node *tree,
                              struct node *item)
{
 
  if (item->key < tree->key)
  {
    if (tree->left == NULL)
    {
      tree->left = item;
      return;
    }
    else
    {
      insert_element(tree->left, item);
      return;
    }
  }
 
  else if (item->key > tree->key)
  {
    if (tree->right == NULL)
    {
      tree->right = item;
      return;
    }
    else
    {
      insert_element(tree->right, item);
      return;
    }
  }
}
 
/* displays the content of hash Tree */
void display()
{
  int i = 0;
  for(i = 0; i < maxim; i++)
  {
    struct node *tree = arr[i].head;
    if (tree == NULL)
    {
      cout << "arr[" << i << "] has no
                             elements" << endl;
    }
    else
    {
      cout << "arr[" << i << "] has
                             elements" << endl;
      display_tree(tree);
    }
  }
}
 
/* displays content of binary tree of
particular index */
void display_tree(struct node *tree)
{
 
  if (tree == NULL)
  {
    return;
  }
 
  cout << tree->key << " and " <<
                          tree->value << "   ";
 
  if (tree->left != NULL)
  {
    display_tree(tree->left);
  }
   
  if (tree->right != NULL)
  {
    display_tree(tree->right);
  }
}
 
/* for initializing the hash Tree */
void init()
{
  int i = 0;
  for(i = 0; i < maxim; i++)
  {
    arr[i].head = NULL;
  }
}
 
/* returns the size of hash Tree */
int size_of_hashTree()
{
  return size;
}
 
/* to del a key from hash Tree */
void del(int key)
{
  int index = hashcode(key);
  struct node *tree = (struct node*)arr[index].head;
  if (tree == NULL)
  {
    cout << key << " Key not present" << endl;
  }
 
  else
  {
    struct node *temp = find(tree, key);
    if (temp == NULL)
    {
      cout << key << " is not present";
    }
    else
    {
      tree = remove_element(tree, key);
      cout << key << " has been removed
                      form the hash tree" << endl;
    }
  }
}
 
struct node* remove_element(struct node *tree,
                                      int key)
{
 
  if (tree == NULL)
  {
    return NULL;
  }
 
  if (key < tree->key)
  {
    tree->left = remove_element(tree->left, key);
    return tree;
  }
 
  else if (key > tree->key)
  {
    tree->right = remove_element(tree->right, key);
    return tree;
  }
 
  else
  {
     
    /* reached the node */
    if (tree->left == NULL  &&  tree->right == NULL)
    {
      size--;
      return tree->left;
    }
 
    else if (tree->left != NULL  &&  tree->right == NULL)
    {
      size--;
      return tree->left;
    }
     
    else if (tree->left == NULL  &&  tree->right != NULL)
    {
      size--;
      return tree->right;
    }
 
    else
    {
      struct node *left_one = tree->left;
      while (left_one->right != NULL)
      {
        left_one = left_one->right;
      }
 
      tree->key = left_one->key;
      tree->value = left_one->value;
      tree->left = remove_element(tree->left,
                                     tree->key);
      return tree;
    }
  }
}
 
// Driver Code
int main()
{
  int choice, key, value, n, c;
  arr = (struct bst*)malloc(maxim *
                             sizeof(struct bst*));
  init();
  do
  {
    cout << "Implementation of Hash Tree" << endl;
    cout << "MENU-: \n1.Insert an item in the Hash Tree"
      "\n2.Remove an item from the Hash Tree"
      "\n3.Check the size of Hash Tree"
      "\n4.Display Hash Tree"
      "\n\n Please enter your choice-:";
     
    cin >> choice;
    switch(choice)
    {
       
      case 1:
        cout << "Inserting element in
                           Hash Tree" << endl;
        cout << "Enter key and value-:    ";
        cin >> key >> value;
        add(key, value);
        break;
         
      case 2:
        cout << "Deleting item from Hash Tree
                   \n Enter the key to delete-:";
        cin >> key;
        del(key);
        break;
         
      case 3:
        n = size_of_hashTree();
        cout << "Size of Hash Tree is-:" << n << endl;
        break;
         
      case 4:
        display();
        break;
         
      default:
        cout << "Wrong Input" << endl;
    }
    cout << "\n Do you want to continue-:
                             (press 1 for yes)     ";
    cin >> c;
 
  }while(c == 1);
  return 0;
}
 
//This code is contributed by Amit Das(amit_das)