# Graphs and Trees

### Algorithms for Interviews

slides.com/bgando/intro-graph-trees

## EXERCISES

### Common Interview DS

DS Common Uses FEM Course
Arrays & Strings ordered data, words Part 2
Hash Tables optimization Part 2
Linked Lists data insert/delete Part 2
Stacks/Queues creative aux DS Part 2
Graphs complex relationships Part 3 (this one)
Trees hierarchical data Part 4 (this one)

### What will we cover today?

Trees

Graphs

Binary Search Trees

### How to be effective

Rule #1 don't aim to memorize, this will not help!

Rule #3 practice with a timer, speed matters

Rule #3.5 actually practice, reading doesn't count

Rule #4 communicate and be nice

Array

Stack

Queue

### Linear Data Structures

Array

Insert at end:

Insert at beginning:

Insert (generally):

Remove from end:

Remove from beginning:

Remove (generally):

Find value:

Access value:

### Linear Data Structures

Array

Insert at end: O(1)

Insert at beginning: O(n)

Insert (generally): O(n)

Remove from end: O(1)

Remove from beginning: O(n)

Remove (generally): O(n)

Find value: O(n)

Access value: O(1)

### Linear Data Structures

Insert at end:

Insert at beginning:

Insert (generally):

Remove from end:

Remove from beginning:

Remove (generally):

Find value:

Access value:

### Linear Data Structures

Insert at end: O(1)

Insert at beginning: O(1)

Insert (generally): O(1)

Remove from end: O(1)

Remove from beginning: O(1)

Remove (generally): O(1)

Find value: O(n)

Access value: O(n)

### Linear Data Structures

Stack

Insert at end:

Insert at beginning:

Insert (generally):

Remove from end:

Remove from beginning:

Remove (generally):

Find value:

Access value:

### Linear Data Structures

Stack

Insert at end: O(1)

Insert at beginning: N/A

Insert (generally): O(1)

Remove from end: O(1)

Remove from beginning: N/A

Remove (generally): O(1)

Find value: O(n)

Access value: O(n)

### Linear Data Structures

Queue

Insert at end:

Insert at beginning:

Insert (generally):

Remove from end:

Remove from beginning:

Remove (generally):

Find value:

Access value:

### Linear Data Structures

Queue

Insert at end: N/A

Insert at beginning: O(n) or O(1)

Insert (generally): O(1) with linked list

Remove from end: O(1)

Remove from beginning: N/A

Remove (generally): O(1)

Find value: O(n)

Access value: O(n)

### Linear Data Structures

Array

Stack

Queue

LINEAR DATA STRUCTURE NON-LINEAR DATA STRUCTURE
Overview arranged in an orderly manner where the elements are attached adjacently arranged with multiple relationships and properties to describe them
Traversing can be accessed in one time (single run) traversing is best handled recursively
Ease of implementation simpler complex
Levels involved single level multiple level
Examples array, queue, stack, linked list, etc. tree and graph

# Anyone have a morning routine?

### Create a data structure to model a chat-bot that helps you decide what to eat for breakfast by asking yes or no questions.

``````{
question: 'Do you feel like cooking?',
yes: <question>,
no: <question>
}
``````

1. create a data structure

2. model a chat-bot that

3. helps you decide what to eat for breakfast

4. by asking yes or no questions.

?

Yes

No

Recommendation

``````{
question: 'Do you feel like cooking?',
yes: <question>,
no: <question>
}

{
question: 'Do you have milk?',
yes: <question>,
no: <question>
}
``````

1. create a data structure

2. model a chat-bot that

3. helps you decide what to eat for breakfast

4. by asking yes or no questions.

Yes

No

Recommendation

``````{
question: 'Do you feel like cooking?',
yes: <question>,
no: <question>
}

{
question: 'Do you have milk?',
yes: <question>,
no: <question>
}

{
question: 'Do you have toast?',
yes: <question>,
no: <question>,
recommendation: 'You should make toast for breakfast!'
}``````

1. create a data structure

2. model a chat-bot that

3. helps you decide what to eat for breakfast

4. by asking yes or no questions.

Yes

No

Recommendation

