•  
  • Algorithms (61)

C# Data Structures – Collections overview

Tags: No Tags
Comments: No Comments
Published on: August 30, 2011

Within C# there are several collections (data structures, containers) ready to use for your applications. Moreover, there are several collections (data structures, containers) in computer science that serves lot of different purposes.

Array :   Let’s start with array, which is likely to be the most used data structures within implementations of C# collections, even the data structures like List, Stack, Queue and many others use array as the base the data structure.

Arrays are very efficient data structures. There are single dimensional array as well as multi-dimensional arrays and jagged arrays. Before getting into how to create arrays and their methods, let’s point out the memory structure of an array. When you create an array, you will need contiguous space in memory. Let’s say you have an array of size 1 million, you will need space for 1 million blocks within the memory. This can be good and bad. It can be good because keeping data at the same region will make access to it faster, compared to having elements all over the memory, such as linked list node. Also, it can be bad, if you reallocate your array you will need enough contagious space within AppDomain for reallocation, otherwise it fails. Is this a seldom case? Yes.

Arrays are based on indexes, which (almost all the time) starts with index 0. There are ways to start an array with a different index, which is mentioned in CLR via C# book. Arrays are fixed size once you create them, arrays don’t grow dynamically unlike a list or arraylist. If you have an array of size 5 and you need to insert the 6th element to it, you will have to allocate a new array with more capacity (load factor), copy all the elements from current element to the new array and then you can insert new elements to it.

Let’s talk about the insertion, search and delete operations on arrays. In order to insert an element to an array, you have to know the location, index, in which you need to insert the element to. If there is an element at the location you insert an element, it will place the new item to that location and you will lose whichever element was there. So insertion to an array takes constant time , O(1). However, if the array is full and you need to insert an additional item, as I mentioned it, you will have to copy all the array elements to a new array, which takes a constant time to insert for each element, this operation becomes amortized and overall insert to an array is still constant time, O(1). Searching an element in an array is very easy, you have to iterate through all the elements and until you find the element you are looking for, which is O(n). There are methods to sort an array. Once the array is sorted you can use binary search, which is way faster than linear search. Deleting an element from an array is same as inserting an element, it takes constant time.

Arrays are enumerable collection in C#, in other words you can enumerate through an array using foreach. Moreover, you can use a for loop and access the array elements by index. Arrays are Reference Types. Once you create an array, it is created on the heap even if it holds a reference type or value type. Because arrays are enumerable, you can also call LINQ methods on arrays.

If you like to read more about the syntax of arrays as well as the methods go to:

http://msdn.microsoft.com/en-us/library/9b9dty7d.aspx

ArrayList : ArrayList is a dynamic array of objects. While this data structure used to be very popular due to dynamic feature, it has been almost abandoned and being kept in the framework for backward compatibility.

If you look at the definition of ArrayList Source code, which is as follows:

public class ArrayList : IList, ICollection, IEnumerable, ICloneable
{
// Fields
private const int _defaultCapacity = 4;
private object[] _items;
private int _size;
[NonSerialized]
private object _syncRoot;
private int _version;
private static readonly object[] emptyArray;
// Much more goes on.
}

You will see that the default capacity of an ArrayList is 4 as well as ArrayList contains items of object type. ArrayList implements IEnumerable which indicates that you can enumerate through the elements that ArrayList contains via foreach loop. Another Collection Interface ArrayList implements is IList, which allows accessing ArrayList elements by index, as well as inserting an item at an index location and removing an item from an index location. Accessing an item via index happens with an indexer. Moreover, ArrayList implements ICollection interface which allows consumers to be able to add items, remove items to the collection. Also there ICollection interface has contains method that ArrayList implements.

You can learn more about ArrayList internal structure by using .Net Reflector. I would like to point out that adding an item, and retrieving an item from an ArrayList as well as other operations are not efficient due to casting. in terms of basic inserting and retrieving you have the same complexity as an array, furthermore you don’t have to reallocate, copy the elements to new ones, ArrayList does it for you. So even though it has many benefits, ArrayList is an inefficient data structure.

if you studied casting or boxing, you can cast anything to an object, which is called boxing, so object is a box and it takes anything, you can put whatever you want in an object. You dont have to worry about the type of what you are putting in an object, however while retrieving, you have to know what to cast to (unbox) the object to, otherwise you will get a casting exception. This operation becomes very expensive, if you cast many items. This is the main reason why ArrayList is inefficient.

List<T>: List is a generic collection type, you will have to define the type of the elements you will be using with the list. List uses array internally. Definition of the list is as follows:

