Ağaçlar: terminoloji, ikili ağaçlar ve gezinmeler
Kök, yaprak, derinlik, yükseklik gibi terimler, genel ve ikili ağaçlar, preorder/inorder/postorder/level-order izleri ve ifade ağaçları.
Listeler, yığınlar ve kuyruklar (SEN2211) doğrusal yapılardı: her elemanın en fazla bir “sonraki”si vardı. Ağaç (tree) hiyerarşik bir yapı: bir elemanın birden çok “çocuğu” olabilir. Dosya sistemleri, HTML belgesi, derleyicinin ifade ağaçları, veritabanı indeksleri hep ağaç. Bu dersin sonraki altı haftası (BST, AVL, red-black, heap) bu sayfadaki terimlerin üzerine kurulu.
Sınavda bu haftadan gelenler: terim sorusu (verilen ağaçta derinlik, yükseklik, yaprak sayısı), gezinme izi (preorder, inorder, postorder, level-order), ifade ağacı (postfix’ten kur, değerlendir) ve iki gezinmeden ağaç kur.
Terminoloji
Bu genel ağacı (general tree) örnek alalım:
A
/ | \
B C D
/ \ / \
E F G H
|
I
| Terim | Anlamı | Örnekte |
|---|---|---|
| kök (root) | ebeveyni olmayan tek düğüm | A |
| ebeveyn (parent) / çocuk (child) | doğrudan bağlı üst / alt düğüm | G’nin ebeveyni D, çocuğu I |
| kardeş (sibling) | aynı ebeveynin çocukları | B, C, D |
| yaprak (leaf) | çocuğu olmayan düğüm | E, F, C, I, H |
| iç düğüm (internal node) | en az bir çocuğu olan | A, B, D, G |
| derece (degree) | çocuk sayısı | A: 3, G: 1 |
| ata (ancestor) / torun (descendant) | kökten düğüme yol üstündekiler / alt ağaçtakiler | I’nın ataları G, D, A |
| derinlik (depth) | kökten düğüme kenar sayısı | I: 3 |
| yükseklik (height) | düğümden en derin yaprağa kenar sayısı | D: 2, ağaç: 3 |
| alt ağaç (subtree) | bir düğüm ve tüm torunları | D, G, H, I |
İki temel gerçek: n düğümlü ağaçta n - 1 kenar vardır (kök hariç her düğümün tek bir ebeveyn kenarı var). Kökten her düğüme tek bir yol vardır.
TUZAK · derinlik ve yükseklik ters yönlerde ölçülür. Derinlik yukarıdan aşağı (kökün derinliği 0), yükseklik aşağıdan yukarı (yaprağın yüksekliği 0). Bazı kaynaklar düğüm sayar, kenar değil. Bu derste ve Weiss’te kenar sayılır; boş ağacın yüksekliği -1.
Genel ağacı saklamak: first-child, next-sibling
Bir düğümün kaç çocuğu olacağı belli değilse her düğüme sabit sayıda referans koyamazsın. Çözüm: her düğümde iki referans tut, ilk çocuk ve sağdaki kardeş.
class TreeNode {
String element;
TreeNode firstChild; // en soldaki çocuk
TreeNode nextSibling; // sağındaki kardeş
}
Yukarıdaki ağaçta A.firstChild = B, B.nextSibling = C, C.nextSibling = D, D.firstChild = G. Bu gösterim aslında her genel ağacı bir ikili ağaca çevirir.
Genel ağaçta preorder (önce düğüm, sonra çocuklar soldan sağa) ve postorder (önce çocuklar, sonra düğüm) tanımlıdır:
preorder : A B E F C D G I H
postorder: E F B C I G H D A
Dosya sistemi örneği: dizin listesini girintili basmak preorder, bir dizinin toplam boyutunu hesaplamak postorder (önce alt dizinlerin boyutu lazım).
İkili ağaçlar
İkili ağaçta (binary tree) her düğümün en fazla iki çocuğu var ve çocuklar sol ve sağ diye ayrılır. Sadece sağ çocuğu olan bir düğüm, sadece sol çocuğu olandan farklı bir ağaçtır.
class Node {
int element;
Node left, right;
Node(int e) { element = e; }
}
Özel ikili ağaç türleri
| Tür | Tanım |
|---|---|
| full (proper) | her düğümün 0 ya da 2 çocuğu var |
| perfect | full ve tüm yapraklar aynı derinlikte |
| complete | son seviye hariç her seviye dolu, son seviye soldan sağa dolu |
Complete ağaç 7. haftada heap’in şekli olacak. Önemli sayılar:
En kötü durumda (her düğümün tek çocuğu) yükseklik olur ve ağaç bağlı listeye döner. Ağaç işlemlerinin süresi yüksekliğe bağlı olduğu için ağacı alçak tutmak sonraki haftaların ana konusu.
Gezinmeler (traversals)
Bu ikili ağaç üzerinde dört gezinmeyi izleyelim:
A
/ \
B C
/ \ \
D E F
/ / \
G H I
| Gezinme | Kural | Sonuç |
|---|---|---|
| preorder | kök, sol, sağ | A B D E G C F H I |
| inorder | sol, kök, sağ | D B G E A C H F I |
| postorder | sol, sağ, kök | D G E B H I F C A |
| level-order | seviye seviye, soldan sağa | A B C D E F G H I |
Kodları üç satır, sadece “ziyaret” satırının yeri değişiyor:
static void preorder(Node n) {
if (n == null) return;
visit(n); // önce
preorder(n.left);
preorder(n.right);
}
static void inorder(Node n) {
if (n == null) return;
inorder(n.left);
visit(n); // ortada
inorder(n.right);
}
static void postorder(Node n) {
if (n == null) return;
postorder(n.left);
postorder(n.right);
visit(n); // sonda
}
Level-order özyinelemeli değil, kuyruk (queue) ile yapılır: kökü kuyruğa koy, her adımda baştan çıkar, ziyaret et, çocuklarını (önce sol) sona ekle.
static void levelOrder(Node root) {
Queue<Node> q = new ArrayDeque<>();
if (root != null) q.add(root);
while (!q.isEmpty()) {
Node n = q.poll();
visit(n);
if (n.left != null) q.add(n.left);
if (n.right != null) q.add(n.right);
}
}
Dördü de her düğümü bir kez ziyaret eder: süre. Özyinelemeli olanlar yığın belleği, level-order en geniş seviye kadar kuyruk belleği kullanır.
İPUCU · elle gezinme hilesi. Ağacın çevresinde soldan başlayıp saat yönünün tersine dolaşan bir çizgi düşün. Her düğümün soluna değdiğinde yazarsan preorder, altına değdiğinde inorder, sağına değdiğinde postorder çıkar.
İfade ağaçları
İfade ağacında (expression tree) yapraklar işlenen (sayı ya da değişken), iç düğümler operatördür. (3 + 4) * (5 - 2):
*
/ \
+ -
/ \ / \
3 4 5 2
- postorder → postfix:
3 4 + 5 2 - * - preorder → prefix:
* + 3 4 - 5 2 - inorder + parantez → infix:
((3 + 4) * (5 - 2)) - değer: postorder ile değerlendir: önce iki alt ağaç, sonra operatör → 7 * 3 = 21
Postfix’ten ağaç kurmak
SEN2211’deki postfix değerlendirme algoritmasının aynısı, sayılar yerine düğüm itiyorsun:
- İşlenen gelirse tek düğümlü ağaç yap, yığına it.
- Operatör gelirse yığından önce sağ, sonra sol alt ağacı çek, operatör düğümü yap, it.
- Sonunda yığında tek ağaç kalır.
6 2 / 1 + 4 * için yığının durumu:
6 -> [6]
2 -> [6, 2]
/ -> [(6/2)]
1 -> [(6/2), 1]
+ -> [((6/2)+1)]
4 -> [((6/2)+1), 4]
* -> [(((6/2)+1)*4)] değer 16
İki gezinmeden ağaç kurmak
Preorder (ya da postorder) kökü söyler, inorder solu sağdan ayırır. Algoritma:
- Preorder’ın ilk elemanı kök.
- Kökü inorder’da bul. Solundakiler sol alt ağaç, sağındakiler sağ alt ağaç.
- Preorder’da kökten sonraki aynı sayıda eleman sol alt ağacın preorder’ı, kalanı sağın.
- Her alt ağaç için tekrarla.
Örnek: preorder A B D E C F, inorder D B E A F C.
kök A inorder: [D B E] A [F C]
sol: pre B D E, in D B E -> kök B, sol D, sağ E
sağ: pre C F, in F C -> kök C, sol F
A
/ \
B C
/ \ /
D E F
postorder: D E B F C A
Postorder + inorder ile de aynı şey yapılır; bu sefer kök postorder’ın son elemanı.
Sık yapılan hatalar
| Yanlış düşünce | Doğrusu |
|---|---|
| Yaprağın yüksekliği 1 | Kenar sayılır: 0. Boş ağaç -1 |
| Kökün derinliği 1 | 0 |
| Level-order özyinelemeyle yazılır | Kuyrukla yazılır; özyineleme DFS sırası verir |
| Postfix’ten ağaç kurarken ilk çekilen sol çocuk | İlk çekilen SAĞ çocuk (8 2 - → 8 - 2) |
| Inorder her ifade ağacının doğru infix’ini verir | Parantez eklemezsen öncelik kaybolur |
| Preorder + postorder ağacı belirler | Tek çocuklu düğümlerde belirlemez; inorder şart |
| Sadece sağ çocuklu düğüm, sadece sol çocukluyla aynı | İkili ağaçta farklı ağaçlardır |
| n düğümlü ağaçta n kenar | n - 1 kenar |
Kendini test et
Sınavdaki gibi İngilizce sorular. Önce kâğıt kalemle çöz, sonra cevabı aç.
For the general tree below, give the depth of T, the height of the tree, the degree of N and the number of leaves.
K
/ | \
L M N
/ \ |
O P Q
/ | \
S T UCevabı göster
Derinlik kökten düğüme kenar sayısı: K → N → Q → T, 3 kenar.
Ağacın yüksekliği en derin yaprağın derinliği: S, T, U derinlik 3'te, yükseklik 3.
Derece (degree) çocuk sayısı: N'nin tek çocuğu Q var, derece 1.
Yapraklar (çocuksuz): O, P, M, S, T, U → 6. İç düğümler K, L, N, Q → 4.
Give the preorder and inorder traversals of the binary tree below.
1
/ \
2 3
/ / \
4 5 6
\ /
7 8Cevabı göster
Preorder = kök, sol, sağ. 1 → sol alt ağaç (2, 4, 7) → sağ alt ağaç (3, 5, 6, 8).
2'nin sağı yok, 4'ün solu yok sağı 7. Bu yüzden 1 2 4 7, sonra 3 5 6 8.
Inorder = sol, kök, sağ. En sola in: 4'ün solu boş, 4 yaz, sonra sağı 7. Sonra 2, sonra kök 1.
Sağ tarafta 5, 3, sonra 6'nın solu 8, sonra 6: 4 7 2 1 5 3 8 6.
For the same tree as the previous question, give the postorder and level-order traversals.
1
/ \
2 3
/ / \
4 5 6
\ /
7 8Cevabı göster
Postorder = sol, sağ, kök. Kök her zaman en sonda. 4'ün alt ağacı: 7 4. Sonra 2. Sağ taraf: 5, sonra 6'nın alt ağacı 8 6, sonra 3. En son 1.
Level-order kuyrukla, seviye seviye soldan sağa: seviye 0: 1; seviye 1: 2 3; seviye 2: 4 5 6; seviye 3: 7 8.
Build the expression tree for the postfix expression 8 2 3 * - 4 2 / +. What is its prefix (preorder) form and its value?
Cevabı göster
Yığın kullan: sayıyı tek düğüm olarak it; operatör gelince iki düğüm çek (önce sağ, sonra sol), operatör düğümü yap, it.
8, 2, 3 itilir. *: (2*3). -: (8 - (2*3)). 4, 2 itilir. /: (4/2). +: kök.
Ağaç: kök +, solu -(8, *(2,3)), sağı /(4,2). Preorder: + - 8 * 2 3 / 4 2.
Değer: 8 - 6 = 2, 4 / 2 = 2, 2 + 2 = 4.
A binary tree has preorder P Q S T R U V and inorder S Q T P U R V. What is its postorder traversal?
Cevabı göster
Preorder'ın ilki kök: P. Inorder'da P'nin solu (S Q T) sol alt ağaç, sağı (U R V) sağ alt ağaç.
Sol alt ağacın preorder'ı Q S T: kök Q, inorder S Q T → solu S, sağı T.
Sağ alt ağacın preorder'ı R U V: kök R, inorder U R V → solu U, sağı V.
Postorder: sol alt ağaç (S T Q), sağ alt ağaç (U V R), kök P → S T Q U V R P.
What is the maximum number of nodes in a binary tree of height 4? What is the minimum possible height of a binary tree with 100 nodes?
Cevabı göster
Derinlik d'de en fazla düğüm var. Yükseklik h için toplam . h = 4 → 31.
n düğümlü ikili ağacın yüksekliği en az . , yani 6.
Kontrol: yükseklik 5 olsaydı en fazla 63 düğüm sığardı, 100'e yetmez.
How many null child references (null links) does the 8-node binary tree in question 2 contain? State the general rule.
Cevabı göster
Her düğümde 2 referans var: toplam 2n. Kök hariç her düğümü tam olarak bir referans gösterir: n - 1 dolu referans.
Null olanlar: 2n - (n - 1) = n + 1. n = 8 için 9.
Elle sayım: 4'ün solu, 7'nin iki çocuğu, 2'nin sağı, 5'in iki çocuğu, 8'in iki çocuğu, 6'nın sağı → 9.
A full binary tree (every node has 0 or 2 children) has 12 leaves. How many internal nodes and how many nodes in total does it have?
Cevabı göster
Full ikili ağaçta yaprak sayısı L ile iç düğüm sayısı I arasında L = I + 1 bağıntısı vardır.
Neden: tek düğümle başla (L=1, I=0). Bir yaprağı iki çocuklu yapmak I'yı 1, L'yi 1 artırır (bir yaprak gitti, iki geldi). Fark hep 1 kalır.
L = 12 → I = 11, toplam 23.
Which traversal of an expression tree produces the postfix expression? Which one produces the fully parenthesized infix expression?
Cevabı göster
Postfix'te operatör iki işleneninden sonra gelir: sol, sağ, kök = postorder.
Prefix'te önce gelir: preorder.
Infix'te ortada: inorder. Ama sade inorder önceliği kaybeder, bu yüzden her iç düğümde alt ağacı parantez içine almak gerekir: ((3 + 4) * (5 - 2)).
Write a recursive Java method int countLeaves(Node n) that returns the number of leaves in a binary tree (Node has fields left and right).
Cevabı göster
Üç durum: boş ağaç 0 yaprak, çocuksuz düğüm 1 yaprak, diğerlerinde iki alt ağacın toplamı.
static int countLeaves(Node n) {
if (n == null) return 0;
if (n.left == null && n.right == null) return 1;
return countLeaves(n.left) + countLeaves(n.right);
}Her düğüm bir kez ziyaret edilir: O(n). Soru 2'deki ağaçta sonuç 3 (7, 5, 8).Write a recursive Java method int height(Node n) for a binary tree, using the convention height(null) = -1 so that a single node has height 0.
Cevabı göster
Bir düğümün yüksekliği, alt ağaçlarından yüksek olanın yüksekliği artı 1. Boş ağaç -1 olunca yaprak 1 + max(-1, -1) = 0 olur.
static int height(Node n) {
if (n == null) return -1;
return 1 + Math.max(height(n.left), height(n.right));
}Soru 2'deki ağaçta sonuç 3 (1 → 2 → 4 → 7). O(n).Can the preorder and postorder traversals together always determine a binary tree uniquely? Justify with an example.
Cevabı göster
İki ağaç düşün: (1) A'nın sadece sol çocuğu B, (2) A'nın sadece sağ çocuğu B.
İkisinde de preorder A B, postorder B A. Ama inorder farklı: (1) B A, (2) A B.
Preorder ya da postorder kökü verir, inorder ise solu sağdan ayırır. Tek çocuklu düğüm varsa ağacı kurmak için inorder şart.
Doğrulama: Tüm gezinme sıraları, derinlik/yükseklik/derece değerleri, ifade ağacı sonuçları, preorder+inorder'dan kurulan ağaçların postorder'ı, null link sayıları ve L = I + 1 özelliği Java ile hesaplandı (verify/SEN2212/W02.java, java W02.java).