chap04alg

22
CHAPTER 4 Searching

Upload: munkhchimeg

Post on 30-Jun-2015

533 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Chap04alg

CHAPTER 4

Searching

Page 2: Chap04alg

Algorithm 4.1.1 Binary SearchThis algorithm searches for the value key in the nondecreasing array L[i], ... , L[j]. If key is found, the algorithm returns an index k such that L[k] equals key. If key is not found, the algorithm returns -1, which is assumed not to be a valid index.

Input Parameters: L,i,j,keyOutput Parameters: Nonebsearch(L,i,j,key) {

while (i = j) { k = (i + j)/2 if (key == L[k]) // found return k if (key < L[k]) // search first part j = k - 1 else // search second part i = k + 1 } return -1 // not found}

Page 3: Chap04alg

Algorithm 4.2.2 Depth-First SearchThis algorithm executes a depth-first search beginning at vertex start in a graph with vertices 1, ... , n and outputs the vertices in the order in which they are visited. The graph is represented using adjacency lists; adj[i] is a reference to the first node in a linked list of nodes representing the vertices adjacent to vertex i. Each node has members ver, the vertex adjacent to i, and next, the next node in the linked list or null, for the last node in the linked list. To track visited vertices, the algorithm uses an array visit; visit[i] is set to true if vertex i has been visited or to false if vertex i has not been visited.

Page 4: Chap04alg

Input Parameters: adj,startOutput Parameters: Nonedfs(adj,start) { n = adj.last for i = 1 to n visit[i] = false dfs_recurs(adj,start)}

dfs_recurs(adj,start) { println(start) visit[start] = true trav = adj[start] while (trav != null) { v = trav.ver if (!visit[v]) dfs_recurs(adj,v) trav = trav.next }}

Page 5: Chap04alg

Algorithm 4.3.2 Breadth-First SearchThis algorithm executes a breadth-first search beginning at vertex start in a graph with vertices 1, ... , n and outputs the vertices in the order in which they are visited.

The graph is represented using adjacency lists; adj[i] is a reference to the first node in a linked list of nodes representing the vertices adjacent to vertex i. Each node has members ver, the vertex adjacent to i, and next, areference to the next node in the linked list or null, for the last node in thelinked list.

To track visited vertices, the algorithm uses an array visit; visit[i] is set to true if vertex i has been visited or to false if vertex i has not been visited. The algorithm uses an initially empty queue q to store pending current vertices. The expression q.enqueue(val)adds val to q. The expression q.front()returns the value at the front of q but does not remove it. The expression q.dequeue()removes the item at the front of q. The expression q.empty()returns true if q is empty or false if q is not empty.

Page 6: Chap04alg

Input Parameters: adj,startOutput Parameters: Nonebfs(adj,start) {

n = adj.last for i = 1 to n visit[i] = false visit[start] = true println(start)

q.enqueue(start) // q is an initially empty queue while (!q.empty()) { current = q.front() q.dequeue() trav = adj[current] while (trav != null) { v = trav.ver if (!visit[v]) { visit[v] = true println(v) q.enqueue(v) } trav = trav.next } }}

Page 7: Chap04alg

Algorithm 4.3.4 Finding Shortest Path Lengths Using Breadth-First SearchThis algorithm finds the length of a shortest path from the start vertex startto every other vertex in a graph with vertices 1, ... , n.

The graph is represented using adjacency lists; adj[i] is a reference to the first node in a linked list of nodes representing the vertices adjacent to vertex i. Each node has members ver, the vertex adjacent to i, and next, areference to the next node in the linked list or null, for the last node in thelinked list.

In the array length, length[i] is set to the length of a shortest path from start to vertex i if this length has been computed or to ∞ if the length has not been computed. If there is no path from start to i, when the algorithm terminates, length[i] is ∞.

Page 8: Chap04alg

Input Parameters: adj,startOutput Parameters: lengthshortest_paths(adj,start,length) {

n = adj.last for i = 1 to n length[i] = ∞ length[start] = 0

q.enqueue(start) // q is an initially empty queue while (!q.empty()) { current = q.front() q.dequeue() trav = adj[current] while (trav != null) { v = trav.ver if (length[v] == ∞) { length[v] = 1 + length[current]

q.enqueue(v) } trav = trav.next } }}

