SEN2212 · 2. hafta · Introduction to different tree structures.

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ı.

treerootleafparentchildsiblingdepthheightdegreesubtreebinary treefull binary treecomplete binary treepreorderinorderpostorderlevel-orderexpression treefirst-child next-sibling

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
TerimAnlamıÖrnekte
kök (root)ebeveyni olmayan tek düğümA
ebeveyn (parent) / çocuk (child)doğrudan bağlı üst / alt düğümG’nin ebeveyni D, çocuğu I
kardeş (sibling)aynı ebeveynin çocuklarıB, C, D
yaprak (leaf)çocuğu olmayan düğümE, F, C, I, H
iç düğüm (internal node)en az bir çocuğu olanA, 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çtakilerI’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ürTanım
full (proper)her düğümün 0 ya da 2 çocuğu var
perfectfull ve tüm yapraklar aynı derinlikte
completeson seviye hariç her seviye dolu, son seviye soldan sağa dolu

Complete ağaç 7. haftada heap’in şekli olacak. Önemli sayılar:

yu¨kseklik h ic¸in en c¸ok 2h+1−1 du¨g˘u¨m,n du¨g˘u¨m ic¸in h≥⌊log⁡2n⌋\text{yükseklik } h \text{ için en çok } 2^{h+1} - 1 \text{ düğüm}, \qquad n \text{ düğüm için } h \ge \lfloor \log_2 n \rfloor

En kötü durumda (her düğümün tek çocuğu) yükseklik n−1n - 1 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
GezinmeKuralSonuç
preorderkök, sol, sağA B D E G C F H I
inordersol, kök, sağD B G E A C H F I
postordersol, sağ, kökD G E B H I F C A
level-orderseviye seviye, soldan sağaA 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: O(n)O(n) süre. Özyinelemeli olanlar O(h)O(h) 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:

  1. İşlenen gelirse tek düğümlü ağaç yap, yığına it.
  2. Operatör gelirse yığından önce sağ, sonra sol alt ağacı çek, operatör düğümü yap, it.
  3. 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:

  1. Preorder’ın ilk elemanı kök.
  2. Kökü inorder’da bul. Solundakiler sol alt ağaç, sağındakiler sağ alt ağaç.
  3. Preorder’da kökten sonraki aynı sayıda eleman sol alt ağacın preorder’ı, kalanı sağın.
  4. 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üşünceDoğrusu
Yaprağın yüksekliği 1Kenar sayılır: 0. Boş ağaç -1
Kökün derinliği 10
Level-order özyinelemeyle yazılırKuyrukla 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 verirParantez eklemezsen öncelik kaybolur
Preorder + postorder ağacı belirlerTek ç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 kenarn - 1 kenar

Kendini test et

Sınavdaki gibi İngilizce sorular. Önce kâğıt kalemle çöz, sonra cevabı aç.

Soru 1kolay

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  U
Cevabı göster
depth(T) = 3, height = 3, degree(N) = 1, 6 leaves

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.

Soru 2kolay

Give the preorder and inorder traversals of the binary tree below.

        1
       / \
      2   3
     /   / \
    4   5   6
     \     /
      7   8
Cevabı göster
Preorder: 1 2 4 7 3 5 6 8; Inorder: 4 7 2 1 5 3 8 6

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.

Soru 3kolay

For the same tree as the previous question, give the postorder and level-order traversals.

        1
       / \
      2   3
     /   / \
    4   5   6
     \     /
      7   8
Cevabı göster
Postorder: 7 4 2 5 8 6 3 1; Level-order: 1 2 3 4 5 6 7 8

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.

Soru 4orta

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
+ - 8 * 2 3 / 4 2, value 4

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.

Soru 5orta

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
S T Q U V R P

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.

Soru 6orta

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
31; 6

Derinlik d'de en fazla 2d2^d düğüm var. Yükseklik h için toplam 20+...+2h=2h+1−12^0 + ... + 2^h = 2^{h+1} - 1. h = 4 → 31.
n düğümlü ikili ağacın yüksekliği en az ⌊log⁡2n⌋\lfloor \log_2 n \rfloor. 26=64≤100<128=272^6 = 64 \le 100 < 128 = 2^7, yani 6.
Kontrol: yükseklik 5 olsaydı en fazla 63 düğüm sığardı, 100'e yetmez.

Soru 7orta

How many null child references (null links) does the 8-node binary tree in question 2 contain? State the general rule.

Cevabı göster
9; a binary tree with n nodes has n + 1 null links

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.

Soru 8orta

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
11 internal, 23 total

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.

Soru 9kolay

Which traversal of an expression tree produces the postfix expression? Which one produces the fully parenthesized infix expression?

Cevabı göster
Postorder; inorder (with parentheses added around each operator subtree)

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)).

Soru 10orta

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
null → 0; no children → 1; else countLeaves(left) + countLeaves(right)

Üç 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).

Soru 11orta

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
null → -1; else 1 + max(height(left), height(right))

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).

Soru 12zor

Can the preorder and postorder traversals together always determine a binary tree uniquely? Justify with an example.

Cevabı göster
No; A with only a left child B and A with only a right child B both give preorder A B and postorder B A

İ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).

Deftere not kartı

Kök: ebeveyni yok. Yaprak: çocuğu yok. Kardeş: aynı ebeveyn. derinlik(x) = kökten x'e kenar sayısı. yükseklik(x) = x'ten en derin yaprağa kenar sayısı. Ağacın yüksekliği = kökün yüksekliği. Konvansiyon: height(null) = -1, yaprak = 0. Derece = çocuk sayısı. n düğüm → n-1 kenar. İkili ağaç, yükseklik h: en çok 2^(h+1) - 1 düğüm, en çok 2^h yaprak. n düğüm: en az floor(log2 n) yükseklik, en çok n-1. null link sayısı n+1. Full (0 ya da 2 çocuk): yaprak = iç düğüm + 1. Complete: son seviye hariç dolu, son seviye soldan dolu (heap şekli). PRE: kök-sol-sağ IN: sol-kök-sağ POST: sol-sağ-kök LEVEL: kuyruk. İfade ağacı: post → postfix, pre → prefix, in + parantez → infix. Postfix'ten ağaç: yığın; operatörde önce SAĞ, sonra SOL çekilir. Ağaç kurmak için inorder + (pre ya da post) gerekir; pre + post yetmez.