Main navigation

This post is one in a series of stuff formally trained programmers know – the rest of the series can be found in the series index.

Continuing on with more tree-based data structures, we get to the heap. If we look back at the BST and Red/Black those trees ended up with the most average/middle value at the root node so that nodes which were smaller were on the left and larger nodes were on the right, the heap changes that.

There are actually two heaps, a minimum and maximum value heap, but there are very similar. The key aspects to know about either heap are

It is a binary tree. This is important for insertion and deletion and ensures the depth of the tree doesn't grow out too far from the root node.

In a minimum heap, the root node is the SMALLEST value in the tree.

In a minimum heap, any node should be smaller than all of its' children

In a maximum heap, the root node is the LARGEST value in the tree

In a maximum heap, any node should be larger than all of its children

The advantage of a heap is as an implementation of a Queue where you can control the order items appear in the queue rather than just relying on insertion order.

Let's have a look at what these will look like when we have the following dataset: 45, 42, 56, 78, 99, 30

Step

Minimum Heap

Maximum Heap

1

We add 45 as the root node

We add 45 as the root node

2

We add 42 as the first child, but it is smaller, so we will swap it with the root node

We add 42 add as the first child node

3

We add 56 as the second child node

We add 56 as the second child node; it is larger than its parent so we swap them.

4

We add 78 as a child of 45

We add 78 as a child of 42, though it is larger so it must be swapped. 78 is now a child of 56, which still wrong so we need to swap them too.

5

We add 99 as a child of 45

We add 99 as a child of 56. 99 is larger, so we then swap 99 and 56. 99 is still larger than 78, so we need to swap those nodes too

6

Next we add 30 under 56. It is smaller than 56 so it must be swapped. Once swapped, its parent 42 is also larger so they need to swapped too.

Last we add 30 to under 45.

Implementations

Java has a built-in implementation with the PriorityQueue and, unfortunately, .NET and JavaScript lacks an out of the box option.

You can see on line 21, we define the new object with the object keyword and then use : Comparator<Int> to state it implements that interface. The Comparator has a single function which needs to be implemented which we do on line 22.

The second Koan takes this further and states if there is a single method in an abstract class or interface then we can use SAM, or Single Abstract Method, to avoid needing the class at all as we just need to implement the single function. To achieve this with the Koan, we use an anonymous function that handles the compare function of the Comparator:

and lastly, if we look back to previous post we can use the extension method to simply it further:

fun task12(): List<Int>{

return arrayListOf(1, 5, 2).sortedDescending()

}

These Koans have given me more thoughts about the language than probably any previous Koans:

Why do classes which implement an interface use override?
In C#, when you implement an interface you do not need to state that you are not overriding the functions (see this example). In C# only state that your are overriding when you inherit from a function and you actually override a function. The reason is that an interface in Kotlin is closer to an abstract class than in C#, to the point it can have functionality - yup, interfaces can have functions and logic!

So why does Kotlin have interfaces and abstract classes?
The key difference is an abstract class can have state while the logic in an interface needs to be stateless!

Why bother having SAM?
As I was working on the Koan, I was delighted by the SAM syntax... and then I wondered why I needed this at all? Why is Collections.sort taking a class as the second parameter? Why not just pass in a function, since that is all that is actually needed? Both C# and Kotlin supports passing functions so this is possible... but something I never knew about Java is that it doesn't support passing functions! You have to use Callable, a class, to pass functions.

When we get into the second Koan, we get exposed to some of the built-in extension's functions in Kotlin which ship out of the box; in this case, we use sortedDescending extension method with the Java collection. It is a great example of mixing Java and Kotlin too:

This is the 9th post in a multipart series.
If you want to read more, see our series index

The goal of this Koan is to show how smart the Kotlin compiler is; in that when you use something like the is keyword to handle type checking the compiler will then know the type later on and be able to use it intelligently.

So if we want to check types in Java we would use something like this where we would use instanceof to check the type and then cast it to the right type.

In Kotlin we, by checking the type the compiler handles the casting for us, but before we get to that we also got to learn about the when which is the Kotlin form of the Switch keyword in C# or Java and it offers similar functionality, as shown in this example:

when(x){

1-> print("x == 1")

2-> print("x == 2")

else->{// Note the block

print("x is neither 1 nor 2")

}

}

and it supports multiple values on the same branch

when(x){

0, 1-> print("x == 0 or x == 1")

else-> print("otherwise")

}

Where it gets awesome, is the extra actions it supports; for example when values can be functions, not just constants:

when(x){

parseInt(s)-> print("s encodes x")

else-> print("s does not encode x")

}

You can also use in or !in to check values in a range/collection:

when(x){

in1..10-> print("x is in the range")

in validNumbers -> print("x is valid")

!in10..20-> print("x is outside the range")

else-> print("none of the above")

}

It really is very cool, so let us see how we use Smart Casts and when together and how it compares with the Java code above:

This is the 8th post in a multipart series.
If you want to read more, see our series index

The next Koan looks at how Kotlin handles nulls, and it does it wonderfully; Null is explicitly opt-in. For example, in C# you can assign null to a string variable but in Kotlin unless you say you want to support nulls, which you do by adding a trailing question mark to the class, you cannot.

This post is one in a series of stuff formally trained programmers know – the rest of the series can be found in the series index.

In this post, we will look at two related and simple data structures, the Stack and the Queue. The stack is a structure which can be implemented with either an Array or Linked List.

An important term for understanding a stack is that it is LIFO, last-in-first-out, system; namely, the last item you add (or push or bury) is the first item you take out when you retrieve an item (or peek or unbury).

Let's have a look at what a stack would look like:

In this, we added 1, 2, 3, 4, and then 5 and when we read from the stack we read in the reverse order.

Implementations

Next is the queue, which is very similar to the stack, except where the stack was LIFO; a queue is FIFO, first-in-first-out; so if we put in 1, 2, 3, 4, & 5 into the queue, then we would read them in the same order, i.e. 1, 2, 3, 4, 5.

Implementations

C# has a queue implementation and the JavaScript array can act as a queue, when you use unshift to add to the beginning of the array (also known as the head) and pop to remove from the end of the array (also known as the tail).

Yup, a single line. The data annotation adds a number of important functions (like ToString and copy). We then declare the class with a constructor which takes two parameters which both become properties.

Another important aspect I learnt with this one is that Kotlin has both a val and var keyword for variables. We have seen var already and val is for read-only variables.

This is the 4th post in a multipart series.
If you want to read more, see our series index

Previously we covered Named Arguments and this is a small continuation from it, we start with a simple function fun foo(name: String): String = todoTask3() and we need to have it call a single Java function and to provide it with default values which ultimately looks like this: