Lecture Slides on Graphs - Data Structures | CS 261, Study notes of Data Structures and Algorithms

Material Type: Notes; Class: DATA STRUCTURES; Subject: Computer Science; University: Oregon State University; Term: Spring 2003;

Typology: Study notes

Pre 2010

Uploaded on 08/30/2009

koofers-user-tdw
koofers-user-tdw 🇺🇸

10 documents

1 / 15

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
1
CS261–DataStructures
Graphs
Graphs
Used in a variety of applications and algorithms
Graphs represent relationships or connections
Superset of trees (i.e., a tree is a restricted form of a graph):
A graph represents general relationships:
Each node may have many predecessors
There may be multiple paths (or no path) from one node to another
Can have cycles or loops
Examples: airline flight connections, friends, algorithmic flow, etc.
A tree has more restrictive relationships and topology:
Each node has a single predecessor—its parent
There is a single, unique path from the root to any node
•Nocycles
Example: less than or greater than in a binary search tree
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff

Partial preview of the text

Download Lecture Slides on Graphs - Data Structures | CS 261 and more Study notes Data Structures and Algorithms in PDF only on Docsity!

CS 261 – Data Structures

Graphs

Graphs

• Used in a variety of applications and algorithms

• Graphs represent relationships or connections

• Superset of trees (i.e., a tree is a restricted form of a graph):

  • A graph represents general relationships:
    • Each node may have many predecessors
    • There may be multiple paths (or no path) from one node to another
    • Can have cycles or loops
    • Examples: airline flight connections, friends, algorithmic flow, etc.
  • A tree has more restrictive relationships and topology:
    • Each node has a single predecessor—its parent
    • There is a single, unique path from the root to any node
    • No cycles
    • Example: less than or greater than in a binary search tree

Graphs: Vertices and Edges

  • A graph is composed of vertices and edges
  • Vertices (also called nodes ):
    • Represent objects, states (i.e., conditions or configurations) , positions,

or simply just place holders

  • Set { v

1

, v

2

, …, v

n

} : each vertex is unique Æ no two vertices represent the

same object/state

  • Edges (also called arcs ):
    • Can be either directed or undirected
    • Can be either weighted (or labeled) or unweighted
    • An edge ( v

i

, v

j

) between two vertices indicates that they are

directly related, connected, etc.

  • If there is an edge from v

i

to v

j

, then v

j

is a neighbor of v

i

(if the

edge is undirected then v

i

and v

j

are neighbors or each other)

Graphs: Types of Edges

Weighted

Unweighted

Undirected Directed

v

1

v

2

v

4

v

3

v

1

v

2

v

4

v

3

v

1

v

2

v

4

v

3

w

1,

w

2,

w

1,

w

3,

w

4,

v

1

v

2

v

4

v

3

w

1-

w

2-

w

1-

w

3-

w

1-

Graphs: Example

Pendleton

Pierre

Pensacola

Princeton

Pittsburgh

Peoria

Pueblo

Phoenix

Graphs: Representations

Two most common representations:

1. Adjacency matrix:

  • Represents graph as a 2-D matrix
  • Vertices are used as indices for both the rows and columns of the matrix
    • Vertices must be numbered or must associate an integer value with each vertex
  • A matrix entry in row i and column j of:

1: indicates an edge from v

i

to v

j

0: no edge from v

i

to v

j

  • Weighted representation has weight w

i , j

instead of 1 and ∞ instead of 0

  • Requires O( V

2

) space for V vertices

2. Edge list:

  • Each vertex v

i

lists the set of directly connected neighbors

  • Weighted representation replaces the neighbor set with a Map :
    • key Æ vertex v

j

  • value Æ weight w

i , j

  • Stores only the edges Æ more space efficient for sparse graph: O( V + E )

Graphs Representation: Adjacency Matrix

7: Pueblo 0 0 0 0 1 0 0?

6: Princeton 0 0 0 0 0 1? 0

5: Pittsburgh 0 1 0 0 0? 0 0

4: Pierre 1 0 0 0? 0 0 0

3: Phoenix 0 0 1? 0 1 0 1

2: Peoria 0 0? 0 0 1 0 1

1: Pensacola 0? 0 1 0 0 0 0

0: Pendleton? 0 0 1 0 0 0 1

City

Pendleton

Pierre

Pensacola

Princeton

Pittsburgh

Peoria

Pueblo

Phoenix

What about the diagonal

matrix entries?

Is a vertex connected to

itself?

Graphs Representation: Adjacency Matrix

7: Pueblo 0 0 0 0 1 0 0 1

6: Princeton 0 0 0 0 0 1 1 0

