fix(guide): simplify directory structure

This commit is contained in:
Mrugesh Mohapatra
2018-10-16 21:26:13 +05:30
parent f989c28c52
commit da0df12ab7
35752 changed files with 0 additions and 317652 deletions

View File

@ -0,0 +1,39 @@
---
title: Bloom Filter
---
## Description
A Bloom filter is a data structure which is similar to a set. The Bloom filter allows for the question _Is this item a member of the set?_ to be answered quickly. The filter will never return _No_ if the item is in the set; but, it may return _Yes_ if the item is not in the set. This is one downside to using a Bloom filter, there is a chance for false positive results when checking if an item is in the set. An upside to using a Bloom filter is that adding an item to the set and checking if the item is in the set is a constant time [O(n)](https://guide.freecodecamp.org/algorithms/algorithm-performance) operation.
## Example
The following example uses a Bloom filter to create a friend list. The example implementation uses three [hashing functions](https://guide.freecodecamp.org/miscellaneous/hash-tables-and-hashing-functions). The hashing functions ingest a string (a friend name) and calculate a single value for the string based on the number of spots in the Bloom filter.
Create filter as an array of 10 indices. A `0` indicates no item is at that index.
`[0,0,0,0,0,0,0,0,0,0]`
A user adds David to the friend list. The string (`'David'`) is put through several hashing functions which return `0`, `4`, and `8`, respectively. The values from the hashing functions are used to update the filter array at those indices.
The filter indices are updated using those hashed values. A `1` indicates an item has been added at that index.
`[1,0,0,0,1,0,0,0,1,0]`
A user adds Rosie to the friend list. The hashing functions return `3`, `4`, and `6` for `'Rosie'`. The filter indices are updated using the hashed values.
`[1,0,0,1,1,0,1,0,1,0]`
There is a check if Chuck is a member of the friend list. The string `'Chuck'` is put through the hashing functions returning `1`, `3`, and `6`. When the filter array is checked at those indices, it returns `0`, `1`, and `1`. Because one index has a `0` value, Chuck is _definitely_ not a member of the list.
There is a check if Maja is a member of the friend list. The string `'Maja'` is put through the hashing functions, returning `0`, `6`, and `8`. When the filter array is checked at those indices, it returns `1`, `1`, and `1`. Because all three indices have a value of `1`, Maja _may_ already be a member of the list. This is a false positive result.
## Considerations
Bloom filters allow for quick look up to determine if a value is _possibly_ a member of the set or _definitely_ not a member of the set. The more items added to the Bloom filter the rate of false positive results when checking if an item is a member of the set will increase. One way to decrease the rate of false positive results is to increase the size of the array. Although this is a compromise because the larger the array, the greater memory it will occupy. It is necessary to determine an acceptable rate of false positive results for a given array size.
## Further Reading
[Medium's Post Recommendation Algorithm](https://blog.medium.com/what-are-bloom-filters-1ec2a50c68ff)
[Wikipedia on Bloom filters](https://en.wikipedia.org/wiki/Bloom_filter)

View File

@ -0,0 +1,225 @@
---
title: Dictionaries
---
## Dictionaries
Let's assume we have a homogeneous list. We want to count how many times each item occurs in the list. How can we do that, without using Python's built-in methods such as count or Counter from the Python collections module? A Google search for "How to count the occurrences of an item in a list?" will return Stack Overflow answers pointing you to the count method and the collections module, but for learning purposes let's try to solve the problem without using these tools.
Here's the list we'll be working with:
```python
ice_cream = ["strawberry",
"vanilla",
"vanilla",
"chocolate",
"chocolate",
"chocolate",
"banana",
"rum raisin",
"banana"]
```
This code, using nested for loops, produces the right answer, storing the answer in the list "count":
```python
count = []
for flavor in ice_cream:
found = False
for entry in count:
if entry[0] == flavor:
entry[1] += 1
found = True
if not found:
count.append([flavor, 1])
# Print.
for (entry, total) in count:
print (entry, total)
```
Although this code gives the correct answer, there are two things wrong with it. First, it is complex. The more nested loops a program contains, the harder it is to understand, fix, and extend. Moreover, it is inefficient. This may not be a problem in this small example, but imagine a list with thousands or millions of items. Scanning the list of entries each time we make an observation would take a very, very long time, no matter how fast the computer. This is a topic addressed more fully when studying topics such as big O notation and comparing searching and sorting algorithms.
A better answer is to use another data structure known as a **dictionary** or **map**. This data structure is an *unordered, mutable* collection of *key / value* pairs. Think of a dictionary like a phonebook, where the key is the person's name, and the value is the phone number. Keys in a dictionary form a set, meaning they can only appear once, and they cannot be changed (they are immutable), although the values associated with a key can be changed.
Dictionaries are created by putting key/value pairs inside of braces. To get the value associated with a key, you put the key in square brackets.
Here are some code examples:
```python
ice_cream = {'chocolate' : 3, 'strawberry' : 1}
print (ice_cream)
>> {'chocolate' : 3, 'strawberry' : 1}
print (ice_cream['strawberry'])
>> 1
```
To test whether a key is in a dictionary, use k in d:
```python
ice_cream = {'chocolate' : 3, 'strawberry' : 1}
if 'chocolate' in ice_cream:
print ('chocolate is in the list')
...
del ice_cream['chocolate']
if 'chocolate' in ice_cream:
print ('oops: why is chocolate still there?')
```
**Updating and Membership**
To update dictionaries, just assign a value to a key. If the key is already in the dictionary, this changes the value associated with it.
If the key was not present, it is added, along with the value:
```python
ice_cream = {}
ice_cream['chocolate'] = 33
ice_cream['vanilla'] = 999 # oops
print (ice_cream)
>> {'chocolate' : 33, vanilla' : 999}
ice_cream['vanilla'] = 9
print (ice_cream)
>> {'chocolate' : 33, vanilla' : 9}
```
Use *del d[k]*, to remove an entry from a dictionary, where *d* is the dictionary name and *k* is the key being removed. Only entries that are present can be removed; trying to remove one that isnt there causes an error:
```python
ice_cream = {'chocolate' : 33, vanilla' : 9}
del ice_cream['chocolate']
print (ice_cream)
>> {'vanilla' : 9}
del ice_cream['strawberry']
>> Traceback (most recent call last):
File "<stdin>", line 5, in <module>
KeyError: 'strawberry'
```
**Loops**
Since dictionaries are collections (along with lists, tuples, and sets), were going to want to loop over their
contents. We do this with a for loop, which assigns each of the keys in the dictionary to the loop variable in turn:
```python
ice_cream = {'chocolate' : 183,
'vanilla' : 71,
'strawberry' : 63,
'banana', 1}
for flavor in ice_cream:
print (flavor, ice_cream[flavor])
>> 'banana' 1
'vanilla' 71
'chocolate' 183
'strawberry' 63
```
As with set elements, Python loops over the entries in the dictionary in an arbitrary order. There is no guarantee that they will be seen alphabetically or in the order, they were added to the dictionary. Notice, by the way, that looping over dictionaries is slightly different from looping over lists. When Python loops over a list, the values in the list are assigned to the loop variable. When it loops over a dictionary, on the other hand, it assigns the keys. Pythons designers chose to do this because:
- looping over the indices of a list isnt very interesting, since the
program would always get the sequence 0, 1, 2, ...; and
- its a lot easier to go from a dictionary key to the associated value
than it is to take the value and find the associated key.
**Dictionary Methods**
Dictionaries are objects, just like lists, tuples and sets. A few common dictionary methods are:
- *d.clear()* - clear a dictionary
- *d.get(x, 99)* - Returns the value associated with a key, or a default value if the key is not present.
- *d.keys()* - return keys
- *d.items()* - return list of key, value pairs
- *d.values()* - return values as a list, values may not be unique
- *d.update()* - update the dictionary with the contents of another
One common use of items is to loop over the keys and values in a dictionary together:
for (key, value) in dictionary.items():
...do something with the key and value...
This is inefficient for large dictionaries since items() actually constructs a list of (key, value) pairs. A similar method called *iteritems()* hands these pairs back one by one on demand:
for (key, value) in dictionary.iteritems():
...do something with the key and value...
Let's go back to the original example - how do we count the number of items in the ice_cream list using a dictionary?
```python
# Count all the flavors.
ice_cream = ["strawberry",
"vanilla",
"vanilla",
"chocolate",
"chocolate",
"chocolate",
"banana",
"rum raisin",
"banana"]
count = {}
for flavor in ice_cream:
if flavor in count:
count[flavor] = count[flavor] + 1
else:
count[flavor] = 1
# Print.
for b in count:
print (b, count[b])
```
To do this, we create a dictionary that is initially empty. Each time we loop through the ice_cream list, we check
to see whether that flavor is already in the count dictionary. If it is, we add one to its count.
If it isnt, we add the name to the dictionary with the value 1.
We can shorten this program a bit using the method *dict.get()*. This returns either the value associated with a key or some default value that we provide. In this case, we get either the number of times weve already seen a flavor or zero, add one to whichever value the method returns, and store that back in the dictionary:
```python
# Count all the flavors.
count = {}
for flavor in ice_cream:
count[flavor] = count.get(flavor, 0) + 1
# Print.
keys = count.keys()
keys.sort()
for b in keys:
print (b, count[b])
# Print.
for key in sorted(count):
print (key, count[key])
```
Note that we're using two separate ways to print the key and the value: one uses Python's sorted method, and the other does not.
If we wanted to print the flavors in order of frequency, we need to **invert the dictionary**. This means we need to use the values as keys, and the keys as values. Since there is no guarantee that the values are unique, we need to take steps to avoid *collisions*.
The solution is to use some sort of collection, such as a list, to store the inverted dictionarys values. If we go this route, the inverse of the dictionary shown earlier would be {1:[a,b,c]}. Heres a program to do what we want:
```python
ice_cream = ["strawberry",
"vanilla",
"vanilla",
"chocolate",
"chocolate",
"chocolate",
"banana",
"rum raisin",
"banana"]
# Count all the flavors.
count = {}
for flavor in ice_cream:
count[flavor] = count.get(flavor, 0) + 1
# Invert the dictionary.
freq = {}
for (flavor, times) in count.items():
if times in freq:
freq[times].append(flavor)
else:
freq[times] = [flavor]
# Print.
for key in freq:
for flavor in sorted(freq[key]):
print (key,":", " ", flavor)
```
#### More Information:
<!-- Please add any articles you think might be helpful to read before writing the article -->

View File

@ -0,0 +1,57 @@
---
title: Graphs
---
## Graphs
A graph is a data-structure you can use to solve routing problems, such as "Are these two components connected?" and "What is the shortest path from point a to b?"
A graph consists of nodes and edges.
A node (i.e. vertex) is an object in your graph.
A node can contain information such as the name of the node and which edges it is attached to.
An edge is a link that connects two nodes.
The edge can contain information such as the weight of the edge.
If two nodes are connected by an edge, they are neighbours (i.e. adjacent).
Depending on the problem you can use either two-way (undirected) or one-way (directed) edges.
If you have a undirected edge from a to b, there is also a way from b to a.
If you have a directed edge from a to b, there is not necessarily an edge from b to a.
You can use graphs to formulate situations such as:
* Geographical maps
* Each city in your country is a node
* If two cities are connected by a road there is a edge between them
* Roads can be one- or two-way (both directed and undirected edges)
* the weight can be the lenght of the road
* Flow of water
* Each floodgate is a node
* Each canal is an edge
* water will only flow in one direction so the edges are directed
* the weight can be the maximum water capacity of the flow
Example: a graph that has as nodes the capitals of the Nordic countries, and as (undirected) edges the driving distance to cities connected by direct road.
```
. +---------+
. |Reykjavik|
. +---------+
.
.
. 529 km +---------+ 1760 km +--------+
. +------------+|Stockholm|+---------+|Helsinki|
. | +---------+ +--------+
. + +
. +----+ 1991 km |
. |Oslo|+-------------------------------------+
. +----+
. +----------+
. |Copenhagen|
. +----------+
```
<!-- The article goes here, in GitHub-flavored Markdown. Feel free to add YouTube videos, images, and CodePen/JSBin embeds -->
#### More Information:
<!-- Please add any articles you think might be helpful to read before writing the article -->
<a href='https://github.com/freecodecamp/guides/tree/master/src/pages/algorithms/graph-algorithms/breadth-first-search/index.md' target='_blank' rel='nofollow'>Breadth First Search (BFS)</a>
<a href='https://github.com/freecodecamp/guides/tree/master/src/pages/algorithms/graph-algorithms/depth-first-search/index.md' target='_blank' rel='nofollow'>Depth First Search (DFS)</a>

View File

@ -0,0 +1,131 @@
---
title: Hash Tables
---
## Hash Tables
Hash table (or Hash Map) is a data structure that can map keys to values.A hash table uses a hash function to compute an index
into an array of buckets, from which the desired values can be found.Time complexity of a well defined Hash function can be O(1).
A hash table (hash map) is a data structure which implements an associative array abstract data type, a structure that can map keys to values. A hash table uses a hash function to compute an index into an array of buckets or slots, from which the desired value can be found.
![an example of a hash table](https://github.com/TomerPacific/fccGuideImages/blob/master/315px-Hash_table_3_1_1_0_1_0_0_SP.svg.png?raw=true)
Some Important properties of Hash Table -
1) Values are not stored in sorted order.
2) In a hash table, one must also handle potential collisions.
This is often done by chaining, which means to create a linked list of all the values whose keys map to a particular index.
Implementation of Hash Table
A hash table is traditionally implemented with an array of linked lists.
When we want to insert a key/Value pair, we map the key to an index in the array using the hash function.
The value is then inserted into the linked list at that position.
The idea of hashing is to distribute the entries (key/value pairs) across an array of buckets.
Given a key, the algorithm computes an index that suggests where the entry can be found:
```
index = f(key, array_size)
```
Often this is done in two steps:
```
hash = hashfunc(key)
index = hash % array_size
```
In this method, the hash is independent of the array size, and it is then reduced to an index (a number between 0 and array_size 1) using the modulo operator (%).
Let us consider string S. You are required to count the frequency of all the characters in this string.
```
string S = “ababcd”
```
The simplest way to do this is to iterate over all the possible characters and count their frequency one by one.
The time complexity of this approach is O(26*N) where N is the size of the string and there are 26 possible characters.
```
void countFre(string S)
{
for(char c = a;c <= z;++c)
{
int frequency = 0;
for(int i = 0;i < S.length();++i)
if(S[i] == c)
frequency++;
cout << c << << frequency << endl;
}
}
```
Output
```
a 2
b 2
c 1
d 1
e 0
f 0
z 0
```
Let us apply hashing to this problem. Take an array frequency of size 26 and hash the 26 characters with indices of the array by using the hash function.
Then, iterate over the string and increase the value in the frequency at the corresponding index for each character.
The complexity of this approach is O(N) where N is the size of the string.
```
int Frequency[26];
int hashFunc(char c)
{
return (c - a);
}
void countFre(string S)
{
for(int i = 0;i < S.length();++i)
{
int index = hashFunc(S[i]);
Frequency[index]++;
}
for(int i = 0;i < 26;++i)
cout << (char)(i+a) << << Frequency[i] << endl;
}
```
Output
```
a 2
b 2
c 1
d 1
e 0
f 0
z 0
```
### Hash Collisions
When you are using a hash map you have to assume that hash collisions are unavoidable, since you will be using a hash map which is significantly smaller in size than the amount of data you have. The two main approaches to solving these collisions are Chaining and Open Addressing.
#### Chaining
One way you can resolve hash collisions is using chaining. What this means is for each key-value mapping in the hash table, the value field will not hold only one cell of data, but rather a linked list of data. In the example shown in the image below, you can see that Sandra Dee is added as another element to key 152 after John Smith.
![an example of chaining in a hash table](https://github.com/TomerPacific/fccGuideImages/blob/master/620px-Hash_table_5_0_1_1_1_1_0_LL.svg.png?raw=true)
The major setback regarding chaining is the increase in time complexity. This means, that instead of the O(1) properties of a regular hash table, each action will now take greater time as we need to traverse the linked list.
#### Open Addressing
Another way you can resolve hash collisions is using open addressing. In this method once a value is mapped to a key that is already occupied, you move along the adjacent keys of the hash table in a preordained determined fashion, until you find a key with an empty value. In the example shown in the image below, Sandra Dee is mapped to key 153, even though her value is supposed to be mapped to 152.
![an example of open addressing in a hash table](https://github.com/TomerPacific/fccGuideImages/blob/master/380px-Hash_table_5_0_1_1_1_1_0_SP.svg.png?raw=true)
The major setback of open addressing lies in the fact that when needing to look for values, they might not be in the place you expect them to be (the key mapping). Therefore you have to traverse parts of the hash table in order to find the value you are looking for, thus resulting in increased time complexity.
#### Time Complexity
It is very important to note that hash tables have amortised constant complexity i.e. on an average case the complexity will be O(1).
In worst case, If too many elements were hashed into the same key, it can have a time complexity of O(n).
### More Information:
<!-- Please add any articles you think might be helpful to read before writing the article -->
[More Info on Hash Tables - Wiki](https://en.wikipedia.org/wiki/Hash_table)<br>
[Comparison Between Hash Table and STL-map](http://www.geeksforgeeks.org/hash-table-vs-stl-map/)
#### Source
[Basics of Hash Tables - HackerEarth](https://www.hackerearth.com/practice/data-structures/hash-tables/basics-of-hash-tables/tutorial/)

View File

@ -0,0 +1,21 @@
---
title: Data Structures
---
## Data Structures
Data Structure is a way of collecting and organising data in such a way that we can perform operations on these data in an effective way. Data Structures is about rendering data elements in terms of some relationship, for better organization and storage. For example, we have data player's name "Virat" and age 26. Here "Virat" is of String data type and 26 is of integer data type.
We can organize this data as a record like Player record. Now we can collect and store player's records in a file or database as a data structure. For example: "Dhoni" 30, "Gambhir" 31, "Sehwag" 33
In simple language, Data Structures are structures programmed to store ordered data, so that various operations can be performed on it easily. It represents the knowledge of data to be organized in memory. It should be designed and implemented in such a way that it reduces the complexity and increases the effieciency.
<!-- Data Structures in memory-->
In Computer memory i.e RAM, different data structures are created like stack, queue, linklist, heaps, etc according to the requirement of the program so to use the memory efficiently.
#### More Information:
<!-- Please add any articles you think might be helpful to read before writing the article -->
* [Data Structures](http://www.studytonight.com/data-structures/introduction-to-data-structures)
* [Geek for Geek](http://www.geeksforgeeks.org/data-structures/)
* [Tutorials Point](https://www.tutorialspoint.com/data_structures_algorithms/data_structure_overview.htm)
* [Data Structures](http://www.studytonight.com/data-structures/introduction-to-data-structures)

View File

@ -0,0 +1,424 @@
---
title: Linked Lists
---
## Linked Lists
#### A Linked List is a simple *linear-access* data structure.
A linked list is a simple data structure, but it can be used to implement more complicated Data Structures like Queues, Stacks, etc. There are three types of Linked Lists:
1. Simple Linked List
2. Doubly Linked List (or Double Ended Linked List)
3. Circular Linked Lists (Ring Buffer)
Linked List | (Introduction)
Like arrays, Linked List is a linear data structure. Unlike arrays, linked list elements are not stored at contiguous location; the elements are linked using pointers or like in the example using Javascript, a reference to the next node.
If you want to understand Linked Lists, it helps to understand **Arrays**.
To recap, an array is traditionally a **static** **linear** data structure that supports constant time random access. Insertions and Deletions are not always constant time.
Advantages over arrays
1) Dynamic size
2) Ease of insertion/deletion
```
static = size fixed at creation time
linear = stored linearly in memory as a single block
```
#### Arrays have the following disadvantages:-
1. Arrays are static structures and therefore cannot be easily extended or reduced to fit the data set.
2. Arrays are also expensive to maintain new insertions and deletions.
Linked Lists address some of the limitations of arrays. Unlike an array, where all the elements are stored in a contiguous block of memory, in a linked list each element is a separate object and has a **link** to the next element in sequence. This allows a linked list to start with space for only one element, and grow to accomodate an arbitrary number of elements by allocating memory as and when needed.
Deleting elements is also simply handled by manipulating links.
Once you understand the Simple Linked List (which from here on will be referred as **'List'**), you can move on to the Doubly Linked List.
A List as illustrated below is made up of the following components:-
```
head
|
|
+---+---+ +---+---+ +----+------+
| 1 | o----->| 2 | o-----> | 3 | φ |
+---+---+ +---+---+ +----+------+
|
|
tail
```
| Node | Significance |
| ----------|-------------|
| HEAD | Beginning of the List|
| Node(s) | Dynamically allocated self-referential block contain 1 Data element and a link to the next node |
| TAIL | End of the List |
Most common operations available on List are,
1. AddFirst - Inserts an element at the front of the List.
2. AddLast - Inserts an element at the tail of the List.
3. InsertAfter - Inserts an element after an existing element in the List.
4. InsertBefore - Inserts an element before an existing element in the List.
5. Remove - Remove an existing element from the List.
6. Access / Peek - Access an existing element from the List.
7. Size / Count - Returns the number of elements currently present in the List.
8. IsEmpty - Check whether the List is empty or not.
#### Implementation of a Simple Linked List in C++
```cpp
#include<iostream>
using namespace std;
struct Number
{
int num;
struct Number *tail;
};
typedef struct Number N;
class List
{
private:
N *head,*end;
int count;
public:
void display();
void insertBefore(int);
List();
};
List :: List()
{
head=NULL;
end=NULL;
count=0;
}
void List :: insertBefore(int data)
{
N *node;
node= new N;
node->num=data;
node->tail=NULL;
if(!head){
head=end=node;
}
else{
node->tail=head;
head=node;
}
count++;
}
void List :: display()
{
cout<<"Number of nodes in the list = "<<count<<endl;
N *node;
node=head;
while(node)
{
cout<<node->num<<endl;
node=node->tail;
}
}
int main()
{
List l1;
l1.insertBefore(10);
l1.insertBefore(20);
l1.insertBefore(30);
l1.insertBefore(40);
l1.insertBefore(50);
l1.display();
return 0;
}
```
#### OUTPUT
```
Number of nodes in the list = 5
50
40
30
20
10
```
#### Explanation
```cpp
struct Number
{
int num;
struct Number *tail;
};
```
Declaration of a structure(node) with 2 data members
* `num` holds the integer data value
* `*tail` pointer points to the next node in the List
```cpp
class List
{
private:
N *head,*end;
int count;
public:
void display();
void insertBefore(int);
List();
};
```
The List class declares the Linked List.
* `*head` points to the first node in the List
* `*end` points to the last node in the List
* `count` holds the value for number of nodes in the list
* `display()` is used to print the complete list on the console
* `insertBefore()` is used to insert a new node
* `List()` is a defualt constructor
```cpp
List :: List()
{
head=NULL;
end=NULL;
count=0;
}
```
The default constructor is used to initialize the data members of the List class with default values
```cpp
void List :: insertBefore(int data)
{
N *node;
node= new N;
node->num=data;
node->tail=NULL;
if(!head){
head=end=node;
}
else{
node->tail=head;
head=node;
}
count++;
}
```
* A new node is created.
* `num` is assigned the value of `data`.
* `tail` is pointing to Null.
* The `if(!head)` condition is true only when there are no elements in the List.
* When this is the case, `head` and `end` are both pointing to the newly created node.
* Control will move to the `else` section, when there is at least one node in the list.
* In this case, `tail` pointer in the newly created node is made to point to the `head`(first) node.
* The `head` pointer then points to the newly created node to make it the first node in the list.
* `count` is incremented by 1 as each new node is added.
```cpp
void List :: display()
{
N *node;
node=head;
while(node)
{
cout<<node->num<<endl;
node=node->tail;
}
}
```
The display function is used to run through the list and print the total number of nodes and values of `num` on the console.
#### Applications
* Base Data Structure for Vector, Array, Queue, Stack, etc
* Polynomial Representation
* Ring Buffer
Drawbacks:
1) Random access is not allowed. We have to access elements sequentially starting from the first node. So we cannot do binary search with linked lists.
2) Extra memory space for a pointer is required with each element of the list
Types:
1) (Singly) linked lists contain nodes which have a data field as well as a 'next' field, which points to the next node in line of nodes. Operations that can be performed on singly linked lists include insertion, deletion and traversal.
2) (Doubly) In a 'doubly linked list', each node contains, besides the next-node link, a second link field pointing to the 'previous' node in the sequence. The two links may be called 'forward('s') and 'backwards', or 'next' and 'prev'('previous').
Example in Javascript:
```
function LinkedList () {
this.head = null;
this.tail = null;
}
// Node has three properties value, next, prev
function Node (value, next, prev) {
this.value = value;
// A 'pointer' referencing to the next Node (if present) otherwise null
this.next = next;
// A 'pointer' referencing the previous Node, otherwise null
this.prev = prev;
}
LinkedList.prototype.addToHead = function(value) {
let newNode = new Node(value, this.head, null);
if (this.head) this.head.prev = newNode;
else this.tail = newNode;
this.head = newNode;
}
```
Now Execute code
```
let LL = new LinkedList();
LL.addToHead(100);
LL.addToHead(200);
console.log(LL);
```
Representation in C:
A linked list is represented by a pointer to the first node of the linked list. The first node is called head. If the linked list is empty, then value of head is NULL.
Each node in a list consists of at least two parts:
1) data
2) pointer to the next node
In C, we can represent a node using structures. Below is an example of a linked list node with an integer data.
In Java, LinkedList can be represented as a class and a Node as a separate class. The LinkedList class contains a reference of Node class type
```C
// A linked list node
struct Node
{
int data;
struct Node *next;
};
```
# Linked List with three elements
```c
// A simple C program to introduce
// a linked list
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int data;
struct Node *next;
};
// Program to create a simple linked
// list with 3 nodes
int main()
{
struct Node* head = NULL;
struct Node* second = NULL;
struct Node* third = NULL;
// allocate 3 nodes in the heap
head = (struct Node*)malloc(sizeof(struct Node));
second = (struct Node*)malloc(sizeof(struct Node));
third = (struct Node*)malloc(sizeof(struct Node));
/* Three blocks have been allocated dynamically.
We have pointers to these three blocks as first, second and third
head second third
| | |
| | |
+---+-----+ +----+----+ +----+----+
| # | # | | # | # | | # | # |
+---+-----+ +----+----+ +----+----+
# represents any random value.
Data is random because we havent assigned anything yet */
head->data = 1; //assign data in first node
head->next = second; // Link first node with the second node
/* data has been assigned to data part of first block (block
pointed by head). And next pointer of first block points to
second. So they both are linked.
head second third
| | |
| | |
+---+---+ +----+----+ +-----+----+
| 1 | o----->| # | # | | # | # |
+---+---+ +----+----+ +-----+----+
*/
second->data = 2; //assign data to second node
second->next = third; // Link second node with the third node
/* data has been assigned to data part of second block (block pointed by
second). And next pointer of the second block points to third block.
So all three blocks are linked.
head second third
| | |
| | |
+---+---+ +---+---+ +----+----+
| 1 | o----->| 2 | o-----> | # | # |
+---+---+ +---+---+ +----+----+ */
third->data = 3; //assign data to third node
third->next = NULL;
/* data has been assigned to data part of third block (block pointed
by third). And next pointer of the third block is made NULL to indicate
that the linked list is terminated here.
We have the linked list ready.
head
|
|
+---+---+ +---+---+ +----+------+
| 1 | o----->| 2 | o-----> | 3 | NULL |
+---+---+ +---+---+ +----+------+
Note that only head is sufficient to represent the whole list. We can
traverse the complete list by following next pointers. */
return 0;
}
```
#### More Information:
* <a href='http://www.geeksforgeeks.org/linked-list-set-1-introduction/' target='_blank' rel='nofollow'>Introduction to Linked Lists</a>
* <a href='https://www.youtube.com/watch?v=njTh_OwMljA' target='_blank' rel='nofollow'>Linked Lists (YouTube video)</a>

View File

@ -0,0 +1,81 @@
---
title: Queues
---
## Queues
Queue is a First In First Out (FIFO) Data Structure. Many algorithms use Queues at their core for improving performance.
Queue is one of the fundamental Abstract Data Types (ADT). It is similar to queues we have in movies or supermarkets. The first person to arrive will be served first right? Similarly, the first element to be inserted will be removed first. There are several types of queues such as,
1. Simple Queue (or Queue)
2. Circular Queue
3. Priority Queue
4. Dequeue (Double Ended Queue)
If you can understand the simple queue (which from here on will be referred as 'Queue') then all the others are just as easy, with little modifications.
Most common operations available on queue are,
1. Add / Offer - Inserts an element into the end of the queue.
2. Remove / Poll - Remove an element from the beginning of the queue.
3. Peek - Returns element at the beginning of the queue but will not remove it.
4. Size / Count - Returns the number of elements currently present in the queue.
5. IsEmpty - Check whether the queue is empty or not.
Implementation of a queue is possible using either arrays or linked lists. The following is a simple array implementation of the queue data structure with its most common operations.
```JavaScript
var Queue = function() {
var queue = [];
var front = 0;
var back = 0;
return {
isEmpty: function() {
return front >= back || queue.length === 0;
},
add: function(elem) {
/* You can also do queue.push(elem) in JavaScript.
This is how they do it in other languages */
queue[back++] = elem;
},
remove: function() {
if (!this.isEmpty()) {
return queue[front++]; // or queue.shift()
}
else {
throw new Error("Queue is Empty.");
}
},
peek: function() {
if (!this.isEmpty()) {
return queue[front];
}
}
}
};
var queue = new Queue();
console.log(queue.isEmpty()); // true
queue.add(1);
queue.add(2);
console.log(queue.remove()); // 1
console.log(queue.peek()); // 2
console.log(queue.remove()); // 2
console.log(queue.remove()); // exception
```
#### Applications
* Simulation
* Scheduling (Job Scheduling, Disk Scheduling)
* Shared Resource Management
* Keyboard Buffer
* Breadth First Search
* To handle congestion in network
#### More Information:
* <a href='http://www.geeksforgeeks.org/queue-data-structure/' target='_blank' rel='nofollow'>More Info on Queues - GeeksForGeeks</a>
* <a href='https://www.hackerrank.com/domains/data-structures/queues' target='_blank' rel='nofollow'>Solve Challenges using Queues - Hackerrank</a>
* <a href="https://www.youtube.com/watch?v=wjI1WNcIntg" target ="_blank" rel="nofollow">HackerRank Stacks and Queues Video</a>

View File

@ -0,0 +1,114 @@
---
title: Stacks
---
## Stacks
A stack is a First In Last Out (FILO) or Last In First Out (LIFO) Data Structure. It is a linear data structure.
You can imagine a stack as the way plates were organized in buffet restaurant. You can only pick the plate at the top otherwise the stack will collapse. Generally, the last item to be inserted will be removed first.
Some basics operations of stack are:
1. Push - Inserts an item at the top of the stack.
2. Pop - Removes an item at the top of the stack.
3. isEmpty - Check whether the stack is empty or not
4. Size - Return the number of items in the stack
(All the operations can be done in O(1) time)
Implementation of a stack is possible using either arrays or linked lists. The following is a simple array implementation of the stack data structure with its most common operations.
```C++
//Stack implementation using array in C++
//You can also include<stack> and then use the C++ STL Library stack class.
#include <bits/stdc++.h>
using namespace std;
class Stack {
int t;
int arr[MaxN];
public:
Stack() {
t = 0;
}
int size() {
return t;
}
bool isEmpty() {
return t < 1;
}
int top() {
return arr[t];
}
void push(int x) {
if (++t >= MaxN) {
cout << "Stack is full" << '\n';
return;
}
arr[t] = x;
}
void pop() {
arr[t--] = 0;
}
};
int main() {
Stack st;
st.push(4);
st.push(3);
st.push(5);
while (!st.isEmpty()) {
cout << st.size() << ' ' << st.top() << '\n';
st.pop();
}
return 0;
}
```
#### Using Arrays as Stacks
In some programming languages an array has stack functionality, allowing the developer to perform **push** and **pop** operations without the need for a custom stack data structure.
For example, an array in JavaScript has **push** and **pop** methods allowing one to easily implement stack functionality in an application.
```js
stack = [];
let i = 0;
while(i < 5)
stack.push(i++);
while(stack.length) {
stack.pop();
}
```
A List in Python can also perform stack functionality in an application. Instead of **push**, one can use the **append** method.
```python
stack = []
for i in range(5):
stack.append(i)
while len(stack):
stack.pop()
```
#### Applications
* Turn recursion into loop.
* Redo-Undo features.
* Sudoku solver
* Depth First Search.
* Tree traversals
* Infix expression -> Prefix/Postfix expression
* Valid Parentheses
#### More Information:
* [More Info on Stacks - GeeksForGeeks](http://www.geeksforgeeks.org/stack-data-structure/)
* [Stack - Wikipedia](https://en.wikipedia.org/wiki/Stack_(abstract_data_type)
* [Tower of Hanoi Problem and how the solution uses stacks and recursions](https://en.wikipedia.org/wiki/Tower_of_Hanoi)
* [HackerRank Stacks and Queues Video](https://www.youtube.com/watch?v=wjI1WNcIntg)

View File

@ -0,0 +1,97 @@
---
title: Trees
---
# Trees
A tree data structure can be defined recursively (locally) as a collection of nodes (starting at a root node), where each node is a data structure consisting of a value, together with a list of references to nodes (the "children"), with the constraints that no reference is duplicated, and none points to the root. A tree with no nodes is called a null or empty tree.
A binary tree is a non linear data structure consisting nodes, where each node has the following 3 components:
**Data element**: Stores any kind of data in the node
**Left pointer**: Points to the sub-tree on the left side of node
**Right pointer**: Points to the sub-tree on the right side of the node
As the name suggests, the data element stores any kind of data in the node.
The left and right pointers point to binary trees on the left and right side of the node respectively.
If a tree is empty, it is represented by a null pointer.
## Terminology used in trees:
**Root** :
The top node in a tree.
**Child**:
A node directly connected to another node when moving away from the Root.
**Parent**:
The converse notion of a child.
**Siblings**:
A group of nodes with the same parent.
**Descendant**:
A node reachable by repeated proceeding from parent to child.
**Ancestor**:
A node reachable by repeated proceeding from child to parent.
**Branch**(internal node):
A node of a tree that has child nodes.
**Leaf**(less commonly called External node):
A node with no children.
**Degree**:
The number of subtrees of a node.
**Edge**:
The connection between one node and another.
**Path**:
A sequence of nodes and edges connecting a node with a descendant.
**Level**:
The level of a node is defined by 1 + (the number of connections between the node and the root).
**Height of tree**:
The height of a tree is the height of its root node.
**Depth**:
The depth of a node is the number of edges from the tree's root node to the node.
**Forest**:
A forest is a set of n ≥ 0 disjoint trees.
### Some Popular Types of Trees:
* Binary Tree
* Binary Search Tree
* AVL Tree
* Red Black Tree
* Splay Tree
* Huffmann Tree
### Common uses
* Representing hierarchical data
* Storing data in a way that makes it easily searchable
* Representing sorted lists of data
* Routing algorithms
### Code of a tree node
``` c++
struct node
{
int data; //Data element
struct node * left; //Pointer to left node
struct node * right; //Pointer to right node
};
```
#### More Information:
* [CMU lesson notes](http://www.cs.cmu.edu/~clo/www/CMU/DataStructures/Lessons/lesson4_1.htm)
* [Wikipedia](https://en.wikipedia.org/wiki/Tree_(data_structure))