Page 9: Chap04alg

Algorithm 4.4.1 Topological SortThis algorithm computes a topological sort of a directed acyclic graph with vertices 1, ... , n. The vertices in the topological sort are stored in the array ts.

The graph is represented using adjacency lists; adj[i] is a reference to the first node in a linked list of nodes representing the vertices adjacent to vertex i. Each node has members ver, the vertex adjacent to i, and next, the next node in the linked list or null, for the last node in the linked list.

To track visited vertices, the algorithm uses an array visit; visit[i] is set to true if vertex i has been visited or to false if vertex i has not been visited.

Page 10: Chap04alg

Input Parameters: adjOutput Parameters: tstop_sort(adj,ts) { n = adj.last

// k is the index in ts where the next vertex is to be// stored in topological sort. k is assumed to be global.k = n

for i = 1 to n visit[i] = false

for i = 1 to nif (!visit[v])

top_sort_recurs(adj,i,ts)}top_sort_recurs(adj,start,ts) {

visit[start] = true trav = adj[start] while (trav != null) { v = trav.ver if (!visit[v]) top_sort_recurs(adj,v,ts) trav = trav.next }

ts[k] = startk = k - 1

}

Page 11: Chap04alg

Algorithm n-Queens, Initial VersionThe n-queens problem is to place n queens on an n × n board so that no two queens are in the same row, column, or diagonal. Using backtracking, this algorithm outputs all solutions to this problem. We place queens successively in the columns beginning in the left column and working from top to bottom. When it is impossible to place a queen in a column, we return to the previous column and move its queen down.

Page 12: Chap04alg

n_queens(n) {rn_queens(1,n)

}

rn_queens(k,n) {for row[k] = 1 to n

if (position_ok(k,n)) if (k == n) { for i = 1 to n print(row[i] + “ ”) println() } else rn_queens(k + 1,n)}

position_ok(k,n)for i = 1 to k - 1

// abs is absolute value if (row[k] == row[i] || abs(row[k] - row[i]) == k - i) return false return true}

Page 13: Chap04alg

Algorithm 4.5.2 Solving the n-Queens Problem Using BacktrackingThe n-queens problem is to place n queens on an n × n board so that no two queens are in the same row, column, or diagonal. Using backtracking, this algorithm outputs all solutions to this problem. We place queens successively in the columns beginning in the left column and working from top to bottom. When it is impossible to place a queen in a column, we return to the previous column and move its queen down.

Page 14: Chap04alg

The value of row[k] is the row where the queen in column k is placed.The algorithm begins when n_queens calls rn_queens(1,n). When

rn_queens(k, n)is called, queens have been properly placed in columns 1 through k - 1, andrn_queens(k,n) tries to place a queen in column k. If it is successful and kequals n, it prints a solution. If it is successful and k does not equal n, itcalls rn_queens(k + 1,n).If it is not successful, it backtracks by returning to its caller rn_queens(k - 1 ,n).

The value of row_used[r] is true if a queen occupies row r and false otherwise. The value of ddiag_used[d] is true if a queen occupies ddiag diagonal d and false otherwise. According to the numbering system used, the queen in column k, row r, is in ddiag diagonal n - k + r. The value of udiag_used[d] is true if a queen occupies udiag diagonal d and false otherwise. According to the numbering system used, the queen in column k, row r, is in udiag k + r - 1.

The function position_ok(k,n) assumes that queens have been placed in columns 1 through k - 1. It returns true if the queen in column k does not conflict with the queens in columns 1 through k- 1 or false if it does conflict.

Page 15: Chap04alg

