mirror of
https://github.com/AdrianKuta/Tree-Data-Structure.git
synced 2025-04-19 23:19:03 +02:00
4: Implement Level-order traversal algorithm (#17)
This commit is contained in:
parent
b69e838a8a
commit
5dd586f9af
@ -1,5 +1,6 @@
|
|||||||
package com.github.adriankuta
|
package com.github.adriankuta
|
||||||
|
|
||||||
|
import com.github.adriankuta.iterators.LevelOrderTreeIterator
|
||||||
import com.github.adriankuta.iterators.PostOrderTreeIterator
|
import com.github.adriankuta.iterators.PostOrderTreeIterator
|
||||||
import com.github.adriankuta.iterators.PreOrderTreeIterator
|
import com.github.adriankuta.iterators.PreOrderTreeIterator
|
||||||
import com.github.adriankuta.iterators.TreeNodeIterators
|
import com.github.adriankuta.iterators.TreeNodeIterators
|
||||||
@ -22,6 +23,9 @@ open class TreeNode<T>(val value: T) : Iterable<TreeNode<T>>, ChildDeclarationIn
|
|||||||
val children: List<TreeNode<T>>
|
val children: List<TreeNode<T>>
|
||||||
get() = _children
|
get() = _children
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Choose one of available iterators from [TreeNodeIterators]
|
||||||
|
*/
|
||||||
var defaultIterator: TreeNodeIterators = PreOrder
|
var defaultIterator: TreeNodeIterators = PreOrder
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -126,27 +130,11 @@ open class TreeNode<T>(val value: T) : Iterable<TreeNode<T>>, ChildDeclarationIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tree is iterated by using `Pre-order Traversal Algorithm"
|
* You can change default iterator by changing [defaultIterator] property.
|
||||||
* 1. Check if the current node is empty or null.
|
|
||||||
* 2. Display the data part of the root (or current node).
|
|
||||||
* 3. Traverse the left subtree by recursively calling the pre-order function.
|
|
||||||
* 4. Traverse the right subtree by recursively calling the pre-order function.
|
|
||||||
* ```
|
|
||||||
* E.g.
|
|
||||||
* 1
|
|
||||||
* / | \
|
|
||||||
* / | \
|
|
||||||
* 2 3 4
|
|
||||||
* / \ / | \
|
|
||||||
* 5 6 7 8 9
|
|
||||||
* / / | \
|
|
||||||
* 10 11 12 13
|
|
||||||
*
|
|
||||||
* Output: 1 2 5 10 6 11 12 13 3 4 7 8 9
|
|
||||||
* ```
|
|
||||||
*/
|
*/
|
||||||
override fun iterator(): Iterator<TreeNode<T>> = when (defaultIterator) {
|
override fun iterator(): Iterator<TreeNode<T>> = when (defaultIterator) {
|
||||||
PreOrder -> PreOrderTreeIterator(this)
|
PreOrder -> PreOrderTreeIterator(this)
|
||||||
PostOrder -> PostOrderTreeIterator(this)
|
PostOrder -> PostOrderTreeIterator(this)
|
||||||
|
LevelOrder -> LevelOrderTreeIterator(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.github.adriankuta.iterators
|
||||||
|
|
||||||
|
import com.github.adriankuta.TreeNode
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tree is iterated by using `Level-order Traversal Algorithm"
|
||||||
|
* In level-order traversal we iterating nodes level by level,
|
||||||
|
* starting from root, and going deeper and deeper in tree.
|
||||||
|
* ```
|
||||||
|
* E.g.
|
||||||
|
* 1
|
||||||
|
* / | \
|
||||||
|
* / | \
|
||||||
|
* 2 3 4
|
||||||
|
* / \ / | \
|
||||||
|
* 5 6 7 8 9
|
||||||
|
* / / | \
|
||||||
|
* 10 11 12 13
|
||||||
|
*
|
||||||
|
* Output: 1 2 3 4 5 6 7 8 9 10 11 12 13
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
class LevelOrderTreeIterator<T>(root: TreeNode<T>) : Iterator<TreeNode<T>> {
|
||||||
|
|
||||||
|
private val stack = ArrayDeque<TreeNode<T>>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
stack.addLast(root)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hasNext(): Boolean = stack.isNotEmpty()
|
||||||
|
|
||||||
|
override fun next(): TreeNode<T> {
|
||||||
|
val node = stack.removeFirst()
|
||||||
|
node.children
|
||||||
|
.forEach { stack.addLast(it) }
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
}
|
@ -4,10 +4,8 @@ import com.github.adriankuta.TreeNode
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Tree is iterated by using `Post-order Traversal Algorithm"
|
* Tree is iterated by using `Post-order Traversal Algorithm"
|
||||||
* 1. Check if the current node is empty or null.
|
* In post-order traversal, we starting from most left child.
|
||||||
* 2. Display the data part of the root (or current node).
|
* First visit all children of parent, then parent.
|
||||||
* 3. Traverse the left subtree by recursively calling the pre-order function.
|
|
||||||
* 4. Traverse the right subtree by recursively calling the pre-order function.
|
|
||||||
* ```
|
* ```
|
||||||
* E.g.
|
* E.g.
|
||||||
* 1
|
* 1
|
||||||
@ -19,7 +17,7 @@ import com.github.adriankuta.TreeNode
|
|||||||
* / / | \
|
* / / | \
|
||||||
* 10 11 12 13
|
* 10 11 12 13
|
||||||
*
|
*
|
||||||
* Output: 1 2 5 10 6 11 12 13 3 4 7 8 9
|
* Output: 10 5 11 12 13 6 2 3 7 8 9 4 1
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class PostOrderTreeIterator<T>(root: TreeNode<T>) : Iterator<TreeNode<T>> {
|
class PostOrderTreeIterator<T>(root: TreeNode<T>) : Iterator<TreeNode<T>> {
|
||||||
|
@ -4,10 +4,8 @@ import com.github.adriankuta.TreeNode
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Tree is iterated by using `Pre-order Traversal Algorithm"
|
* Tree is iterated by using `Pre-order Traversal Algorithm"
|
||||||
* 1. Check if the current node is empty or null.
|
* The pre-order traversal is a topologically sorted one,
|
||||||
* 2. Display the data part of the root (or current node).
|
* because a parent node is processed before any of its child nodes is done.
|
||||||
* 3. Traverse the left subtree by recursively calling the pre-order function.
|
|
||||||
* 4. Traverse the right subtree by recursively calling the pre-order function.
|
|
||||||
* ```
|
* ```
|
||||||
* E.g.
|
* E.g.
|
||||||
* 1
|
* 1
|
||||||
@ -33,12 +31,10 @@ class PreOrderTreeIterator<T>(root: TreeNode<T>) : Iterator<TreeNode<T>> {
|
|||||||
override fun hasNext(): Boolean = stack.isNotEmpty()
|
override fun hasNext(): Boolean = stack.isNotEmpty()
|
||||||
|
|
||||||
override fun next(): TreeNode<T> {
|
override fun next(): TreeNode<T> {
|
||||||
println(stack)
|
|
||||||
val node = stack.removeLast()
|
val node = stack.removeLast()
|
||||||
node.children
|
node.children
|
||||||
.asReversed()
|
.asReversed()
|
||||||
.forEach { stack.addLast(it) }
|
.forEach { stack.addLast(it) }
|
||||||
println(stack)
|
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,68 @@
|
|||||||
package com.github.adriankuta.iterators
|
package com.github.adriankuta.iterators
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see PreOrder
|
||||||
|
* @see PostOrder
|
||||||
|
* @see LevelOrder
|
||||||
|
*/
|
||||||
enum class TreeNodeIterators {
|
enum class TreeNodeIterators {
|
||||||
PreOrder, PostOrder
|
/**
|
||||||
|
* Tree is iterated by using `Pre-order Traversal Algorithm"
|
||||||
|
* The pre-order traversal is a topologically sorted one,
|
||||||
|
* because a parent node is processed before any of its child nodes is done.
|
||||||
|
* ```
|
||||||
|
* E.g.
|
||||||
|
* 1
|
||||||
|
* / | \
|
||||||
|
* / | \
|
||||||
|
* 2 3 4
|
||||||
|
* / \ / | \
|
||||||
|
* 5 6 7 8 9
|
||||||
|
* / / | \
|
||||||
|
* 10 11 12 13
|
||||||
|
*
|
||||||
|
* Output: 1 2 5 10 6 11 12 13 3 4 7 8 9
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
PreOrder,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tree is iterated by using `Post-order Traversal Algorithm"
|
||||||
|
* In post-order traversal, we starting from most left child.
|
||||||
|
* First visit all children of parent, then parent.
|
||||||
|
* ```
|
||||||
|
* E.g.
|
||||||
|
* 1
|
||||||
|
* / | \
|
||||||
|
* / | \
|
||||||
|
* 2 3 4
|
||||||
|
* / \ / | \
|
||||||
|
* 5 6 7 8 9
|
||||||
|
* / / | \
|
||||||
|
* 10 11 12 13
|
||||||
|
*
|
||||||
|
* Output: 10 5 11 12 13 6 2 3 7 8 9 4 1
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
PostOrder,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tree is iterated by using `Level-order Traversal Algorithm"
|
||||||
|
* In level-order traversal we iterating nodes level by level,
|
||||||
|
* starting from root, and going deeper and deeper in tree.
|
||||||
|
* ```
|
||||||
|
* E.g.
|
||||||
|
* 1
|
||||||
|
* / | \
|
||||||
|
* / | \
|
||||||
|
* 2 3 4
|
||||||
|
* / \ / | \
|
||||||
|
* 5 6 7 8 9
|
||||||
|
* / / | \
|
||||||
|
* 10 11 12 13
|
||||||
|
*
|
||||||
|
* Output: 1 2 3 4 5 6 7 8 9 10 11 12 13
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
LevelOrder
|
||||||
}
|
}
|
@ -177,4 +177,52 @@ class TreeNodeTest {
|
|||||||
val expectedPreOrder = listOf("E", "B", "C", "F", "G", "H", "I", "J", "D", "A")
|
val expectedPreOrder = listOf("E", "B", "C", "F", "G", "H", "I", "J", "D", "A")
|
||||||
assertContentEquals(expectedPreOrder, tree.toList().map { it.toString() })
|
assertContentEquals(expectedPreOrder, tree.toList().map { it.toString() })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun secondPostOrderIteratorTest() {
|
||||||
|
val tree = tree(1, TreeNodeIterators.PostOrder) {
|
||||||
|
child(2) {
|
||||||
|
child(5) {
|
||||||
|
child(10)
|
||||||
|
}
|
||||||
|
child(6) {
|
||||||
|
child(11)
|
||||||
|
child(12)
|
||||||
|
child(13)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
child(3)
|
||||||
|
child(4) {
|
||||||
|
child(7)
|
||||||
|
child(8)
|
||||||
|
child(9)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val expectedOrder = listOf(10, 5, 11, 12, 13, 6, 2, 3, 7, 8, 9, 4, 1)
|
||||||
|
assertContentEquals(expectedOrder, tree.toList().map { it.value })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun levelOrderIteratorTest() {
|
||||||
|
val tree = tree(1, TreeNodeIterators.LevelOrder) {
|
||||||
|
child(2) {
|
||||||
|
child(5) {
|
||||||
|
child(10)
|
||||||
|
}
|
||||||
|
child(6) {
|
||||||
|
child(11)
|
||||||
|
child(12)
|
||||||
|
child(13)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
child(3)
|
||||||
|
child(4) {
|
||||||
|
child(7)
|
||||||
|
child(8)
|
||||||
|
child(9)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val expectedOrder = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)
|
||||||
|
assertContentEquals(expectedOrder, tree.toList().map { it.value })
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user