5: Pittsburgh 0 1 0 0 0 1 0 0

4: Pierre 1 0 0 0 1 0 0 0

3: Phoenix 0 0 1 1 0 1 0 1

2: Peoria 0 0 1 0 0 1 0 1

1: Pensacola 0 1 0 1 0 0 0 0

0: Pendleton 1 0 0 1 0 0 0 1

City 0 1 2 3 4 5 6 7

Pendleton

Pierre

Pensacola

Princeton

Pittsburgh

Peoria

Pueblo

Phoenix

By convention, a vertex is

usually connected to itself

(though, this is not always the case)

All-Pairs Reachability: Adjacency Matrix

  • How do we compute all-pairs reachability
  • Converts adjacency matrix into a “reachability” matrix
    • A matrix entry in row i and column j of:

1: indicates that there is a path (of zero or more edges) from v

i

to v

j

0: no path from v

i

to v

j

  • Warshall’s algorithm:
    • Named after the computer scientist who discovered it
    • Three nested loops of order V Æ O( V

3

  • Key idea: each iteration of the outer loop (index k ) adds any

path of length 2 that has vertex v

k

as its center

  • Since the adjacency and the reachability matrices are binary (0 or

1 entries) , use bitwise operations

Warshall’s Algorithm

class Warshall {

static void warshall(int [][] a) { // Input: initial adjacency matrix.

int n = a.length; // Number of vertices.

for (int k = 0; k < n; k++) { // Add paths of length 2 through v

k

.

for (int i = 0; i < n; i++)

for (int j = 0; j < n; j++) // Add path from v

i

to v

j

a[i][j] |= a[i][k] & a[k][j]; // going through v

k

.

}

}

static void matrixOutput(int [][] a) { // Print matrix.

for (int i = 0; i < a.length; i++) {

for (int j = 0; j < a[i].length; j++)

System.out.print(" " + a[i][j]);

System.out.println(" ");

}

}

...

}

Warshall’s Algorithm: Initialization

class Warshall {

...

static public void main (String [] args) {

int [][] adjacency = {{1, 0, 0, 1, 0, 0, 0, 1}, // Initialize

{0, 1, 0, 1, 0, 0, 0, 0}, // adjacency

{0, 0, 1, 0, 0, 1, 0, 1}, // matrix.

{0, 0, 1, 1, 0, 1, 0, 1},

{1, 0, 0, 0, 1, 0, 0, 0},

{0, 1, 0, 0, 0, 1, 0, 0},

{0, 0, 0, 0, 0, 1, 1, 0},

{0, 0, 0, 0, 1, 0, 0, 1}};

warshall (adjacency); // Compute all-pairs reachability matrix.

matrixOutput(adjacency); // Print resulting reachability matrix.

}

}

Warshall’s Algorithm: Initialization

7: Pueblo 0 0 0 0 1 0 0 1

6: Princeton 0 0 0 0 0 1 1 0

5: Pittsburgh 0 1 0 0 0 1 0 0

4: Pierre 1 0 0 0 1 0 0 0

3: Phoenix 0 0 1 1 0 1 0 1

2: Peoria 0 0 1 0 0 1 0 1

1: Pensacola 0 1 0 1 0 0 0 0

0: Pendleton 1 0 0 1 0 0 0 1

City 0 1 2 3 4 5 6 7

Pendleton

Pierre

Pensacola

Princeton

Pittsburgh

Peoria

Pueblo

Phoenix

Initial adjacency matrix

Warshall’s Algorithm: After Iteration 2

7: Pueblo 0 0 0 0 1 0 0 1

6: Princeton 0 0 0 0 0 1 1 0

5: Pittsburgh 0 1 0 1 0 1 0 0

4: Pierre 1 0 0 1 1 0 0 1

3: Phoenix 0 0 1 1 0 1 0 1

2: Peoria 0 0 1 0 0 1 0 1

1: Pensacola 0 1 0 1 0 0 0 0

0: Pendleton 1 0 0 1 0 0 0 1

City

Add all paths of length 2 that go

through vertex 2 (Peoria)

Pendleton

Pierre

Pensacola

Princeton

Pittsburgh

Peoria

Pueblo

Phoenix

Edges already exist (doesn’t add

anything new)

Could potentially define paths of

length 4 in this (the third) iteration

Warshall’s Algorithm: After Iteration 3

7: Pueblo 0 0 0 0 1 0 0 1

6: Princeton 0 0 0 0 0 1 1 0

5: Pittsburgh 0 1 1 1 0 1 0 1

4: Pierre 1 0 1 1 1 1 0 1

3: Phoenix 0 0 1 1 0 1 0 1

2: Peoria 0 0 1 0 0 1 0 1

1: Pensacola 0 1 1 1 0 1 0 1

0: Pendleton 1 0

City 0 1 2 3 4 5 6 7

Add all paths of length 2 that go

through vertex 3 (Phoenix)

Pendleton

Pierre

Pensacola

Princeton

Pittsburgh

Peoria

Pueblo

Phoenix

Notice that it also includes the paths

formed in interations 0 and 1

(resulting, in this case, in new

reachability paths of length 3)

Could potentially define paths of

length 5 in this (the fourth) iteration

Warshall’s Algorithm: After Iteration 7

7: Pueblo 1 1 1 1 1 1 0 1

6: Princeton 1 1 1 1 1 1 1 1

5: Pittsburgh 1 1 1 1 1 1 0 1

4: Pierre 1 1 1 1 1 1 0 1

3: Phoenix 1 1 1 1 1 1 0 1

2: Peoria 1 1 1 1 1 1 0 1

1: Pensacola 1 1 1 1 1 1 0 1

0: Pendleton 1 1 1 1 1 1 0 1

City

Final result: Every city can reach

every other city, except for Princeton

Pendleton

Pierre

Pensacola

Princeton

Pittsburgh

Peoria

Pueblo

Phoenix

The final matrix has a 1 in row i and

column j if vertex v

j

is reachable

from vertex v

i

via some path

Warshall’s Algorithm: Another Look

static void warshall(int [][] a) { // Input: initial adjacency matrix.

int n = a.length; // Number of vertices.

for (int k = 0; k < n; k++) { // Add paths of length 2 through v

k

.

for (int i = 0; i < n; i++)

for (int j = 0; j < n; j++) // Add path from v

i

to v

j

a[i][j] |= a[i][k] & a[k][j]; // going through v

k

.

}

}

  • Notice that a[i][k] doesn’t change inside the inner loop:
    • If zero, then the inner loop does nothing
    • If one, don’t need to perform bitwise AND ( & )
    • If graph is sparse, the inner loop is not needed very often (at least

initially)

  • May get a performance improvement by checking a[i][k] prior

to third loop

Floyds’s Algorithm: Initialization

7: Pueblo

6: Princeton ∞ ∞ ∞ ∞ ∞ 1 0 ∞

5: Pittsburgh ∞ 4 ∞ ∞ ∞ 0 ∞ ∞

4: Pierre 2 ∞ ∞ ∞ 0 ∞ ∞ ∞

3: Phoenix ∞ ∞ 4 0 ∞ 10 ∞ 3

2: Peoria ∞ ∞ 0 ∞ ∞ 5 ∞ 3

1: Pensacola ∞ 0 ∞ 5 ∞ ∞ ∞ ∞

0: Pendleton 0

City

Pendleton

Pierre

Pensacola

Princeton

Pittsburgh

Peoria

Pueblo

Phoenix

Initial adjacency matrix

2

4

3

3

4

3

5

4

10

8

5

2

Floyd’s Algorithm

class Floyd {

static void floyd(double [][] a) { // Input: initial adjacency matrix.

int n = a.length; // Number of vertices.

for (int k = 0; k < n; k++) { // Add paths of length 2 through v

k

.

for (int i = 0; i < n; i++)

for (int j = 0; j < n; j++) { // Check path from v

i

to v

j

double m = a[i][k] + a[k][j]; // going through v

k

.

if (m < a[i][j]) a[i][j] = m; // Update if less.

}

}

}

...

}

Floyd’s Algorithm: Improved

Of course, we can apply a similar improvement as we did

to Warshall’s algorithm

class Floyd {

static void floyd(double [][] a) { // Input: initial adjacency matrix.

int n = a.length; // Number of vertices.

for (int k = 0; k < n; k++) { // Add paths of length 2 through v

k

.

for (int i = 0; i < n; i++) {

double v = a[i][k]; // If there is a path from v

i

to v

k

:

if (v < Double.POSITIVE_INFINITY)

for (int j = 0; j < n; j++) { // Check path from v

i

to v

j

double m = v + a[k][j]; // going through v

k

.

if (m < a[i][j]) a[i][j] = m; // Update if less.

}

}

}

}

...

}

Single Source Reachability: Edge-List

  • How do you determine reachability with an edge-list

representation?

  • In this case we want to answer the single-source question:

What is reachable from a given vertex v

i

  • Should be faster than the all-pairs question
  • Basic algorithm:

Initialize set of reachable vertices with v

i

and add v

i

to a stack

While stack is not empty

Get and remove (pop) last vertex v from stack

For all neighbors, v

j

, of v

If v

j

is not is set of reachable vertices, add to stack and reachable set