``````const chatBot = {
question: 'Do you feel like cooking?',
yes: {
question: 'Do you have milk?',
yes: <question>,
no: <question>
},
no: {
question: 'Do you have toast?',
yes: <question>,
no: <question>
}
}

``````

1. create a data structure

2. model a chat-bot that

3. helps you decide what to eat for breakfast

4. by asking yes or no questions.

?

Yes

No

Recommendation

### Trees - Terminology

eat toast!

eat toast!

The DOM is a tree.

Parsers use trees to model the structure of code

Autocomplete features use a special kind of tree called a trie.

### Non-Linear to Linear?

``````const chatBot = {
question: 'Do you feel like cooking?',
yes: {
question: 'Do you have milk?',
yes: <question>,
no: <question>
},
no: {
question: 'Do you have toast?',
yes: <question>,
no: <question>
}
}

``````
``````const mother = { name: 'Ashleigh' };
const son = { name: 'Sammy' };
const daughter = { name: 'Alex' };

``````

### Family Trees

``````const mother = { name: 'Ashleigh' };
const son = { name: 'Sammy' };
const daughter = { name: 'Alex' };

const mother = {
name: 'Ashleigh',
children: [son, daughter]
};``````

### Family Trees

``````/** Class representing a Tree. */

class Tree {

constructor(value) {

}
/*
* Adds a new value as a child of the tree
* @param {*} value the value to add
*/
insertChild(value) {

}

/*
* Removes a value from the tree
* @param {*} value the value to remove
*/
removeChild(value) {

}
}

const myTree = new BinaryTree();

console.log(myTree)``````

# EXERCISE

Insert: O(1)

Remove: ??

Traverse: ??

``````class Tree {
constructor(value) {
this.value = value;
this.children = [];
}

insertChild(value) {
const newTree = new Tree(value);
this.children.push(newTree);
return newTree;
}

removeChild(value) {
// ??
}
}``````

# chat-bot recommendations.

``````const chatBot = {
question: 'Do you feel like cooking?',
yes: {
question: 'Do you have milk?',
yes: <question>,
no: <question>
},
no: {
question: 'Do you have toast?',
yes: <question>,
no: <question>
}
}

``````

Q1

Q2

Q3

``````const chatBot = {
question: 'Do you feel like cooking?',
yes: {
question: 'Do you have milk?',
yes: <question>,
no: <question>
},
no: {
question: 'Do you have toast?',
yes: <question>,
no: <question>
}
}

``````

Q1

Q2

Q3

Leaf nodes are the recommendations!

### Binary Trees - Traversals

Preorder: Node, then children (starting left)

Q1

Q2

Q3

Q1

Q2

Q3

``````function traverse(tree) {

...

}``````
``````const mother = { name: 'Ashleigh' };
const son = { name: 'Sammy' };
const daughter = { name: 'Alex' };

const mother = {
name: 'Ashleigh',
children: [son, daughter]
};``````
``````function traverse(tree) {

...

}``````
``````const family = {
name: 'Ashleigh',
children: [{
name: 'Sammy',
children: [{
name: 'Bowser',
children: [{ name: 'P' }],
}],
},
{ name: 'Alex' }]
};
``````
``````/** Class representing a Binary Tree. */

class BinaryTree {

constructor(value) {
}
/*
* Explores all the nodes in the tree
*/
traverse() {
}

/*
* Returns true if value is found
*/
contains(value) {
}
}

const myTree = new BinaryTree();

console.log(myTree)``````
```                                Fixed Operations
contains(val), size(tree), traverse(tree)

Dynamic Operations
insert(x, y), remove(node),
reOrder(x, y)

```

# EXERCISE

``````function traverse(tree) {
console.log(tree.name);
tree.children.forEach((child)=> {
traverse(child);
});
}``````
``````// if node is null, return 0.
// elseIf yes and no child nodes are null, return 1
// else recursively calculate
// Leaf count of left subtree +
// Leaf count of right subtree

function countReccos(tree) {
console.log(tree.name);
tree.children.forEach((child)=> {
traverse(child);
});
}``````

Insert:

Remove:

Traverse:

countReccos:

Preorder: Node, then children (starting left)

Inorder: Left child recursively, Node, Right child

Postorder: Children recursively, then Node
+

Q1

Q2

Q3

Q1

Q2

Q3

Q3

Q2

Q1

Q3

