My understanding on data structures and algorithms goes mainly to the three books that I read as a beginner and continue to consult the books whenever I need guidance.
- Data Structures Using C by Aaron M. Tenenbaum
- Data Structures, Algorithms, and Program Style Using C by James F. Korsh
- Data Structures and Algorithms with Object-Oriented Design Patterns in C++ by Bruno R. Preiss
Technology changes quickly and new languages keep surfacing while old ones become obsolete. However, the basic knowledge I captured on data structures and algorithms through these books is what I can rely on for other languages as well since the fundamentals remain the same.
Seniors, peers and my online community of programmers have helped me during my career. Without their help and guidance, I wouldn’t have been able to resolve half the practical problems that I faced while programming. Working as a Web Developer for an IT company called “The Academics”, I have used C# as my programming language.
I learnt about different data types such as boolean, integer types (short, signed and unsigned integer, long, etc.), floating point types (float, single, double, long double, etc.) string types (string, char), etc., with each language having its own version of data types but the classification is more or less on similar lines. One of the important things I learnt is to understand how much memory each data type occupies in whatever language you are working with and when and how to use them in your programming. My first lesson on data types was when I used an integer value where a long was required. So for all future programs, I always used a higher data value than required that is using long instead of integer. One of my seniors pointed out how that hogged up the memory unnecessarily and why it is essential to understand and consider the most appropriate data type rather than using the minimum sized or maximum sized data type.
I frequently used data structures to temporarily store sets of data together to be able to access them with a single variable and perform operations on them. Arrays, linked lists, stacks, queues, hash tables are common examples in many languages while ArrayList, HashSet, Dictionary have been new in C#. Using various algorithms, one can manipulate the data contained in these data structures. Some examples are searching the data, sorting them, etc.
Arrays are the simplest and most commonly used data structure in almost all languages. In C#, an array is a list of objects of the same type and fixed length. List, on the other hand, is a dynamic array whose length can be varied as required. The object type needs to remain the same however. ArrayList goes a step further – it is a dynamic array whose length can be varied as required, and it also supports storing of different types of objects in the same ArrayList. Due to this, there is need of casting the retrieved values back to their original type before they could be used.
LinkedList also stores series of objects; however, instead of indexing the list, each object is linked to each other i.e. each object has a reference each to the next object and previous object. Dictionary data structure allows making the index keys which can be of any type of object unlike ArrayList, for example, which automatically makes sequential integer keys. Thus, keys can actually be meaningful and link it to the object for easy retrieval. Hashtables are similar to Dictionary except that the keys are generic objects rather than typed which makes it faster than Dictionary data structure. A new data structure introduced in latest C# versions is HashSet which is similar to List data structure except that it does not allow duplicate values.
Stack data structure is similar to ArrayList but works on the Last-In-First-Out (LIFO) behavior and is particularly useful when it is required to “retrace your steps”. Queue, on the other hand, is based on First-In-First-Out (FIFO). This can be used when, for example, you want to serve clients on the basis of who came first.
The typical operations include adding or removing data, retrieving data, manipulating data, displaying in a particular format, sorting data, etc.
A common algorithm for sorting arrays is bubblesort method based on swapping. One variable is compared with the other and their places are switched with the help of a temporary variable. C# also provides a Sort function for Arrays to sort the list directly. The most efficient method, however, is to use the interface IComparable and the function CompareTo to compare the objects and sort accordingly.
The source files in C language are usually given the extension “.c” and “.h”, one for the source file and the other for the header files. For C++, the files use the “.cpp” extension and “.h” for the declaration or header files. While file organization has no significance to the C# compiler i.e. an entire project could be merged into one.cs file and it would still compile (except for preprocessor statements). However, it makes sense to have one type in one file making the filename matching the name of the class and the file’s directory matching the name of the class’s namespace.
In C#, the abstract class Stream forms the parent class for performing file operations and processing and it is comes under the System.IO namespace. With the help of this abstract class, one can store data to a stream or retrieve data from a stream. Stream class acts as the parent class for inherited classes which consists of the actual implementation to carry out the necessary operations. Typical stream operations usually require a combination of classes, for example, some classes are used to create a stream object, some others to write data back to the stream, and another set to read the data from the stream.
One such stream is file streaming that consists of performing one of the routine operations on a file, such as creating, opening, editing, appending, etc. A basic class to help with the file creation and opening is FileStream. A FileStream object is used to get a stream ready for reading, writing, and other processing. Another class, BinaryWriter class is used to write values of primitive data types such as int and float in C#. TextWriter is another abstract class for writing data to the streams. StreamWriter, derived from TextWriter is used to write a character to a stream. Similarly, TextReader is an abstract class and StreamReader is derived from that class and is used to perform reading operations from a stream.