Saturday, June 2, 2018

Kotlin Data Structure: Circular Queue

Welcome to this post.
In this post, we are going to learn about the Circular queue.

If you don't know the queue data structure, please check this post Queue.

In the previous post of Queue, I discuss the problem about the queue. So today we learn about the circular queue.

In queue, to data in the queue, the method is called enqueue()  
and to get data from the queue, the method is dequeue()

Let's jump in the programming:

circular queue
circular queue

In the above picture, you can see that data inserted in the back or last position and then the position move one row. and the same thing happens when we access data.
So we have to track
  • Top position
  • Last position
First, create a class with a constructor. In the constructor take an int type data. It will use for initializing the circular queue with size.
class CircularQueueK(size: Int){
}
Create an array with size and also create 2 variable that mentions above.
private val list:Array<Any> = Array(size,{ i: Int -> i })
private var head = 0
private var tail = 0

we have to implement 2 additional method
  • isFull() ->  this will return true if the queue is full, so we don't allow to insert more data.
  • isEmpty() -> this will return true if the queue is empty, so we don't allow dequeue the data.
Let's implement those-
fun isFull() = (tail + 1) % list.size == head
fun isEmpty() = head == tail

Code review of isFull():
In this method, we increase of tail with one the modules with list size and if the result is same as head then it is full. For example, At first, the head is 0, so insert data and tail are increasing, assume that our list size is 5, so at the 4 index it will be filled and the tail is now 4.
Now, when this method is called then first increase tail, and modulus with the list size. Increase the tail to 5 and list size is 5, then the modulus is zero, and it is equal to the head. So it's now empty. because it's come back to the start position.

enqueue():
First, check the circular queue is full or not, If full the return.
Insert data in the list at the tail position
Insert the value in the tail as we did on the if full method
fun enqueue(value: Any){
    if (isFull()){
        return
    }

    list[tail] = value
    tail = (tail+1) % list.size
}

dequeue():
First, check the circular queue is empty or not. if empty return
Get data from the head position
assign new value of the read same as enqueue()
fun dequeue():Any{

    var a:Any = ""

    if (!isEmpty()){
        a = list[head]
        head = (head +1) % list.size
    }

    return a
}

Code analysis:
head = (head +1) % list.size
what is actually happening under the hood?
For example, assume the list size is 5 and head position is now 4.
Now if we want to access data from the list then it is the last position of the list. so we don't access next data.
This is the main problem in the queue. But in the circular queue head and tail position is circled from zero to list position.
so now our goal is to initialize head position to again start point.
If the head is 4 then with increase 1 and modules with the list size, and the result is zero.
So, it's back again.
In the circular queue, at least one position is to remain blank for this purpose.

Ok, one more extra method to go-
fun iterator() = list.withIndex()

Now time for testing
Create the main method-
fun main(args: Array<String>) {
}

Create an instance of the circular queue.
val queue = CircularQueueK(5)

enqueue():
run a while loop until the circular queue is full
var s = 0

while (!queue.isFull()){
    queue.enqueue(s)
    s++
}

Check the list:
run a for loop with the help of iterator() function that we created earlier.
for ((i,v) in queue.iterator()) {
    println("Index:$i and value:$v")
}
Output:
Index:0 and value:0
Index:1 and value:1
Index:2 and value:2
Index:3 and value:3
Index:4 and value:4

dequeue():
just call dequeue method for 3 times and print the value
println("\nGet value1:${queue.dequeue()}")
println("Get value2:${queue.dequeue()}")
println("Get value3:${queue.dequeue()}")
Output:
Get value1:0
Get value2:1
Get value3:2

now enqueue() again:
var d = 10
while (!queue.isFull()){
     queue.enqueue(d)
     d++
}

Compare this list with the previous result-
print all data from the circular queue
for ((i,v) in queue.iterator()) {
    println("Index:$i and value:$v")
}
Output:
Index:0 and value:11
Index:1 and value:12
Index:2 and value:2
Index:3 and value:3
Index:4 and value:10

Result analysis:
If you compare this output with the previous output you will see the changes.
we call dequeue() function for 3times, that means we get 3 data from the circular queue. So 3 position is empty now.
We enqueue() again, and only 3 data is inserted on the position of the array is 4, 1, 2 and now the head position is 3. so circulated.

That's the ending of the circular queue()
Thank you, for reading.
Happy coding.

About Author:

I am Shudipto Trafder,
Since 2015, I write android code. I love to implement new ideas. I use java and also kotlin. Now I am learning Flutter. I love to learn new things and also love to share. And that is the main reason to run this blog.


Let's Get Connected: Facebook Twitter Linkedin Github

No comments :