Q2

Q1

### Binary Trees - Traversals

``````
// left, root, right
function inOrder(node, func = console.log) {
if (node.left) {
node.left.inOrder(func);
}

func(node);

if (node.right) {
node.right.inOrder(func);
}
}``````
``````
// root, left, right
function preOrder(node, func = console.log) {
func(node);

if (node.left) {
node.left.preOrder(func);
}

if (node.right) {
node.right.preOrder(func);
}
}``````
``````// left, right, root
function postOrder(node, func = console.log) {
if (node.left) {
node.left.postOrder(func);
}

if (node.right) {
node.right.postOrder(func);
}

func(node);
}``````

No

Do you want toast?

No!

...?

# Draw it!

Consider the breakfast foods of myself and my friends. How could you represent this as a graph?

A   −   B,

A   −  C,

A   −   E,

B    −   D,

C   −    D,

C .   −   E.

A   −   B,

A   −  C,

A   −   E,

B    −   D,

C   −    D,

C .   −   E.

A   −   B,

A   −  C,

A   −   E,

B    −   D,

C   −    D,

C .   −   E.

A   −   B,

A   −  C,

A   −   E,

B    −   D,

C   −    D,

C .   −   E.

A   −   B,

A   −  C,

A   −   E,

B    −   D,

C   −    D,

C .   −   E.

A   −   B,

A   −  C,

A   −   E,

B    −   D,

C   −    D,

C .   −   E.

A   −   B,

A   −  C,

A   −   E,

B    −   D,

C   −    D,

C .   −   E.

### Graph Implementation

Let's create a data structure to model a better breakfast recommendation engine!

Aren't you so excited?

### First Step

What data needs to be stored?

What data needs to be stored?

1

4

3

2

5

### First Step

Vertices

Vertices

Edges

Vertices

Vertices

Edges

`````` [[0,1,0,0,1],
[1,0,1,1,1],
[0,1,0,1,0],
[0,1,1,0,1],
[1,1,0,1,0]];``````
``````

Vertices

Vertices

Edges

`````` [[0,1,0,0,1],
[1,0,1,1,1],
[0,1,0,1,0],
[0,1,1,0,1],
[1,1,0,1,0]];``````
``````function addEdge(v1, v2) {
}

Vertices

Vertices

Edges

`````` [[0,1,0,0,1],
[1,0,1,1,1],
[0,1,0,1,0],
[0,1,1,0,1],
[1,1,0,1,0]];``````
``````function addEdge(v1, v2) {
}

removeEdge(v1,v2)``````

Vertices

Vertices

Edges

`````` [[0,1,0,0,1],
[1,0,1,1,1],
[0,1,0,1,0],
[0,1,1,0,1],
[1,1,0,1,0]];``````
``````function addEdge(v1, v2) {
}

function removeEdge(v1, v2) {
}

removeEdge(v1,v2)``````

Vertices

Vertices

Edges

`````` [[0,1,0,0,1],
[1,0,1,1,1],
[0,1,0,1,0],
[0,1,1,0,1],
[1,1,0,1,0]];``````
``````function addEdge(v1, v2) {
}

function removeEdge(v1, v2) {
}

removeEdge(v1,v2)``````

### Time Complexity?

Vertices

Vertices

Edges

`````` [[0,1,0,0,1],
[1,0,1,1,1],
[0,1,0,1,0],
[0,1,1,0,1],
[1,1,0,1,0]];``````

Vertices

Edges

``````

``````
``````const adjList = {
1:[2,5],
2:[1,5,3,4],
3:[2,4],
4:[2,5,3],
5:[4,1,2]
}``````

Vertices

Edges

``````function addEdge(v1, v2) {
}

``````
``````const adjList = {
1:[2,5],
2:[1,5,3,4],
3:[2,4],
4:[2,5,3],
5:[4,1,2]
}``````

Vertices

Edges

``````function addEdge(v1, v2) {
}

removeEdge(v1,v2)``````
``````const adjList = {
1:[2,5],
2:[1,5,3,4],
3:[2,4],
4:[2,5,3],
5:[4,1,2]
}``````

Vertices

Edges

``````function addEdge(v1, v2) {
}

function removeEdge(v1, v2) {
}

