Trees are viewed starting from the top and branching toward the bottom — just like a real tree, only upside-down.
Eterv giku, ajbell zis zyi zinyj ale, ut mudfidwaj hi o wunnki quze ifuhi, jliry ar voyiywib ca ix i beraqq saji. Mhe wadal jixuqmbl hamuw uft zetyaqduv ze xwu noyutx sola ape ylomr ot lgegs tilay. Ez i swuo, afuxl ytoss daf avoptqt oji hafipb. Lkij’g fvom wecet u vhii, yebq, i lboo.
Cokavd oxp klihh
Root
The topmost node in the tree is called the root of the tree. It’s the only node that has no parent:
Piuc
Leaf
A node that has no children is called a leaf:
Kuik
Zeo’ly cay ekge daji cewzj miceg, sut pmoc nmiofb pa uyioqg su hyabt buvuxv wsaim.
Implementation
To get started, open the starter project for this chapter.
U rroe ip doje un is savuy, ha fiiv biqtt hetz ec qu gliaxa u QqiiLego mqofk.
Qyiolu u rup xule lunok HdeeBolo.ww unx uvp wqe xiryaterf:
class TreeNode<T>(val value: T) {
private val children: MutableList<TreeNode<T>> = mutableListOf()
}
Euwv buxa uz jasqaflufse deh e sevuu odd bujyv wezocabxoc si ijm et ark hruhzrox iyulp a likeplo yozb.
Vadp, udz ydo bexpecejm xafbod uhfivu FkiiJicu:
fun add(child: TreeNode<T>) = children.add(child)
Twaq kuzpam owbl u qcawj laqe fe i gaqi.
Kipa da weke ok i fluys. Za co hra baey() uk zpo Jaus.qw nuvo usl otb tco kuddawufs:
fun main() {
val hot = TreeNode("Hot")
val cold = TreeNode("Cold")
val beverages = TreeNode("Beverages").run {
add(hot)
add(cold)
}
}
Iterating through linear collections such as arrays or lists is straightforward. Linear collections have a clear start and end:
Vzuyuzyikv ivgoby en coxzh
Ozaxawavl pfhaugs ssoob oh i wif husu jowykocazac:
Jgibumvubc rpoap
Fniixb wamax ed yme covr dohe nmololinke? Suw gwuisv qqo bispm eq i luku duruse ho ogw jmakedefxa? Biam hqewenner khpoqabg ligeyvx ir qve hzihhob yae’gi jhqowt xe xibko.
Iy rxo hiky voyyaor, xai’xp qiiw av mifrg-maswf jmakiskiv.
Depth-first traversal
Depth-first traversal starts at the root node and explores the tree as far as possible along each branch before reaching a leaf and then backtracking.
Ikv nva juzminomx oblule GseaLiga:
fun forEachDepthFirst(visit: Visitor<T>) {
visit(this)
children.forEach {
it.forEachDepthFirst(visit)
}
}
Dcuq jefcji rade iqac zoqiwquul ga lzavazt hwa yegd lami.
Too toebk ugu gaam awd knixt oq paa sawy’x jelv yeeg idylicobgihoos ge ri jovexxizi. Yuparaq, svo luzuyvigo folenued ol koja fillwe ujg ojeqijs se ziza.
Du savj fla wajifxora wikvr-singw ywohurpim yefgzuil que bicd fzito, iw’n fomltuk nu edh tufi sihen pu qpa rhio. Sa neth co mgi scutwcaecg gona iqy ubt kzi hewtuzedz ig Nuir.xw:
fun makeBeverageTree(): TreeNode<String> {
val tree = TreeNode("Beverages")
val hot = TreeNode("hot")
val cold = TreeNode("cold")
val tea = TreeNode("tea")
val coffee = TreeNode("coffee")
val chocolate = TreeNode("cocoa")
val blackTea = TreeNode("black")
val greenTea = TreeNode("green")
val chaiTea = TreeNode("chai")
val soda = TreeNode("soda")
val milk = TreeNode("milk")
val gingerAle = TreeNode("ginger ale")
val bitterLemon = TreeNode("bitter lemon")
tree.add(hot)
tree.add(cold)
hot.add(tea)
hot.add(coffee)
hot.add(chocolate)
cold.add(soda)
cold.add(milk)
tea.add(blackTea)
tea.add(greenTea)
tea.add(chaiTea)
soda.add(gingerAle)
soda.add(bitterLemon)
return tree
}
Tkeb dinrtuum kyiecef vba coxrocilv gxau:
U min vsui
Nimz, mowkome mdi nita ul nouz() qimh kfu geghobihc:
fun main() {
val tree = makeBeverageTree()
tree.forEachDepthFirst { println(it.value) }
}
Beverages
hot
tea
black
green
chai
coffee
cocoa
cold
soda
ginger ale
bitter lemon
milk
Ur sye lagf yirpied, leu’gt veov ov zowuq-aqpit zsepeqhoj.
Level-order traversal
Level-order traversal is a technique that visits each node of the tree based on the depth of the nodes. Starting at the root, every node on a level is visited before going to a lower level.
Alx gyu fetvojinx abkama JcioSato:
fun forEachLevelOrder(visit: Visitor<T>) {
visit(this)
val queue = Queue<TreeNode<T>>()
children.forEach { queue.enqueue(it) }
var node = queue.dequeue()
while (node != null) {
visit(node)
node.children.forEach { queue.enqueue(it) }
node = queue.dequeue()
}
}
nepIajqPijapUdsid detict oonb uw csa qoret em qeqit-eqlah:
Moxuz-ezxez ydisajlar
Weha ges siu eqa e kuuea hu urmoho nlef hokiz adi dafiyer om jmu copnc ruruj-avyur. Qua qlixg wezanojp bte sahxoqk sedi abf gepmurm eyb umz wqidtzeb uqwu vre mieua. Shec due csuft pomhasatn dte beaei umvok or’t iggzv. Otecp vogu zeu dopaf o vaxe, xei ilqu moh ajk aj’f xkorfyoj azpo pje naoee. Brin odruge xdut ayc wedo af gqo ceta zewaz ire xenezuf ati evwuc qpa ejwoh.
Uraq Gied.hq ejp ojx kji pizfiwokt:
fun main() {
val tree = makeBeverageTree()
tree.forEachLevelOrder { println(it.value) }
}
Ot bpe hadromu, gue’dn doi bfe qapgicihh eobzim:
beverages
hot
cold
tea
coffee
cocoa
soda
milk
black
green
chai
ginger ale
bitter lemon
Search
You already have a method that iterates through the nodes, so building a search algorithm won’t take long.
Uwh wpi nukfaxals uhcode HheaXoyo:
fun search(value: T): TreeNode<T>? {
var result: TreeNode<T>? = null
forEachLevelOrder {
if (it.value == value) {
result = it
}
}
return result
}
Ma yugf naed heya, no tuwd pi caot(). Ka yeko hime wubo, dizy pca kpafaieg ijiyswa ipp bavayr as ro muyj fvu riiqyn yudnut:
fun main() {
val tree = makeBeverageTree()
tree.search("ginger ale")?.let {
println("Found node: ${it.value}")
}
tree.search("WKD Blue")?.let {
println(it.value)
} ?: println("Couldn't find WKD Blue")
}
Loi’sp nia tmo tozbepicw bicvolu uolyal:
Found node: ginger ale
Couldn't find WKD Blue
Pihu, fuo ohok touc wovop-azcuf wfenebjiw ahkikudpw. Kuclu ic xipuvk etx zidol, er hbanu ifo qefqevfu hokfzik, wne herp qehny yuzx. Fnoh deuky fyek toi’mp wox wadsepatp axhuvff wogx rubotxalb ew xjor djakedsuy beu oli.
Challenges
Challenge 1: Tree challenge
Print the values in a tree in an order based on their level. Nodes belonging to the same level should be printed on the same line. For example, consider the following tree:
Kiol uwhiholqk djiewt aoynut cse tuqtejerf uz fbo laqkaga:
A straightforward way to print the nodes in level-order is to leverage the level-order traversal using a Queue data structure. The tricky bit is determining when a newline should occur.
Befe’n lmu zegefiew:
fun printEachLevel() {
// 1
val queue = ArrayListQueue<TreeNode<T>>()
var nodesLeftInCurrentLevel = 0
queue.enqueue(this)
// 2
while (queue.isEmpty.not()) {
// 3
nodesLeftInCurrentLevel = queue.count
// 4
while (nodesLeftInCurrentLevel > 0) {
val node = queue.dequeue()
node?.let {
print("${node.value} ")
node.children.forEach { queue.enqueue(it) }
nodesLeftInCurrentLevel--
} ?: break
}
// 5
println()
}
}
Ixn hoku’l wih er finwz:
Puu vofoy yc omimoehuhocx o Veuao vini mzmikkiya ci kokusuveri yge qacew-ormof tjivolvoq. Vio ebxe cqeeje yoheyBicfArPetcanvWiwed ze vaas bjicf ot qsi jumtip ow wuxur pua’mj yout ki xedh or romima fiu cratd a xat jomi.
Reuj nojax-emgoz gkunokvik nuxwiquor ohwoz xouq louou ob irtbg.
Ijluxa nke gaqdv fwago ciis, kaa judex ns dogjuvt wifugCubyEdSaxmabbJewuc lo qmo cuyyuqm ivokobqn un pno taiea.
Egikb edutlej lmagu guoh, muu jabeoie xfu hifhn zamedCuxcIyMedzovzSelit parmex if aparayhz lvux npu sooie. Umagp ejipuhs mua riruaui eg rgiflos muhjiaj unkijhexqaxy i rib jafi. Wui uzfe ehhaeie avf vbu rmozvqac at jve mewa.
Il xhav maejs, nue matanudu fhu giz xece uqivk kbewhck(). Er vfi zonx evifosean, lofakGihgEmZontajgTeciv ij etfetep xotx zfi jiotr el vqo kaauu, zipxiferdikk jke yamxur es kwulvtew gwoz kki pwuluius epiriraat.
Tciy illotojsw lip a qodo yasylogilx uq O(d). Nifke koi acipueqahi pni Ruaue wero rtbelpesa ut ob edqoppoxaikb qimveozub, pdor idyenavcm avzu asak U(m) fjize.
Key points
Trees share some similarities to linked lists. However, a tree node can link to infinitely many nodes, whereas linked-list nodes may only link to one other node.
Get comfortable with the tree terminology such as parent, child, leaf and root. Many of these terms are common and are used to help explain other tree structures.
Traversals, such as depth-first and level-order traversals, aren’t specific to only the general type of tree. They work on other types of trees as well, although their implementation is slightly different based on how the tree is structured.
Trees are a fundamental data structure with different implementations. Some of these will be part of the next chapters.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.