これは、私が最近遭遇したインタビューの質問の1つです。
完全な、またはほぼ完全なバイナリツリーのルートアドレスを指定すると、ツリーを最大ヒープに変換する関数を作成する必要があります。
ここに含まれる配列はありません。ツリーはすでに構築されています。
たとえば、
1
/ \
2 5
/ \ / \
3 4 6 7
出力として可能な最大ヒープのいずれかを持つことができます-
7
/ \
3 6
/ \ / \
2 1 4 5
または
7
/ \
4 6
/ \ / \
2 3 1 5
等...
私はソリューションを作成しましたが、前後のトラバーサルの組み合わせを使用していますが、O(n ^ 2)で実行されると思います。私のコードは次の出力を出します。
7
/ \
3 6
/ \ / \
1 2 4 5
より良い解決策を探していました。誰か助けてもらえますか?
編集:
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;
}
これはO(NlogN)時間で次の手順で実行できると思います。 http://www.cs.rit.edu/~rpj/courses/bic2/studios /studio1/studio121.html
左側と右側の両方のサブツリーがヒープである要素がツリーにあると想定します。
E
H1 H2
E、H1、およびH2で構成されるこのツリーは、要素Eを正しい位置まで泳がせることにより、logN時間でヒープ化できます。
したがって、ヒープのボトムアップを構築し始めます。左端のサブツリーに移動し、簡単な比較によってヒープに変換します。これも兄弟のために行います。次に、上に移動してヒープに変換します。
同様に、すべての要素に対してこれを行います。
編集:コメントで述べたように、複雑さは実際にはO(N)です。
親ノードに簡単にアクセスできないか、配列表現がない場合、ツリーを走査してそれをref(array(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を修正するだけで1つの作業を取得できると思います。これは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;
}
}