removeEdge(v1,v2)``````
``````const adjList = {
1:[2,5],
2:[1,5,3,4],
3:[2,4],
4:[2,5,3],
5:[4,1,2]
}``````

Vertices

Edges

``````function addEdge(v1, v2) {
}

function removeEdge(v1, v2) {
}

removeEdge(v1,v2)``````
``````const adjList = {
1:[2,5],
2:[1,5,3,4],
3:[2,4],
4:[2,5,3],
5:[4,1,2]
}``````

Vertices

### Time Complexity?

Edges

``````function addEdge(v1, v2) {
}

function removeEdge(v1, v2) {
}

removeEdge(v1,v2)``````
``````function addEdge(v1, v2) {
}

function removeEdge(v1, v2) {
}

removeEdge(v1,v2)``````

# Let's make some recommendations!

A

C

6

3

4

B

2

8

``````const adjList = {
A:[2,3,4],
2:[A],
3:[A,B],
4:[A,B,C],
B:[4,3,6]
...
}

``````

4

7

4

7

# Depth First!

4

7

1

1

2

1

2

3

1

2

3

4

1

2

5

3

4

1

2

5

3

6

4

1

2

5

3

6

4

7

1

2

5

3

6

8

4

7

1

2

5

9

3

6

8

4

7

1

2

5

9

3

6

8

4

7

10

### Graph Exploration

``````const adjList = {
1:[2,3,4],
2:,
3:[1,5],
4:[1,5,7],
5:[4,3,6]
...
}
``````

1. Add unvisited vertex to stack

2. Mark vertex as visited

3. If vertex has unvisited children

- repeat 1-2 with child

4. If vertex has no unvisited children

- pop from stack

5. repeat until stack is empty

### DFS

1. Add unvisited vertex to stack

2. Mark vertex as visited

3. If vertex has unvisited children

- repeat 1-2 with child

4. If vertex has no unvisited children

- pop from stack

5. repeat until stack is empty

1

2

5

9

3

6

8

4

7

10

### DFS

``{ 1: [2, 3, 4] }``
``````const stack = [1          ]

visited = {

}``````

1. Add unvisited vertex to stack

### DFS

``{ 1: [2, 3, 4] }``
``````const stack = [1          ]

visited = {
1: true,

}``````

2. Mark vertex as visited

### DFS

``{ 1: [2, 3, 4] }``
``{ 2:  }``
``````const stack = [1, 2      ]

visited = {
1: true,
2: true,

}``````

3. If vertex has unvisited children

- repeat 1-2 with child

### DFS

``{ 1: [2, 3, 4] }``
``{ 2:  }``
``{ 5:  }``
``````const stack = [1, 2, 5   ]

visited = {
1: true,
2: true,
5: true,

}``````

### DFS

``{ 1: [2, 3, 4] }``
``{ 2:  }``
``{ 5:  }``
``{ 9: [] }``
``````const stack = [1, 2, 5, 9]

visited = {
1: true,
2: true,
5: true,
9: true
}``````

### DFS

``{ 1: [2, 3, 4] }``
``{ 2:  }``
``{ 5:  }``
``{ 9: [] }``
``````const stack = [1, 2, 5, 9]

visited = {
1: true,
2: true,
5: true,
9: true
}``````

### DFS

``{ 1: [2, 3, 4] }``
``{ 2:  }``
``{ 5:  }``
``````const stack = [1, 2, 5,  ]

visited = {
1: true,
2: true,
5: true,
9: true
}``````

### DFS

``{ 1: [2, 3, 4] }``
``{ 2:  }``
``{ 5:  }``
``````const stack = [1, 2, 5,  ]

visited = {
1: true,
2: true,
5: true,
9: true
}``````

### DFS

``{ 1: [2, 3, 4] }``
``{ 2:  }``
``````const stack = [1, 2,     ]

visited = {
1: true,
2: true,
5: true,
9: true
}``````

### DFS

``{ 1: [2, 3, 4] }``
``````const stack = [1,        ]

visited = {
1: true,
2: true,
5: true,
9: true
}``````

5. repeat until stack is empty

### DFS

``{ 1: [2, 3, 4] }``
``````const stack = [1,3     ]

visited = {
1: true,
2: true,
5: true,
9: true,
3: true,

}``````
``{ 3: [6, 7] }``

