#### Mindset

Bad programmers worry about the code. Good programmers worry about Data structures and their Relationships.

Computer Programming is all about Data Structures and Algorithms. Computer science legend Donald Knuth once said **I don't understand things unless I try to program them.** I also believe that the best way to learn an algorithm is to program it. Algorithms and Data structures (I'm deliberately using the Term 'Algorithms' before the 'Data Structures') are essential for any Computer Programmer. As a beginner, one may feel discouraged and frustrated by these concepts. The terms algorithms and data structures both sound abstract and obscure. The reason you feel that way is that you haven't found the right method to let you study the subject deliberately. I'm going to tell you about my roadmap and tips. Be patient, and always keep moving forward.

#### Don't be intimidated by mathematics

Data structures and algorithms do involve some mathematical reasoning and proofs, particularly when analyzing the time- and space-complexity of an algorithm. Being able to perform a big-O complexity analysis is certainly important, but you don't need to worry about it too much to start with. You don't need a high IQ or abstract mathematical knowledge. As long as you understand high school mathematics, you have the tools needed to understand data structures and algorithms.

#### Algorithm

Algorithms are everywhere. Algorithms are also used heavily in Data Science. An algorithm for a particular task can be defined as "a finite sequence of instructions, each of which has a clear meaning and can be performed with a finite amount of effort in a finite length of time". As such, an algorithm must be precise enough to be understood by human beings. However, in order to be executed by a computer, we will generally need a program that is written in a rigorous formal language; and since computers are quite inflexible compared to the human mind, programs usually need to contain more details than algorithms.

Algorithms can obviously be described in plain English, and we will sometimes do that. However, for computer scientists it is usually easier and clearer to use something that comes somewhere in between formatted English and computer program code, but is not runnable because certain details are omitted. This is called **pseudocode**, which comes in a variety of forms.

#### Fundamental questions about algorithms

Given an algorithm to solve a particular problem, we are naturally led to ask:
**1. **What is it supposed to do?
**2. **Does it really do what it is supposed to do?
**3. **How efficiently does it do it?

The technical terms normally used for these three aspects are:
**1. **Specification.
**2. **Verification.
**3. **Performance analysis.

The details of these three aspects will usually be rather problem dependent.

The **specification** should formalize the crucial details of the problem that the algorithm is intended to solve. Sometimes that will be based on a particular representation of the associated data, and sometimes it will be presented more abstractly

For simple problems, it is often easy to see that a particular algorithm will always work, i.e. that it satisfies its specification. However, for more complicated specifications and/or algorithms, the fact that an algorithm satisfies its specification may not be obvious at all. In this case, we need to spend some effort **verifying** whether the algorithm is indeed correct. *In general, testing on a few particular inputs can be enough to show that the algorithm is incorrect.* However, since the number of different potential inputs for most algorithms is infinite in theory, and huge in practice, more than just testing on particular cases is needed to be sure that the algorithm satisfies its specification. **Formal verification techniques** are complex and will normally be left till after the basic ideas of these notes have been studied.

Finally, the **efficiency or performance** of an algorithm relates to the resources required by it, such as how quickly it will run, or how much computer memory it will use. This will usually depend on the problem instance size, the choice of data representation, and the details of the algorithm.

#### Data Structure

For many problems, the ability to formulate an efficient algorithm depends on being able to organize the data in an appropriate manner. The term data structure is used to denote a particular way of organizing data for particular types of operation.

**Generally speaking, a data structure is a way to organize data, while an algorithm is a method or pattern for solving problems.**

Often we want to talk about data structures without having to worry about all the implementational details associated with particular programming languages, or how the data is stored in computer memory. We can do this by formulating abstract mathematical models of particular classes of data structures or data types which have common features. These are called **abstract data types**, and are defined only by the operations that may be performed on them. Typically, we specify how they are built out of more **primitive data types** (e.g., integers or strings), how to extract that data from them, and some basic checks to control the flow of processing in algorithms. The idea that the implementational details are hidden from the user and protected from outside access is known as **encapsulation**