แนวคิด
Complete Binary Tree: ทุกระดับเต็มยกเว้นระดับสุดท้าย และโหนดชิดซ้ายสุด Perfect Binary Tree เป็น Complete เสมอ แต่กลับไม่จริง
โจทย์: หาขนาดของ Complete Subtree ใหญ่ที่สุดใน Binary Tree ที่กำหนด
วิธีการแก้ปัญหา
Traverse แบบ Bottom-up ส่งข้อมูลจากลูกขึ้นมาหา parent:
- bool isPerfect: subtree นี้เป็น Perfect หรือไม่
- bool isComplete: subtree นี้เป็น Complete หรือไม่
- int size: ขนาด subtree
- node* rootTree: รากของ Complete subtree ใหญ่ที่สุดที่พบ
3 กรณีที่ parent เป็น Complete:
- Left Perfect + Right Complete + ความสูงเท่ากัน → Complete (Perfect ถ้า Right ก็ Perfect)
- Left Complete + Right Perfect + ความสูง Left = Right + 1 → Complete (แต่ไม่ Perfect)
- อื่นๆ → ไม่ใช่ Complete, ส่ง size ใหญ่สุดของลูกขึ้นไป
ตัวอย่างโค้ด C++
#include <bits/stdc++.h>
using namespace std;
struct node1 { int data; struct node1* left; struct node1* right; };
struct returnType {
bool isPerfect;
bool isComplete;
int size1;
node1* rootTree;
};
int getHeight(int size1){ return ceil(log2(size1 + 1)); }
returnType findCompleteBinaryTree(struct node1* root){
returnType rt1;
if (root == NULL) { rt1.isPerfect = rt1.isComplete = true; rt1.size1 = 0; rt1.rootTree = NULL; return rt1; }
returnType lv1 = findCompleteBinaryTree(root->left);
returnType rv1 = findCompleteBinaryTree(root->right);
// CASE A
if (lv1.isPerfect && rv1.isComplete && getHeight(lv1.size1) == getHeight(rv1.size1)) {
rt1.isComplete = true;
rt1.isPerfect = rv1.isPerfect;
rt1.size1 = lv1.size1 + rv1.size1 + 1;
rt1.rootTree = root;
return rt1;
}
// CASE B
if (lv1.isComplete && rv1.isPerfect && getHeight(lv1.size1) == getHeight(rv1.size1) + 1) {
rt1.isComplete = true;
rt1.isPerfect = false;
rt1.size1 = lv1.size1 + rv1.size1 + 1;
rt1.rootTree = root;
return rt1;
}
// CASE C
rt1.isPerfect = rt1.isComplete = false;
rt1.size1 = max(lv1.size1, rv1.size1);
rt1.rootTree = (lv1.size1 > rv1.size1 ? lv1.rootTree : rv1.rootTree);
return rt1;
}
void inorderPrint(node1* root){ ... }
int main(){
struct node1* root = newNode(50);
root->left = newNode(30);
root->right = newNode(60);
root->left->left = newNode(5);
root->left->right = newNode(20);
root->right->left = newNode(45);
root->right->right = newNode(70);
root->right->left->left = newNode(10);
struct returnType ans1 = findCompleteBinaryTree(root);
cout << "Size : " << ans1.size1 << endl;
cout << "Inorder Traversal : ";
inorderPrint(ans1.rootTree);
return 0;
}
ผลลัพธ์
Size : 4 Inorder Traversal : 10 45 60 70