### DFS

``{ 1: [2, 3, 4] }``
``````const stack = [1,3,6   ]

visited = {
1: true,
2: true,
5: true,
9: true,
3: true,
6: true,

}``````
``{ 3: [6, 7] }``
``{ 6:  }``

### DFS

``{ 1: [2, 3, 4] }``
``````const stack = [1,3,6,10]

visited = {
1: true,
2: true,
5: true,
9: true,
3: true,
6: true,
10: true
}``````
``{ 3: [6, 7] }``
``{ 6:  }``
``{ 10: [] }``

### DFS

``{ 1: [2, 3, 4] }``
``````const stack = [1,3,6,10]

visited = {
1: true,
2: true,
5: true,
9: true,
3: true,
6: true,
10: true
}``````
``{ 3: [6, 7] }``
``{ 6:  }``
``{ 10: [] }``

### DFS

``{ 1: [2, 3, 4] }``
``````const stack = [1,3,6,  ]

visited = {
1: true,
2: true,
5: true,
9: true,
3: true,
6: true,
10: true
}``````
``{ 3: [6, 7] }``
``{ 6:  }``

### DFS

``{ 1: [2, 3, 4] }``
``````const stack = [1,3     ]

visited = {
1: true,
2: true,
5: true,
9: true,
3: true,
6: true,
10: true,

}``````
``{ 3: [6, 7] }``

### DFS

``{ 1: [2, 3, 4] }``
``````const stack = [1,3,7   ]

visited = {
1: true,
2: true,
5: true,
9: true,
3: true,
6: true,
10: true,
7: true
}``````
``{ 3: [6, 7] }``
``{ 7: [] }``

### DFS

``{ 1: [2, 3, 4] }``
``````const stack = [1,3,7   ]

visited = {
1: true,
2: true,
5: true,
9: true,
3: true,
6: true,
10: true,
7: true
}``````
``{ 3: [6, 7] }``
``{ 7: [] }``

### DFS

``{ 1: [2, 3, 4] }``
``````const stack = [1,3     ]

visited = {
1: true,
2: true,
5: true,
9: true,
3: true,
6: true,
10: true,
7: true
}``````
``{ 3: [6, 7] }``

### DFS

``{ 1: [2, 3, 4] }``
``````const stack = [1       ]

visited = {
1: true,
2: true,
5: true,
9: true,
3: true,
6: true,
10: true,
7: true
}``````

### DFS

``{ 1: [2, 3, 4] }``
``````const stack = [1,4       ]

visited = {
1: true,
2: true,
5: true,
9: true,
3: true,
6: true,
10: true,
7: true,
4: true

}``````
``{ 4:  }``

### DFS

``{ 1: [2, 3, 4] }``
``````const stack = [1,4,8      ]

visited = {
1: true,
2: true,
5: true,
9: true,
3: true,
6: true,
10: true,
7: true,
4: true,
8: true
}``````
``{ 4:  }``
``{ 8: [] }``

### DFS

``{ 1: [2, 3, 4] }``
``````const stack = [1,4        ]

visited = {
1: true,
2: true,
5: true,
9: true,
3: true,
6: true,
10: true,
7: true,
4: true,
8: true
}``````
``{ 4:  }``

### DFS

``{ 1: [2, 3, 4] }``
``````const stack = [1      ]

visited = {
1: true,
2: true,
5: true,
9: true,
3: true,
6: true,
10: true,
7: true,
4: true,
8: true
}``````

### DFS

``````const stack = [          ]

visited = {
1: true,
2: true,
5: true,
9: true,
3: true,
6: true,
10: true,
7: true,
4: true,
8: true
}``````
``````const DFS = graph => {

}``````

# EXERCISE

1

1

2

1

2

3

1

2

3

4

1

2

3

4

5

1

2

3

4

5

6

1

2

3

4

5

6

7

1

2

3

4

5

6

7

8

1

2

3

4

5

6

7

9

8

1

2

3

4

5

6

7

9

10

8

### BFS

``````const BFS = graph => {
set start vertex to visited

while queue not empty

for each edge incident to vertex

if its not visited

mark vertex
}``````

### BFS