public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable
{
// Fields
private const int _defaultCapacity = 4;
private static readonly T[] _emptyArray;
private T[] _items;
private int _size;
[NonSerialized]
private object _syncRoot;
private int _version;

Generic List Collection uses Array internally as well. By implementing IList<T> interface, it ensures to provide implementation to an indexer, Insert, Remove methods. Moreover, List<T> also implements ICollection<T> interface which ensures to provide implementation to several collection methods like add, remove, count etc.

Just like ArrayList, List<T> also provides several high level methods to insert, remove, sort, search and manipulate the list without knowing what s going on internally. This is a great abstraction and eases the development for programmers. List<T> implements IEnumerable so i can be traversed/enumerated with a foreach loop, it also has index support so you can access List<T> elements by index. You can use Linq queries and Standard Query methods on a List<T>.

Difference between ArrayList and List<T> is that you dont need boxing and unboxing with List<T> since you define the generic type during the initialization of the List. So avoiding casting brings tremendous performance gain especially if you have high number of elements in your collection.

keep in mind that List uses array internally, so again, you will need contiguous memory space to keep the elements together.

LinkedList<T> : Linked Lists are composed of LinkedListNodes. These nodes are basically containers which keeps elements within. here is a definition of a node for singly linked list.

class Node<T>
{

public T Value {set;get;}
public Node<T> NextNode {set;get;}

}

This is the most basic definition of a Node class for a LinkedList. Node contains data and it also contains a pointer to the next node. This Singly Linked List Node is forward only, there is no Previous Node Pointer. You can add a PreviousNode<T> to the Node class and maintain the previous node while building your linked list.

For this text, I will write about Doubly Linked List, because .net Linked List implementation is a doubly linked list and certainly doubly linked list makes life way easier, compared to Singly Linked List.

Linked List nodes are stored in the memory unlike arrays. You wont need contiguous memory space to store Linked List Nodes. Nodes are sparse in the memory. This is good and bad. It s good, so that you won’t need contiguous memory space, and you can use all of the memory. It’s bad, accessing them will require to scan the memory, which might be a little slower compared to accessing an item in the memory by an index.

Linked Lists are very popular and used in many applications. Moreover, you can implement other data structures, using linked lists, such as queue, stack and deque.

There is also circular doubly linked list or circular linked lists. The idea behind circular linked lists are they point to a node (usually head node) in the linked list.

Lets briefly describe insertion, find and delete operations in linked list. To insert an item to a linked list, there are various ways to do it, if you want to just insert an element to the head node, it is constant time O(1), if you like to insert an element to the end of the list it takes O(n) time, linear time, because you will have to find the last element and insert to the end of it. These is for a NON circular linked list, for a circular linked with head and tail nodes, in other words sentinel nodes. I assume that you dont have sentinel nodes, and you just need to add to last.

Deleting a node from linked list takes linear time as well. You need to find the node to be deleted and disconnect it from the linked list.

Searching an element in a linked list takes linear time. You need to visit all the nodes in order to find an element. There is no notion of binary search for linked list data structure.

There are several linked list algorithms and uses. You can check out this post on linked lists and algorithms for linked list.

Linked list is a very simple data structure, you should be able to implement a linked list easily. It is a good practice.

SkipList : I will briefly mention about skip list. Skip list is an amazing list type data structure. Skip list also uses Node<T>, nodes to represent data in containers and like linked list it has pointers, unlike linked list, skip list has many pointers to many arbitrary elements within the list. Skip list needs to keep order, sorted order. One of the important purpose of skip list is to increase searching time. Searching in a skip list takes O(logn), logarithmic time, which is faster than searching a linked list. There is no notion of indexes with skip list.

inserting an element, deleting an element from skip list is also complicated operations. Because you will have to maintain all the pointers, and make sure they wont break.

You can read more about skip list on Wiki.

There is no Skip List Implementation within C#, so you will have to implement it yourself.

Stack<T>: Stack is a first in last out based data structure. It is a very common data structure. Stack is very easy to understand and implement. Stack uses array as the internal data structure. You can also implement a stack using linked list. Both are pretty straight forward to implement.If you use an Array for implementing Stack, you will have to maintain the array as it grows and shrinks. Another data structure which can be used for implementing a stack can be circular buffer, and this can be more efficient than both using an array or linked list.

In C# stack implements ICollection and IEnumerable interfaces, which means you can iterate through stack elements due to IEnumerable interface, moreover, you can use methods of ICollection interfaces such as, Count, CopyTo etc. You can iterate the stack from top to bottom and from bottom to top, if you write a Custom Enumerator, which is very straight forward.

Main operations of Stack are Push, Pop and Peek. While adding an item to stack, you use Push method. While removing an item from the stack, you need to call Pop method. Peek returns the element on top of stack, however, it doesn’t remove the item from the Stack.

Implementing Stack in C# is very straightforward.

Running time, of inserting an item to a stack is O(1), you just insert the item to the location where the current pointer is pointing to. Popping, removing an item from stack also takes O(1), because you just remove the first item on top of stack. If you want to remove any element in the stack it might take up to O(n). Searching an item in a stack is linear time, O(n), as you need to iterate through the whole stack.You can search a Stack by using Contains(T item) method or you can peek all the elements and check equality, either way, you need to iterate through all the elements within Stack.

Stack is a very easy and useful data structure and it is very common. With .Net 4.0 C# has ConcurrentStack<T> which can be used in multi threaded applications. If you want a Thread Safe Stack Implementation, I would highly recommend if you use ConcurrentStack<T> instead of you trying to build your own Stack implementation with locks etc.

Queue<T>: Queue is a commonly used data structure, just like Stack and they are very similar, you can implement a Queueu with Stack and vice versa.

Queue is a First in First Out data structure. First item you insert is removed from Queue, once you remove an item. Imagine a two ended stream, items are entering from one end and leaving from another end in order of insertion.

C# implementation of Queue uses Array internally with a single pointer. Becauase Queue uses array internally and naturally, array will grow as you insert (enqueue) elements to Queue, you will have to maintain array ie: grow and shrink it. There is a grow factor variable used internally for array. This factor indicates how much the array will be growing as you enqueue items.

Queue can be implemented using a linked list or circular buffer as well easily.

Main operations of Queue is enqueue, dequeue, and peek. Enqueue is for inserting an item to the queue. Dequeue is for removing an item from the Queue. Peek is for looking for the item in front of the queue, but not removing it actually.

Asymptotic notation of Queue is very similar to Stack, Enqueue to Queue and Dequeue from Qeueue takes O(1), constant time. You just do the operation to the array element that pointer is pointing to. Peek is as well takes constant time. Searching an element in a Queue is takes linear time. You have to iterate through all the elements, at most, to find a item within Queue, this takes O(n) time.

There are several algorithms and usage of Queue data structure. With .Net 4.0, now there is ConcurrentQueue for thread safe queue operations.

Queue implements IEnumerable, which means, you can iterate through all the elements of the Queue, you can also peek all the elements without removing them.

You can also iterate the Queue from both ends if you write a custom enumerator.

Queue is commonly used within applications.

HashSet: HashSet is very cool data structure and it is very efficient and fast. HashSet contains only unique items, in order words, duplicates are not allowed in hash set. Hash set is due to Set Theory, you can use any operation that a Set in math supports. Such as union, intersection, overlapping, difference etc. This brings lot of value to HashSet.

HashSet is based on Hash values of items. Due to this, hashset resembles HashTable or dictionary.Implementing hash code is very important. Once the hash code is calculated for an item/object, it determines duplicates. If there is a duplicate in the set, you wont be able to insert the object to the hash set. Therefore, you GetHashcode method should be implemented carefully. Moreover, GetHashcode method should be very fast, implementing a slow GetHashcode method might cause performance degration, if your application takes lot of time calculating hashcode. If different objects results in same hashcode, this is called Collision. Collision is HashSet basically fails to insert an element the collection, unlike HashTable.

HashSet uses two arrays Internally as well.One to store the hash values of the elements and one to store the Items/Objects namely :
private Slot<T>[] m_slots;

private int[] m_buckets;

Slot is a value type, Struct, that keeps the elements in. Buckets are where the hashcode and corresponding element resides.

As you would imagine, both of these arrays should be maintained when they need to grow and shrink. Both HashSet and HashTable has to handle this natural cause. Once the hash array and bucket array is full, there are two new arrays are created to store Slots and hash codes, then the next prime number that s bigger than the current array size is calculated. This new prime number is set as the size of new Slot and Hash Code array. Here is the interesting part, hash codes are being recalculated, by finding the remainder by the prime number and Items are being inserted to Slots array correspondingly. Even though this seems to be a costly operation, it is very efficient for a implementing a Set.

In order to add an item to HashSet,you need to use Add(T item) method, which call AddIfNotPresent(T item) method, and does all the operations i just mentioned including adding the item to both of the arrays.

HashSet implements ISet<T> which has public methods as follows :add, ExceptWith, IsProperSubsetOf, IsProperSuperSetOf, IsSubsetOf, IsSupersetOf, Overlaps, SetEquals, UnionWith, SymmetricExceptWith.

Moreover, HashSet implements, IEnumerable which indicates that you can iterate through the HashSet elements.

HashSet also implements ICollection<T> which has methods : Add, Remove, Clear, Contains and Count. So HashSet implements all these methods.

There is much more details to HashSet. Above is just a little summary of HashSet in C#.

The HashSet<T> performs very well for add and search operations. It has O(1) for add in most cases. When the internal capacity must be increased, it is an O(n) operation. Increasing capacity is infrequent. Any search operation (Contains, Remove, and similar operations) are O(1). That’s great. Enumerating the elements in a sorted order forces you to copy the items to a different collection (like a List<T>) and sort the resulting list. You could construct a LINQ query to order the elements, however internally that query will likely use some form of temporary storage to create the sorted sequence. That means every sort will be an expensive operation. Sort is typically an O(n ln n) operation, Also, because the HashSet<T> does not have a sort method, you’ll also have increased memory pressure and time cost to copy the elements.

Enter SortedSet.

SortedSet: Ordering and sorting is a very important topic in Computer Science. There are more then dozen of sorting algorithms and still this day, there is constant development and optimization of sorting algorithms.

SortedSet uses Red-Black Trees internally. Red-Black trees are balanced trees to guarantee logarithmic time for inserting and searching for elements. Red black trees are not easy to implement because you need to maintain the height balance of the tree as well as the colors of the nodes. You can read more about Red-Black trees online. All you need to know for this context is that, elements are being stored internally within SortedSet as sorted and inserting an element to SortedSet is fast, logarithmic time and searching for an element, finding an element takes logarithmic time as well.

Enumerating a sorted set will provide ordered , sorted, elements.

SortedSet also provides all the set methods like union, intersection etc. SortedSet implements ISet so all methods I mentioned above are implemented for SortedSet as well. All these methods are really easy to implement, such as reverse, subset, superset and etc.

I think implementation of red black trees are the hard part for SortedSet.

If you like to check out some code examples, take a look at this link

Circular Buffer : TODO

Heap : TODO

HashTable : TODO


SortedSet : TODO

Dictionary : TODO

Sorted Dictionary : TODO

Tree : TODO

Binary Search Tree : TODO

Graph : TODO

 

 

 

Binary Search Tree Implementation via C#

Categories: Algorithms, Programming
Tags:
Comments: No Comments
Published on: July 10, 2011

Below is my binary search tree implementation (Not self balancing). Binary search trees are very common data structure and being used by many algorithms. Furthermore, binary search trees can be adopted to solve many algorithms, problems and puzzles.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FiratAtagun.DataStructures
{
    public abstract class Node :  IEquatable, IEquatable> where T : IComparable
    {
        public T Value { set; get; }

        protected Node(T value)
        {
            Value = value;
        }

        protected Node()
        {

        }

        public override string ToString()
        {
            return Value.ToString();
        }

        public override int GetHashCode()
        {
            return Value.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            return base.Equals(obj);
        }

        public bool Equals(T other)
        {
            return Value.Equals(other);
        }

        public bool Equals(Node other)
        {
            return Value.Equals(other.Value);
        }

        public static bool operator <(Node left, Node right)
        {
            if(left.Value.CompareTo(right.Value) < 0)
            {
                return true;
            }

            return false;
        }

        public static bool operator >(Node left, Node right)
        {
            if (left.Value.CompareTo(right.Value) > 0)
            {
                return true;
            }

            return false;
        }

    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FiratAtagun.DataStructures
{
    public class TreeNode : Node where T : IComparable
    {

        public TreeNode LeftChild { set; get; }
        public TreeNode RightChild { set; get; }

        public TreeNode()
        {
        }

        public TreeNode(T value): base(value)
        {
        }
    }
}

using System;
using System.Collections.Generic;

namespace FiratAtagun.DataStructures
{
    public class BinaryTree : IEnumerable, IEnumerable> where T: IComparable
    {

        public TreeNode Root { set; get; }

        public BinaryTree()
        {

        }

        public BinaryTree(IEnumerable collection)
        {
            foreach (var item in collection)
            {
                Insert(item);
            }
        }

        public void Insert(T value)
        {
           Insert(new TreeNode(value));
        }

        public void Insert(TreeNode treeNode)
        {
            if (ReferenceEquals(Root, null))
            {
                Root = treeNode;
                return;
            }

            var currentNode = Root;

            var node = treeNode;

            while (true)
            {
                if (node < currentNode)
                {

                    if (ReferenceEquals(currentNode.LeftChild, null))
                    {
                        currentNode.LeftChild = node;
                        break;
                    }
                    currentNode = currentNode.LeftChild;
                    continue;
                }

                if (node > currentNode)
                {

                    if (ReferenceEquals(currentNode.RightChild, null))
                    {
                        currentNode.RightChild = node;
                        break;
                    }
                    currentNode = currentNode.RightChild;
                    continue;
                }
            }
        }

        public void InsertRecursively(T value)
        {
            var node = new TreeNode(value);

            if(ReferenceEquals(Root, null))
            {
                Root = node;
                return;
            }

            var currentNode = Root;

            InsertRecursively(currentNode, node);
        }

        public void InsertRecursively(TreeNode currentNode , TreeNode node)
        {
            if(node < currentNode)
            {
                if(ReferenceEquals(currentNode.LeftChild,null))
                {
                    currentNode.LeftChild = node;
                    return;
                }
                InsertRecursively(currentNode.LeftChild, node);
                return;
            } 

            if(node > currentNode)
            {
                if(ReferenceEquals(currentNode.RightChild, null))
                {
                    currentNode.RightChild = node;
                    return;
                }
                InsertRecursively(currentNode.RightChild, node);
                return;
            }
        }

        public int NumberOfNodes
        {
            get { return NumberOfNodesMethod(); }
        }

        private int NumberOfNodesMethod()
        {
            if(ReferenceEquals(Root,null))
            {
                return 0;
            }

            return NumberOfNodesImpl(Root);
        }

        private static int NumberOfNodesImpl(TreeNode treeNode)
        {
            if(ReferenceEquals(treeNode, null))
            {
                return 0;
            }

            var count = 1 + NumberOfNodesImpl(treeNode.LeftChild) + NumberOfNodesImpl(treeNode.RightChild);

            return count;
        }

        public int Height
        {
            get { return GetHeight() -1; }
        }

        private int GetHeight()
        {
            if(ReferenceEquals(Root, null))
            {
                return 0;
            }

            return GetHeight(Root);
        }

        private static int GetHeight(TreeNode node)
        {
            if(ReferenceEquals(node, null))
            {
                return 0;
            }

            return 1 + Math.Max(GetHeight(node.LeftChild), GetHeight(node.RightChild));
        }

        public void PreOrderTraversal()
        {
            if(ReferenceEquals(Root, null))
            {
                return;
            }

            var currentNode = Root;

            PreOrderTraversal(currentNode);
        }

        public void PreOrderTraversal(TreeNode node)
        {
            if(ReferenceEquals(node, null))
            {
                return;
            }

            Console.WriteLine(node.Value);
            PreOrderTraversal(node.LeftChild);
            PreOrderTraversal(node.RightChild);
        }

        public void InOrderTraversal()
        {
            if(ReferenceEquals(Root, null))
            {
                return;
            }

            InOrderTraversalImpl(Root);
        }

        public void InOrderTraversalImpl(TreeNode node)
        {
            if(ReferenceEquals(node, null))
            {
                return;
            }

            InOrderTraversalImpl(node.LeftChild);
            Console.WriteLine(node.Value);
            InOrderTraversalImpl(node.RightChild);
        }

        public void PostOrderTraversal()
        {
            if(ReferenceEquals(Root,null))
            {
                return;
            }

            PostOrderTraversalImpl(Root);
        }

        public void PostOrderTraversalImpl(TreeNode node)
        {
            if(ReferenceEquals(node, null))
            {
                return;
            }

            PostOrderTraversalImpl(node.LeftChild);
            PostOrderTraversalImpl(node.RightChild);
            Console.WriteLine(node.Value);
        }

        public IEnumerator GetEnumerator()
        {
            throw new NotImplementedException();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }

        IEnumerator> IEnumerable>.GetEnumerator()
        {
            throw new NotImplementedException();
        }
    }
}

LinkedList Notes

Categories: Algorithms, Programming
Tags:
Comments: 2 Comments
Published on: July 7, 2011

LinkedList is a common data structure being used. One of the difference between linked list and array based structures are, linked list doesn’t require contiguous memory space. Moreover, expansion within array based data structures bases on a load factor that s determined by the engineers who build the structures, and expansion of arrays usually twice the size of the current size. During expansion of the array, CLR creates a new array with the new size and then copy all the entities from one array to another. Even though this seems to be a an easy operation, as you data grows, it might become slow. Imagine, your array size becomes 5 million elements, next expansion would require contiguous memory to hold 10 million blocks. So this operation becomes very expensive. Benefit of linked list in the aspect is that, it doesn’t require contiguous memory space, nodes can be anywhere withing the Virtual Memory. Since we keep pointers to the nodes, that is sufficient to access any node which is linked by another node. Therefore the issue we mentioned above doesn’t happen with linked list.

There can be several algorithms and problems based on linked list due to the fact that linked list is convenient for multiple pointer usages, recursion, iteration, reversing etc.
Some of the examples are follows and the best way to practice them is to write code for it after understanding them.

If there is a cycle in a given linked list, you can find it by marking the visited nodes as visited, if you see a visited node again, you halt. This solution requires you to modify the Node structure and add a bolean to it. Another solution would be to have two pointers at the beginning, one that moves one by one node, and another pointer, that moves 2 nodes at a time. And if there is a cycle in the linked list they will meet both pointers will eventually meet.

A way to find out the middle element of a linked list is to use two pointers, one that moves one by one and another that moves two by two. Once the one that moves two nodes at a time reaches to the end, first node comes to the middle of the linked list.

To check if a given linked list is palindrome, divide the list into two parts. Reverse the first part and compare with the second part node by node. If they are equal that, linked list contains a palindrome. There are several different approaches to solve palindrome problem both recursively and iteratively.

Given two singly linked lists in sorted order, which forms a Y shape, you can reverse both of the linked lists and compare each element one by one by keeping two pointers. Once you reach the nodes that don’t intersect. Previous nodes are the intersection points.

Given a sorted singly linked, it s possible to remove the duplicates with a single iteration, by keeping two pointers, one to current node and one to the next node. If the next node is equal to current node, connect the current node to next node’s next node.

Given an unsorted singly linked list, it s possible to remove duplicates by using a dictionary. Store elements in the dictionary as you iterate the list. Each time you move to a node, check the dictionary, if the element is in the dictionary already, that s duplicate. Another way is to sort and do the above algorithm.

Given a linked list of even and odd numbers, you can separate the even numbers from the odd ones as follows. Using two pointers, one to point to the head and another to point to the tail, start iterating from both ends, if first pointer’s node is even and second pointer node is odd then swap them. Otherwise keep moving the pointers until you reach a odd or even number. Then swap them until two pointers overlap.

Given a linked list in which you need to set the last node as the head of the linked list. You traverse the linked list once. Once you reach to the end, you also keep a previous pointer to find the node that will qualify to last node. Last node next pointer will be assigned to the head pointer and then will qualify to be the head node. Tail node will be the second pointer node, whose next pointer will point to null.

Below is an implementation of a linked list that I have quickly written. Syntax hightlighter is not working perfect as you can see. Sorry about that.

using System;
using System.Collections;
using System.Collections.Generic;

namespace FiratAtagun.DataStructureTests.LinkedList
{
    public class Node : IEquatable where T : IComparable
    {
        public Node Next;

        public Node()
        {
        }

        public Node(T data)
        {
            Data = data;
        }

        public Node(Node data)
        {
            Data = data.Data;
        }

        public Node(T data, Node next)
        {
            Data = data;
            Next = next;
        }

        public T Data { set; get; }

        #region IEquatable Members

        public bool Equals(T other)
        {
            return Data.Equals(other);
        }

        #endregion
    }

    public enum InsertionMethod
    {
        Default,
        Recursive,
        Iterative
    }

    public class SinglyLinkedList : ICollection> where T : IComparable
    {
        private int _count;
        private Node _head;
        private Node _iterator;

        public SinglyLinkedList()
        {
        }

        public SinglyLinkedList(T data)
        {
            _head = new Node(data);
        }

        public SinglyLinkedList(Node node)
        {
            _head = node;
        }

        public SinglyLinkedList(IEnumerable collection)
        {
            foreach (T item in collection)
            {
                Insert(item);
            }
        }

        #region ICollection> Members

        public void Add(Node item)
        {
            Insert(item);
        }

        public void Clear()
        {
            _head = null;
        }

        public bool Contains(Node item)
        {
            Node found = Find(item);
            return found != null ? false : true;
        }

        public void CopyTo(Node[] array, int arrayIndex)
        {
            throw new NotImplementedException();
        }

        public int Count
        {
            get { return _count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(Node item)
        {
            return Delete(item);
        }

        public IEnumerator> GetEnumerator()
        {
            _iterator = _head;
            while (_iterator != null)
            {
                yield return _iterator;
                _iterator = _iterator.Next;
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion

        public void Insert(T data, InsertionMethod insertionMethod = InsertionMethod.Default)
        {
            _count++;
            Insert(new Node(data), insertionMethod);
        }

        public void Insert(Node node, InsertionMethod insertionMethod = InsertionMethod.Default)
        {
            if (insertionMethod == InsertionMethod.Default || InsertionMethod.Iterative == insertionMethod)
            {
                InsertIteratively(node);
                return;
            }

            InsertRecursively(node);
        }

        private void InsertRecursively(Node node)
        {
            if (_head == null)
            {
                _head = node;
                return;
            }

            Node currentNode = _head;
            InsertRecursively(node, currentNode, null);
        }

        private void InsertRecursively(Node node, Node currentNode, Node previousNode)
        {
            if (currentNode != null)
            {
                InsertRecursively(node, currentNode.Next, currentNode);
                return;
            }

            currentNode = node;
            previousNode.Next = currentNode;
        }

        private void InsertIteratively(Node node)
        {
            if (_head == null)
            {
                _head = node;
                return;
            }

            Node currentNode = _head;

            while (currentNode.Next != null)
            {
                currentNode = currentNode.Next;
            }

            currentNode.Next = node;
        }

        public bool Delete(Node node)
        {
            return true;
        }

        public Node Find(T element)
        {
            foreach (var item in this)
            {
                if (element.Equals(item.Data))
                    return item;
            }
            return null;
        }

        public Node Find(Node node)
        {
            foreach (var element in this)
            {
                if (node.Data.Equals(element.Data))
                    return element;
            }
            return null;
        }

        public void InsertAfter(T data, Node node)
        {
        }

        public void InsertBefore(T data, Node node)
        {
        }

        public bool Replace(T data, Node node)
        {
            return true;
        }

        public bool Contains(T item)
        {
            return Contains(new Node(item));
        }
    }
}

MinHeap Implementation via C#

Categories: Algorithms, Programming
Tags:
Comments: No Comments
Published on: July 1, 2011

Heap data structure, Binary Heap, is quite useful to keep the min and max access in constant time,O(1). Moreover, Binary heaps can be used to implement priority queues.

Binary heap
implementation is quite easy. Below is the code for MinHeap . I need to add the HeapSort which is an efficient comparison based algorithm that takes O(nlogn) for sorting a sequence, Heap sort can be done in place. Basic idea behind Heap sort is to remove the minimum, then take the right most leaf (which is the last element in the array, due to the nature of this structure, which should be a complete tree) and then call heapify method each time after removing the min, removing n nodes takes O(n) time and for each node, we need to call heapify method which cost O(logn), hence overall running time of this algorithm is O(nlogn).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FiratAtagun.DataStructures.Heap
{
    public class MinHeap : IEnumerable
    {

        private int[] _collection;
        private int _currentCapacity;
        private const int DefaultCapacity = 20;
        private int _index = 0;

        public MinHeap()
        {
            _collection = new int[DefaultCapacity];
            _currentCapacity = DefaultCapacity;
        }

        public int GetParent(int i, out int index)
        {
            double element = i;
            index = (int)Math.Floor((element - 1)  / 2);

            if(index < 0)
            {
                return 0;
            }

            return _collection[index];
        }

        public int GetLeftChild(int i, out int index)
        {
            index = (2 * i) + 1;
            return _collection[index];
        }

        public int GetRightChild(int i, out int index)
        {
            index = (2 * i) + 2;
            return _collection[index];
        }

        public void Insert(int i)
        {
            _collection[_index] = i;

            HeapifyUp(_index);
            _index++;
        }

        private int _currentIndex;

        private void HeapifyUp(int element)
        {
            int parentIndex;

            int parent = GetParent(element, out parentIndex);

            if (_collection[element] < parent)
            {
                Swap(ref _collection[parentIndex], ref _collection[element]);

            }
            else
            {
                return;
            }

            // Swapped, current element is at parentIndex now, and _index is the parent of the element

            HeapifyUp(parentIndex);

        }

        public void Swap(ref int a, ref int b)
        {
            int temp = a;
            a = b;
            b = temp;
        }

        public int Count
        {
            get { return _index - 1; }
        }

        public int Minimum
        {
            get { return _collection[0]; }
        }

        public int ExtractMinimum()
        {
            int minimum = _collection[0];

            _collection[0] = _collection[--_index];
            _collection[_index] = default(int);

            Heapify();

            return minimum;
        }

        public void Heapify()
        {
            _currentIndex = 0;
            Heapify(_currentIndex);
        }

        public void Heapify(int index)
        {

            int leftChildIndex;
            int rightChildIndex;

            int leftChild = GetLeftChild(index, out leftChildIndex);
            int rightChild = GetRightChild(index, out rightChildIndex);

            if(leftChild == 0 && rightChild == 0)
            {
                return;
            }

            int replacingElement = 0;

            if (leftChild < rightChild)
            {
                replacingElement = leftChildIndex;
            }
            if (leftChild > rightChild)
            {
                replacingElement = rightChildIndex;
            }

            if (leftChild == rightChild)
            {
                replacingElement = leftChildIndex;
            }

            Swap(ref _collection[index], ref _collection[replacingElement]);

            Heapify(replacingElement);
        }

        #region IEnumerable Members

        public IEnumerator GetEnumerator()
        {
            foreach (var i in _collection)
            {
                yield return i;
            }
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion
    }
}

Equilibrium index of an array

Categories: Algorithms, Programming
Tags: No Tags
Comments: No Comments
Published on: June 30, 2011

Equilibrium index of an array is an index such that the sum of elements at lower indexes is equal to the sum of elements at higher indexes. For example, in an arrya A:
Median of two sorted arrays

A[0] = -7, A[1] = 1, A[2] = 5, A[3] = 2, A[4] = -4, A[5] = 3, A[6]=0

3 is an equilibrium index, because:
A[0] + A[1] + A[2] = A[4] + A[5] + A[6]

6 is also an equilibrium index, because sum of zero elements is zero, i.e., A[0] + A[1] + A[2] + A[3] + A[4] + A[5]=0

7 is not an equilibrium index, because it is not a valid index of array A.

Write a function int equilibrium(int[] arr, int n); that given a sequence arr[] of size n, returns an equilibrium index (if any) or -1 if no equilibrium indexes exist.

Solution : Iterate through the array and find the sum of all elements, lets call it WholeSum. Then start iterating from left to right, while iterating store the addition of the elements in another variable called left sum. From WholeSum we subtract LeftSum and we get RightSum, if LeftSum is equal to RightSum, that s out Equilibrium index of the array. It takes O(n).

Merge an array of size n into another array of size m+n

Categories: Algorithms, Programming
Tags: No Tags
Comments: No Comments
Published on: June 30, 2011

There are two sorted arrays. First one is of size m+n containing only m elements. Another one is of size n and contains n elements. Merge these two arrays into the first array of size m+n such that the output is sorted.

First array : 2, null, 7, null, null, 10, null
Second Array : 5,8, 12,14

This can be solved as follows: Populate all the numbers of the first array to the end of the first array. Then merge the second array on to the first array, by comparing elements from the first array and second array starting from the beginning.

Reversal algorithm for array rotation

Categories: Algorithms, Programming
Tags:
Comments: No Comments
Published on: June 30, 2011

Given an array 1,2,3,4,5,6,7. You are asked to rotate the array so that output will be 3,4,5,6,7,8,1,2. How to do this? There is a very easy way to get this done.

Question: Write a function rotate(arr[], d, n) that rotates arr[] of size n by d elements.

here is the pseudo code for it.

Reverse first d element,
reverse d+1 to n,
reverse the whole array
and voila.

Below is the code :

        public static void Rotate(int [] arr, int n)
        {
            RecursiveReverse(arr, 0, n-1);
            RecursiveReverse(arr, n, arr.Length-1);
            RecursiveReverse(arr, 0, arr.Length-1);
        }

        public static void RecursiveReverse(int [] arr, int start, int end)
        {
            if(start >= end)
            {
                return;
            }

            var temp = arr[end];
            arr[end] = arr[start];
            arr[start] = temp;

            RecursiveReverse(arr, start + 1, end-1);
        }

Maximum difference between two elements

Categories: Algorithms, Programming
Tags:
Comments: No Comments
Published on: June 30, 2011

Given an array arr[] of integers, find out the difference between any two elements such that larger element appears after the smaller number in arr[].

Examples: If array is [2, 3, 10, 6, 4, 8, 1] then returned value should be 8 (Diff between 10 and 2). If array is [ 7, 9, 5, 6, 3, 2 ] then returned value should be 2 (Diff between 7 and 9)

Obvious solution is using two for loops and checking the difference between every element to every other element which is O(n^2). You will need an additional variable to keep the max difference.

It is important to understand this question such that, you can only go from left to right, so we are not talking about absolute value difference. Therefore, sorting doesnt help.

A better solution is to keep two variables, one to keep the minimum element so far and another to keep the maximum difference so far. This allows a single iteratation over the array and you will have the answer.

Below is the code for it.

        public static void FindMaxDifference()
        {
            var arr = new int[] { 7, 9, 5, 6, 3, 20 };
            int min = arr[0];
            int maxSoFar = arr[1] - arr[0];
            for (int i = 0; i < arr.Length; i++)
            {
                if (arr[i] < min)
                {
                    min = arr[i];
                }
                if (arr[i] - min > maxSoFar)
                {
                    maxSoFar = arr[i] - min;
                }
            }
            Console.WriteLine(maxSoFar);
        }

Leaders in an array

Categories: Algorithms, Programming
Tags:
Comments: No Comments
Published on: June 30, 2011

Write a program to print all the LEADERS in the array. An element is leader if it is greater than all the elements to its right side. And the rightmost element is always a leader. For example int the array {16, 17, 4, 3, 5, 2}, leaders are 17, 5 and 2.

This is a pretty simple algorithm, you need to scan the array from right to left and keep track of the maximum element, whenever you change the maximum, you find a leader, you print that.

        public static void FindLeadersInArray()
        {
            int[] arr = new[] { 16, 17, 4, 3, 5, 2 };

            int maxNow = 0;
            for (int i = arr.Length - 1; i >= 0; i--)
            {
                if(arr[i] > maxNow)
                {
                    maxNow = arr[i];
                    Console.WriteLine(arr[i]);
                }
            }

        }

Sort elements by frequency

Categories: Algorithms, Programming
Tags:
Comments: No Comments
Published on: June 30, 2011

Print the elements of an array in the decreasing frequency if 2 numbers have same frequency then print the one which came 1st
E.g. 2 5 2 8 5 6 8 8 output: 8 8 8 2 2 5 5 6.
There are several approaches to this problem, such as sorting and counting the number of occurrence, sorting can be done in nlogn using quick sort, merge sort. etc. Also , you can use bucket sort for this kind of questions as well.

Below is a method that uses dictionary/hashtable, first, we need to iterate through the input and find the occurrences of all the elements. Then we need to sort the dictionary by value in descending order, which i used linq in the code below.

You can also use a binary search tree, you will need to modify the Node class, and add the count property to it, so if there is a duplicate, you will need to increment the count. Then you can do a inorder traversal to find the sorted sequence in ascending order then you need to reverse that.

        public static void SortByFrequency(int [] arr)
        {
            Dictionary numbersToOccurence = new Dictionary();

            foreach (var  item in arr)
            {
                int res = 0;

                if(numbersToOccurence.TryGetValue(item,out res))
                {
                    numbersToOccurence[item] = ++res;
                }else
                {
                    numbersToOccurence.Add(item, 1);
                }
            }

            var sorted = (from item in numbersToOccurence orderby item.Value descending select item).ToDictionary(kvpair => kvpair.Key, kvpair=>kvpair.Value);

            foreach (var i in sorted)
            {
                Console.WriteLine("Key : {0}, {1}",i.Key, i.Value);
            }

        }
page 1 of 7»

Welcome , today is Tuesday, February 7, 2012

Bad Behavior has blocked 250 access attempts in the last 7 days.