Keseimbangan adalah properti yang benar-benar halus; Anda pikir Anda tahu apa itu, tetapi sangat mudah untuk salah. Secara khusus, bahkan jawaban (baik) Eric Lippert tidak aktif. Itu karena pengertian ketinggian saja tidak cukup. Anda harus memiliki konsep tinggi minimum dan maksimum sebuah pohon (di mana tinggi minimum adalah jumlah langkah paling sedikit dari akar ke daun, dan maksimumnya adalah ... yah, Anda mengerti gambarannya). Mengingat itu, kita dapat mendefinisikan keseimbangan menjadi:
Pohon yang tinggi maksimum cabang mana pun tidak lebih dari satu lebih dari tinggi minimum cabang mana pun.
(Ini sebenarnya menyiratkan bahwa cabang-cabang itu sendiri seimbang; Anda dapat memilih cabang yang sama untuk maksimum dan minimum.)
Yang perlu Anda lakukan untuk memverifikasi properti ini hanyalah pelacakan traversal pohon sederhana dari kedalaman saat ini. Pertama kali Anda mundur, itu memberi Anda kedalaman dasar. Setiap kali setelah itu ketika Anda mundur, Anda membandingkan kedalaman baru dengan baseline
- jika sama dengan baseline, maka Anda lanjutkan saja
- jika lebih dari satu perbedaan, pohon itu tidak seimbang
- jika salah satu, maka Anda sekarang mengetahui kisaran keseimbangannya, dan semua kedalaman berikutnya (saat Anda akan mundur) harus berupa nilai pertama atau kedua.
Dalam kode:
class Tree {
Tree left, right;
static interface Observer {
public void before();
public void after();
public boolean end();
}
static boolean traverse(Tree t, Observer o) {
if (t == null) {
return o.end();
} else {
o.before();
try {
if (traverse(left, o))
return traverse(right, o);
return false;
} finally {
o.after();
}
}
}
boolean balanced() {
final Integer[] heights = new Integer[2];
return traverse(this, new Observer() {
int h;
public void before() { h++; }
public void after() { h--; }
public boolean end() {
if (heights[0] == null) {
heights[0] = h;
} else if (Math.abs(heights[0] - h) > 1) {
return false;
} else if (heights[0] != h) {
if (heights[1] == null) {
heights[1] = h;
} else if (heights[1] != h) {
return false;
}
}
return true;
}
});
}
}
Saya kira Anda dapat melakukan ini tanpa menggunakan pola Observer, tetapi saya merasa lebih mudah untuk bernalar seperti ini.
[EDIT]: Mengapa Anda tidak bisa hanya mengukur tinggi setiap sisi. Pertimbangkan pohon ini:
/\
/ \
/ \
/ \_____
/\ / \_
/ \ / / \
/\ C /\ / \
/ \ / \ /\ /\
A B D E F G H J
OK, berantakan sedikit, tapi setiap sisi akar yang seimbang: C
adalah kedalaman 2, A
, B
, D
, E
yang kedalaman 3, dan F
, G
, H
, J
yang mendalam 4. Ketinggian cabang kiri adalah 2 (ingat ketinggian berkurang ketika Anda melintasi cabang), tinggi cabang kanan adalah 3. Namun pohon secara keseluruhan tidak seimbang karena ada perbedaan ketinggian 2 antara C
dan F
. Anda memerlukan spesifikasi minimax (meskipun algoritme sebenarnya bisa kurang rumit karena hanya boleh ada dua ketinggian yang diizinkan).