Order of visitation Queue contents after processing node
S
A
C
D
E
B
[ S ]
[ A C D E ]
[ C D E B ]
[ D E B ]
[ E B ]
[ ]

### BFS

``````const BFS = graph => {
initialize unexplored list

for the first vertex
optional: store pointer to parent vertex to null
mark as visited
while unexplored list is not empty
remove next vertex from unexplored list
optional: process vertex
for each edge
if un-visited
optional: process edge
add all un-visited/explored vertices to list
optional: store pointer to parent vertex
mark as visited
mark vertex as explored
}``````

### BFS

``````const BFS = graph => {

}``````

# What should we use BFS or DFS?

Logging or validating the contents of each edge and/or vertex.

Copying a graph, or converting between adjacency matrix or list.

Counting the number of edges and/or vertices.

Identifying the connected components.

Finding paths or cycles between two vertices.

``````const adjList = {
1:[2,5],
2:[1,5,3,4],
3:[2,4],
4:[2,5,3],
5:[4,1,2]
};``````

Vertices

Edges

Vertices

Edges

``````const adjMatrix = [
[0,1,0,0,1],
[1,0,1,1,1],
[0,1,0,1,0],
[0,1,1,0,1],
[1,1,0,1,0]
];``````

Directed, Undirected

Weighted, Unweighted

Self loops

Sparse, Dense

Cyclic, Acyclic

# Let's find something specific

Apple

Cereal

Donut

Eggs

Fudge

### Linear Search

Apple

Cereal

Donut

Eggs

Fudge

``````index = 0
length = 6``````

### Linear Search

Apple

Cereal

Donut

Eggs

Fudge

``````index = 1
length = 6``````

### Linear Search

Apple

Cereal

Donut

Eggs

Fudge

``````index = 2
length = 6``````

### Linear Search

Apple

Cereal

Donut

Eggs

Fudge

``````index = 3
length = 6``````

### Linear Search

Apple

Cereal

Donut

Eggs

Fudge

``````index = 4
length = 6``````

### Linear Search

Apple

Cereal

Donut

Eggs

Fudge

``````index = 4
length = 6``````

### Linear Search

Search/Find: O(n)

Apple

Cereal

Donut

Eggs

Fudge

``````firstIndex = 0
lastIndex = 5
mid = floor((lastIndex - firstIndex) / 2)``````

0

5

### Binary Search

Apple

Cereal

Donut

Eggs

Fudge

``````firstIndex = 0
lastIndex = 5
mid = 2``````

0

5

### Binary Search

Apple

Cereal

Donut

Eggs

Fudge

``````firstIndex = 0
lastIndex = 5
mid = 2

check mid - 1``````

0

5

### Binary Search

Apple

Cereal

Donut

Eggs

Fudge

``````firstIndex = 0
lastIndex = 5
mid = 2

check mid + 1``````

0

5

### Binary Search

Apple

Cereal

Donut

Eggs

Fudge

``````firstIndex = 0
lastIndex = 5
mid = 2

firstIndex = mid + 1``````

0

5

### Binary Search

Apple

Cereal

Donut

Eggs

Fudge

``````firstIndex = 3
lastIndex = 5
mid =
(lastIndex - firstIndex / 2)
+ firstIndex
``````

5

3

### Binary Search

Apple

Cereal

Donut

Eggs

Fudge

``````firstIndex = 3
lastIndex = 5
mid = 4``````

5

3

### Binary Search

Apple

Cereal

Donut

Eggs

Fudge

``````firstIndex = 3
lastIndex = 5
mid = 4``````

5

3

### Binary Search

Apple

Cereal

Donut

Eggs

Fudge

``````firstIndex = 3
lastIndex = 5
mid = 4``````

5

3

### Binary Search

Apple

Cereal

Donut

Eggs

Fudge

``````firstIndex = 3
lastIndex = 5
mid = 4``````

5

3

### Binary Search

Search/Find: O(log n)

Apple

Cereal

Donut

Eggs

Fudge

5

3

O(log n)

Apple

Cereal

Donut

Eggs

Fudge

O(n)

Apple

Cereal

Donut

Eggs

Fudge

5

3

### Binary vs Linear Search

O(log n)

Needs to be sorted

Apple

Cereal

Donut

Eggs

Fudge

O(n)

Unsorted

Apple