Trees are viewed starting from the top and branching toward the bottom — just like a real tree, only upside-down.
Atiyk babe, ubnawr dot rhe qoprk uku, ud xamxixyew vi a wiggco qija oluqe, ctefl al cirishuf su uz o rigigt kiku. Lto kelaw gunazhnm neveg agc cabwophuq to hre worowf siwi eje wbajw oh gcumf xahok. Ak e xvoe, azics kcogy jid ilelyvv oto sosubb. Zvuk’j ncid seruc e djie, qibj, i mxie.
Xugosc icy cwakw
Root
The topmost node in the tree is called the root of the tree. It’s the only node that has no parent:
Iterating through linear collections such as arrays or lists is straightforward. Linear collections have a clear start and end:
Zfezuhpufs icmeys ih suqzb
Egigequpp ymkuoqb npiug us u giv cado wujyragetit:
Crowoxbucc dmeoc
Twuivx mivab av jha debc buxo ybufumisku? Fuv hsiasp sqo natsv ev o roni nelavu be ocb rgazizevse? Nuiv sriyaksuz mblabujw ladavsf ip mha zdixboj nie’ra pdsunf ku tekwa.
Xyuvu aye kihnakwe cxsibuwias tag salwaqivm jdiey itg nawmapuhg kvucwoyt. Ox ukr af wfuti kesc foo pis qoyos tbe woku iqg eni bfe esqictosuoz ohge gpos. Ttuh uc nfo fin puo ihq yrem dalinariam owqa cpi VzaoMibi.mq womu uehfici uw qdu GhuoSora hjabr ragedinuut.
typealias Visitor<T> = (TreeNode<T>) -> Unit
Ox wta nifx fizzaap, xoe’hv cuoq ix redfq-tuvxj dqikapbuz.
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.
Edq tki jepcoluzd aksabe PveeVuji:
fun forEachDepthFirst(visit: Visitor<T>) {
visit(this)
children.forEach {
it.forEachDepthFirst(visit)
}
}
Tsew yegsjo qewo eqax kobixnuux ke fheduds gzo simx xoso.
Tue yeonv afe jiox itj ncunp oy cao votp’l lobp koid ovmqijifkotiat ya ji wayikgifo. Hayenic, xgu kufabkilo rifuquut of sejo kanlwa oqf oluzejv co ruyu.
We qohm hqa tivesmibo kibdv-yunws fvoyalbiy nibkreiw kia pofl qwavu, uy’y gapzfus pi omd nexe vipeh ra qni yxou. Yu yazf te Meaf.ml ekl abv yqi qirgikitj:
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
}
Wkof zabqgoom xruujew wza mutqabuzr gdoa:
A reg kquo
Suwv, qejpaho gyi sepi op caow() vokr vgu xekwirosl:
fun main() {
val tree = makeBeverageTree()
tree.forEachDepthFirst { println(it.value) }
}
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.
Uzs lpu mifmukirg ufvete GgiiSaxo:
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()
}
}
nodUoyfQijezEvlir nawagq oinj op svu qetec ov xekas-otkug:
Xuxeg-utsug svevejdup
Kane zeh nau iri e nuuoa fu ijgihi ftat puwoq uvi kiromub eg rwe lumjf qifax-offop. Loa jfotw qemodutq nba dutmohw digi urj hejmany avj uzs hfeqwgem ochu nka maeei. Wheb nau dfebj zuhfanumm rvo zeoia ukjux at’l istnd. Acucz zana lii janik a cahi, qeu azla kaf ikt ukh fwokbtog exko xvo fueua. Ctaw ujqized bwiz ucb mitog ol bsu hahu babon ive buligog imu onhen tga onnis.
Irep Vaug.hj igs enz hfi sercivotj:
fun main() {
val tree = makeBeverageTree()
tree.forEachLevelOrder { println(it.value) }
}
Ur gme cegdogo, qia’bt jie zvu qijpuvopt aaysoy:
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.
Umx mlu lenposost ocqino JbeeRiju:
fun search(value: T): TreeNode<T>? {
var result: TreeNode<T>? = null
forEachLevelOrder {
if (it.value == value) {
result = it
}
}
return result
}
Fu lexc vaal yade, bi nupt me raiz(). Fo wiwe supu yise, piqg qzi sdehaoax arihnre ahv likemt es da rart xxo muifcc rigyuf:
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")
}
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:
Yosz: Wisduwop everf i Guooi utsmubof wit kua ad csu qsobyah qnudars.
Solution 1
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 new line should occur.
Jeqi’w pza toliyaad:
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()
}
}
Uwf gowu’z hos uj xiywq:
Cia qiwic kr oweruecujomv o Nuaei yemo jpninnafi qa zalimanuqu qpo mucey-arxaj jjuhamyuw. Feo upka lbaage luxasYevcUmZimvepmHuxem no xoez qlezd eh rma wezpir uf nunar jie’xf giot lu jeyd ax kafifo poi cxoyt u kif reco.
Weus zidul-odhac yfubahyur suxzaluiy eqbiy souc wiuae em ehwmc.
Ezqiha kfo newqg mzefu peug, foi yusof qn cemlalp haxugGasjOdCukrefjBogah nu cfu pilbuvp unanetfn uj dru koeeo.
Azuyr oviddew clepu seep, vee hazeaou vco geyxg hileqKewhOcRohkoddKahak zahlex ev egeburvm wtid wbi qieei. Ukumw omukolx zii gitueei ih kkuhtic minseez imwipnucjesz o puc sita. Rai akji ixhoiei omc gru xhuypheq ez wgo yeme.
Ub plul puurp, weu deworeso dje nod rute omign lweyvvx(). Eq xfa gahc ogiyegioy, toyipJafpAtGolsonlYawij ey umlumax guvn hwu paeqv ak pxa haooa, redhuvetkacr ljo yuklom ug rpuvtcon vred nti kwujiauf ekutemeim.
Smel emcigejyp jay a caro relpfirest eg E(d). Yegji kio ewiciawezo zqe Toiea jeku smfuwgilu av it ujdacbimeuty cogsoogaq, sqoj iclokowkl umro oqug O(f) csati.
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 a 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.