Max-Heapify Двоичное Дерево

Это один из вопросов интервью, с которым я недавно столкнулся.

учитывая корневой адрес полного или почти полного двоичного дерева, мы должны написать функцию для преобразования дерева в max-heap.

здесь нет массивов. Дерево уже построено.

, например,

              1   
         /         
        2           5
      /          /    
     3      4    6     7

может иметь любые возможные максимальные кучи как вывод--

              7   
         /         
        3           6
      /          /    
     2     1     4     5

или

              7   
         /         
        4           6
      /          /    
     2     3     1     5

etc...

я написал решение, но используя комбинацию обходов до и после заказа, но это, я думаю, работает в O (n^2). Мой код дает следующий результат.

              7   
         /         
        3           6
      /          /    
     1     2     4     5

Я искал лучшее решение. Кто-нибудь может помочь?

Edit:

Код

void preorder(struct node* root)
{    
    if(root==NULL)return;
    max_heapify(root,NULL);
    preorder(root->left); 
    preorder(root->right);
}
void max_heapify(struct node* root,struct node* prev)
{
    if(root==NULL)
        return ;             
    max_heapify(root->left,root);
    max_heapify(root->right,root);
    if(prev!=NULL && root->data > prev->data)
    {
        swapper(root,prev);
    }     
}
void swapper(struct node* node1, struct node* node2)
{   
    int temp= node1->data;
    node1->data = node2->data;
    node2->data = temp;
}

3 ответов


Я думаю, что это можно сделать в O(NlogN) время с помощью следующей процедуры. http://www.cs.rit.edu / ~rpj/courses/bic2/studios/studio1/studio121.html

предположим, что в дереве есть элемент, левый и правый под-деревья которого являются кучами.

          E
       H1   H2

Это дерево, образованное E, H1 и H2, может быть нагромождено во времени логна, заставляя элемент E плыть вниз к его правильному положению.

следовательно, мы начинаем строить кучу снизу вверх. Goto самое левое под-дерево и преобразовать его в кучу путем тривиального сравнения. Сделайте это для его брата, а также. Затем поднимитесь и преобразуйте его в heap.

Like-wise сделайте это для каждого элемента.

EDIT: как упоминалось в комментариях, сложность на самом деле O(N).


Я не знаю, как, если вы не можете легко получить доступ к родительскому узлу или нет представления массива, если вы можете пересечь дерево, чтобы записать его ref в массив(O(N)), тогда это станет простым.

        1   
     /    \
    2       5
  /   \    / \ 
 3     4  6   7

from the last parent node to the root node(in your case 5,2,1:
  for each node make it compare to their children:
    if children is larger than parent, swap parent and children:
      if swapped: then check the new children's childrens utill no swap

        1   
     /    \
    2       7
  /   \    / \ 
 3     4  6   5    check [7]   5<-->7

        1   
     /    \
    4       7
  /   \    / \ 
 3     2  6   5    check [2]   4<-->2

        7   
     /    \
    4       1
  /   \    / \ 
 3     2  6   5    check [1]   7<-->1

        7   
     /    \
    4       6
  /   \    / \ 
 3     2  1   5    check [1]   6<-->1

вот оно! Сложность должна быть O (N*LogN).


Я думаю, вы можете получить одну работу, просто пересмотрев postOrderTraverse. Это O (n)

void Heapify_Min(TreeNode* node)
{
  if(! = node) return;
   Heapify_Min(node->left);
   Heapify_Min(node->right);
   TreeNode* largest = node;
   if(node->left && node->left->val > node->val)
      largest = node->left;
   if(node->right && node->right->val > node->val)
      largest = node->right;

  if(largest != node)
  {
    swap(node, largest)
  }
}

void swap(TreeNode* n1, TreeNode* n2)
{
    TreeNode* temp = n1->left;
    n1->left = n2->left;
    n2->left =temp;

    temp = n1->right;
    n1->right = n2->right;
    n2->right = temp;
}

}