Input Parameter: nOutput Parameters: Nonen_queens(n) {

for i = 1 to n row_used[i] = false for i = 1 to 2 * n - 1 ddiag_used[i] = udiag_used[i] = false rn_queens(1,n)}

...

Page 16: Chap04alg

...// When rn_queens(k,n) is called, queens have been// properly placed in columns 1 through k - 1.rn_queens(k,n) {

for row[k] = 1 to n if (position_ok(k,n))

row_used[row[k]] = trueddiag_used[n - k + row[k]] = trueudiag_used[k + row[k] - 1] = true

if (k == n) {// Output a solution. Stop if only one // solution is desired.

for i = 1 to n print(row[i] + “ ”) println() } else rn_queens(k + 1,n)

row_used[row[k]] = falseddiag_used[n - k + row[k]] = falseudiag_used[k + row[k] - 1] = false

}...

Page 17: Chap04alg

...

// position_ok(k,n) returns true if the queen in column k// does not conflict with the queens in columns 1// through k - 1 or false if it does conflict.position_ok(k,n)

return !(row_used[row[k]] || ddiag_used[n - k + row[k]] || udiag_used[k + row[k] - 1 ])

}

Page 18: Chap04alg

Form of Backtracking Algorithm

Suppose that we solve a problem using backtracking as in Algorithm 4.5.2 in which the solution is of the form

x[1], ... , x[n].Suppose also that the values of x[i] are in the set S (e.g., in Algorithm 4.5.2,S = {1, . . . , n}).

We require a function bound(k) with the following property. Whenever x[1], ... , x[k - 1]is a partial solution and x[k] has been assigned a value, then bound(k) has to return true if x[1], ... , x[k]is a partial solution and false otherwise. The key to writing a useful back-tracking algorithm is to write an efficient bound function that eliminatesmany potential nodes from the search tree.

Page 19: Chap04alg

The general form of a backtracking algorithm is

backtrack(n) { rbacktrack(1,n)}

rbacktrack(k,n) { for each x[k] S if (bound(k)) if (k == n) { // Output a solution. Stop if only

for i = 1 to n // one solution is desired. print(x[i] + “ ”) println() } else rbacktrack(k + 1, n)}

Page 20: Chap04alg

Algorithm 4.5.4 Searching for a Hamiltonian CycleThis algorithm inputs a graph with vertices 1, ... , n. The graph is represented as an adjacency matrix adj; adj[i][j] is true if (i,j) is an edge or false if it is not an edge. If the graph has a Hamiltonian cycle, the algorithm computes one such cycle (x[1], ... , x[n], x[1]).If the graph has no Hamiltonian cycle, the algorithm returns false and the contents of the array x are not specified.

In the array used, used[i] is true if i has been selected as one of the vertices in a potential Hamiltonian cycle or false if i has not been selected.

The function path_ok(adj,k,x) assumes that (x[1], ... , x[k - 1]) is a path from x[1] to x[k - 1] and that the vertices x[1], ... , x[k - 1] are distinct. It then checks whether x[k] is different from each of x[1], ... , x[k - 1] and whether (x[k - 1], x[k]) is an edge. If k = n, path_ok also checks whether (x[n], x[1]) is an edge.

Page 21: Chap04alg

Input Parameter: adjOutput Parameter: xhamilton(adj,x) { n = adj.last

x[1] = 1used[1] = truefor i = 2 to n

used[i] = falserhamilton(adj,2,x)

}

rhamilton(adj,k,x) {n = adj.lastfor x[k] = 2 to n

if (path_ok(adj,k,x)) { used[x[k]] = true if (k == n || rhamilton(adj,k + 1,x)) return true used[x[k]] = false

} return false}...

Page 22: Chap04alg

...

path_ok(adj,k,x) {n = adj.last

if (used[x[k]]) return false if (k < n) return adj[x[k - 1]][x[k]] else return adj[x[n - 1]][x[n]] && adj[x[1]][x[n]]}