COSC 336 Towson Final
Heap • The root of the tree A[1] and given index i of a node, the indices of its parent, left child and right child can be computed
PARENT (i) return floor(i/2) LEFT (i) return 2i RIGHT (i) return 2i + 1
Summing odd integers iterative version Induction
input n x = 0 for i = 1 to n do x = x+(2i-1) output x Induction can be used to show that for all inputs n>=0, the program computers x = n^2 Basis: for input n = 0, the for loop is not executed and x - 0 = 0^2 is computed (inductive step) : For inputs n>1, assume the theorem true for all inputs in the range 0 through n-1, so in particular, on input (n-1) it computes (n-1)^2. since on input n the program executes the same instructions as for input n01 and then executes one additional iteration of the loop (where it adds 2n-1 to the current value of x), it computes: x = (n-1)^2+(2n-1) = (n^2-2n+1) + (2n-1) = n^2
Breadth First Traversal
level order traversal
Advantage to using array to represent tree
- no need to store leg and right pointers in the nodes -> save memory - Direct access to nodes: to get to node k, access A[k]
depth first traversal
1. Perform pre-order opera?on 2. for i=1 to n-1 do 1. Visit child[i], if present 2. Perform in-order opera?on 3. Visit child[n], if present 4. Perform post-order opera?on O(n)
Array implementation of Stacks
A variable top is the index of the first unused location. if there are currently k items, locations 0 through k-1 store them, top - k, and locations k through n-1 are unused An array S[0]....s[n-1] An integer variable top that is initially 0 PUSH places a data item d on the stack S: procedure PUSH(d,s) ---if top >= n then {stack overflow} ---else begein ------S[top] := d ------top := top+1 ------end ---end POP removes (and returns) the data item on top of the stack S: function POP(S) ---if top <=0 then {stack underflow} ---else begin ------top:= top-1 ------return S[top] ------end ---end TOP simply returns data item on top of the stack S: ---function TOP(S) if top <= 0 then {error} else return S[top-1] end
Circular Queue (ENQUEUE)
Array Q[0]...Q[n-1] and variables front, rear, size = 0 The ENQUEUE operation to enter d at the rear of queue Q: ---procedure ENQUEUE(d, Q) ------if size >= n then {queue overflow} ------else begin ---------Q[rear]:=d ---------rear := rear+1; if rear = n then rear := 0 ---------size := size + 1 ---------end ------end
Divide and Conquer - Sort
Base case at most one element (left ≥ right), return 2. Divide A into two subarrays: FirstPart, SecondPart Two Subproblems: sort the FirstPart sort the SecondPart 3. Recursively sort FirstPart sort SecondPart 4. Combine sorted FirstPart and sorted SecondPart
• For each edge (u,v), the flow f(u,v) is a realvalued function that must satisfy 3 conditions:
Capacity constraint: for all u,v that exist in V, f(u,v) <= c(u,v) Skew symmetry: for all u,v that exist in V, f(u,v) = -f(v,u) Flow conservation: for all u that exist in V, - {s,t}, epsilon f(u,v) = 0
Binary Search Algoirthm
Compute the midpoint m between a and b, check whether x<=A[m], and repeat this process on the appropriate half of the array. while a<b do begin ---m := [(a+b)/2] ---if x <= A[m] then b:= m else a:= m+1 ---end if x = A[a] then {x is at position a} else {x is not in A} O(logn)
reversing a singly linked list (making a new list)
Copy L to a second list R one item at a time. Because items are removed from the front of L and placed at the front of R, the effect is like pushing them on a stack, and R ends up in the reverse of the order of L R:=CREATE while(not EMPTY(L)) do INSERT(DELETE(FIRST(L),L),nil,R) DESTROY(L) L:=R O(n)
DELETEMIN(v,T) :
Delete and return smallest data in the subteree of T rooted at v. First compute v = MIN(v,T) and let p be the parents of w and r the right child of w. As depicted on the following page, if w is a left child ( and it might be that w =v) then delete w and make r the left child of p (the left child of p becomes nil if r is nil). there are also two "degenerate" cases when w = v and w is a right child or the root w = MIN(v,T) p = PARENT(w) r=RCHILD(w) if r != nil then make the parent of r be p if w is a left child then make the left child of p be r else if w is a right child then make the right child be of r else make r the new root (and make T be the empty tree if r = nil) reclaim the memory for w and return the data that was stored in w
recursive approach for evaluating a prefix expression
Given a stack containing a prefix expression (each item is a value, an operator, or a parenthesis), preEVAL pops a binary operator and then recursively pops its two arguments function preEVAL ---if the stack is empty then ERROR - missing value ---else if TOP is a vlue then return POP ---else if TOP is a binary operation then begin ------op = POP ------x = preEVAL ------y = preEVAL ------return the result of applying op to x and y ------end ---else ERROR - illegal input ---end Note: the longest legal initial portion is evaluated. The calling code can check if the stack is not empty, and if so report "ERROR - missing operator"
Heapsort
Heapsort(A) { Buildheap(A) for i =length[A] //down to 2 do swap A[1], A[i] heapsize[A] = heapsize[A] - 1 Heapify(A, 1) } procedure Heapify(A, i) ----- l = left(i); ----- r = right(i); ----- if(l == heapsize[A] and A[l] > A[i]) ---------- then largest = l; ----- else largest = i; ----- if(r <= heapsize[A] and A[r] > A[largest]) ---------- then largest = r; ----- if(largest != i) ---------- then swap A[i] with A[largest]; ---------- Heapify(A, largest) Buildheap(A) { heapsize[A] =length[A] for i =|length[A]/2 //down to 1 do Heapify(A, i) } ::: Running Time: O(nlogn)
making change greedy
MAKE-CHANGE (n) C ← {100, 25, 10, 5, 1} // constant. Sol ← {}; // set that will hold the solution set. Sum ← 0 sum of item in solution set WHILE sum not = n x = largest item in set C such that sum + x ≤ n IF no such item THEN RETURN "No Solution" S ← S {value of x} sum ← sum + x RETURN S
Towers of Hanoi Puzzle (alg and induction) You are given three posts labeled A, B, and C. On Post A there are n rings of different sizes, in the order of the largest ring on the bottom to the smallest one on top. Posts B and C are empty. The object is to move the n rings from Post A to Post B by successively moving a ring from one post to another post that is empty or has a larger diameter ring on top.
Recursive algorithm: procedure TOWER (n,w,y,x) if n>0 then begin ---TOWER(n-1,x,z,y) ---write "Move ring n from x to y" ---TOWER (n-1, z, y, x) ---end end Inductive proof that the puzzle has a solution basis: one ring can always be moved inductive step : assume that we can move n-1 rings from any given post to any other post. Since any of the rings 1 through n-1 can be placed on top of ring n, all n rings can be moved as follows: ---1. Move n-1 rings from Post A to Post C. ---2. Move ring n from Post A to Post B ---3. Move n-1 rings from Post C to Post B The solution for 3 disks takes 7 steps
Quick Sort
Sort A[i]...A[j] procedure arrayQSORT(i,j) if i < j then begin ---a,b = PARTITION (i,j) ---QSORT(i,a) ---QSORT(b,j) PARTITION(i,j) x = i +1 y = j while x <= y do ---while x <= y and A[x] < A[i] do x = x+1 ---while x < = y and A[y] >= A[i] do y = y-1 ---if x < y then begin exchange A[x] and A[y]; x = x+1; y = y-1 Exchange A[i] and A[y] return y - 1 and y +1 O(nlogN)
max heap
Store data in ascending order - Has property of A[Parent(i)] ≥ A[i]
min heap
Store data in descending order - Has property of A[Parent(i)] ≤ A[i]
Circular Queue (DEQUEUE)
The Dequeue operation to remove from the front of the queue Q: ---function DEQUEUE(Q) ------if size = 0 then {queue underflow} ------else begin ---------temp := Q[front] ---------front := front+1; if front = n then front := 0 ---------size := size-1 ---------return temp ---------end ------end
the POP(i) Stack operation
The operation POP(i) removes i-1 items from the stack and then does a normal POP operation (if the stack has less than i items, there is an underflow error). procedure POP(i) ---for j = 1 to i - 1 do POP ---return POP ---end Note: here we have used POP as both a procedure that simply discards the element on top of the stack and as a function that deletes and returns it O(n)
Merge sort (1 & 2 lists) linked list
To sort a list, divide it in half, sort the two halves independently, and then merge the two sorted lists into a single sorted list. To simplify our presentation, we begin by assuming that linked lists are used. procedure MSORT(list): ---if list is empty or has only one element then return list ---else begin ------divide list into two equal size lists, list1 and list2 ------return MERGE(MSORT(list1),MSORT(list2)) ------end ---end merge two sorted lists in linear time and space: function MERGE(list 1, list2) ---list 3 = the empty list while both list1 and list2 are not empty do begin ------compare the first elements of list1 and list2 and whichever is smaller (ties can broken arbitrarily), delete it and append it to list3. ------end ---append list1 and list2 to the end of list3 ---return list3 ---end O(nlogn)
reversing a singly linked list(in place)
Traverse L to reverse each next pointer and then finish by exchanging the first and last pointers of the header. Although some of the steps can be expressed using the basic list operations, "low-level" assignments are needed to modify the next field and the first and last fields of the header, we use the same notation for low level operations as the previous examples. previous = nil current = L.first while(current != nil) do begin ---temp = current.next ---current.next = previous ---previous = current ---current = temp ---end L.last = L.first L.first = previous O(n)
definition of Heap Sort
an efficient sorting algorithm implemented with the heap data structure.
array implementation of merge sort
arrayMSORT(i,j) if i < j then begin ---m = [i+j/2] ---arrayMSORT(i,m) ---arrayMSORT(i+1,j) ---arrayMERGE(i,j,m) ---end end arrayMERGE(i,j,m) x = i z = m+1 z = i while z <= j do begin ---if y > j then begin B[z] = A[x]; x = x+1 end ---else if x>m then begin B[z] = A[y]; y = y+1 end ---else if A[x] < A[y] then begin B[z] = A[x]; x = x+1 end ---else begin B[z] = A[y]; y = y+1 end ---z=z+1 ---end for k =i to j do A[k] = B[k] end O(n(logn))
delete from BST
delete(X, node){ if(node = NULL) //nothing to do ---return if(X < node.data) ---delete(X, node.lef tChild) else if(X > node.data) ---delete(X, node.rightChild) else { // found the node to be deleted! Take action based on number of node children ---if(node.lef tChild = NULL and node.rightChild = NULL){ ------delete node ------node = NULL ------return } ---else if(node.lef tChild = NULL){ ---tempNode = node ---node = node.rightChild ---delete tempNode } else if(node.rightChild = NULL){ ---(similar to the case when node.lef tChild = NULL) } else { ---//replace node.data with minimum data from right subtree ---tempNode = f indM in(node.rightChild) ---node.data = tempNode.data ---delete(node.data,node.rightChild) } } }
findmin binary search tree
findMin(T) if (t = null) return null if (t.left = null) return t return findMin(t.left)
MCSS linear
for (int j = 0; j < seq.length; j++) ---thisSum += seq[j] ---if thisSum > result.sum then do ------result.sum = thisSum; --- ---result.startIndex = i ------result.endIndex = j; ---else if thisSum < 0 then ------i = j + 1; ------thisSum = 0 ------end ---end return result end
Height of a Vertex v TREE
function HEIGHT(v): ---h=0 ---for each child w of v do h = MAXIMUM(h, HEIGHT(w)+1) ---return h ---end
MIN-HEIGHT of a Vertex v
function MIN-HEIGHT(v) h = 0 initialize a queue to contain the pair v,h while v is not a leaf do begin ---b,h = DEQUEUE ---for each child w of v do ENQUEUE(w,h+1) ---end return h end
Binary Search recursive
function RBS(a,b) ---if a<b then begin ------m=[(a+b)/2] ------if x<= A[m] then return RBS(a,m) else return RBS(m+1,b) ------end ---else if x = A[a] then return a ---else return -1 ---end O(log(n))
Traversing Linked List from a specified vertex
function SEARCHTAIL(d,v,L) ---if v=nil then return nil ---else if d = DATA(V) then return v ---else return SEARCHTAIL(d,NEXT(v),L) ---end function SEARCH(d,L) ---SEARCHTAIL(d,FIRST(L),L) ---end
Sum the data in vertices v through w linked list
function SUM(v,w,L) ---if v=w ------then return DATA(w) ------else return DATA(v)+SUM(NEXT(v),w,L) ---end
summing odd integers recursive version Induction
function SUMODD(n) ---if n=0 then return 0 else return SUMODD(n-1)+(2n-1) ---end induction can be used to show that for all inputs n>= 0, the program computes x=n^2 Basis: for input n =0 , SUMODD returns 0 Inductive Step: for inputs n>1, assume the theorem is true for all inputs in the range 0 through n01, so inparticular, on input (n-1) it computes (n-1)^2. Since the sum of the first n odd numbers is the same as the sum of the first n-1 plus the addition term (2n-1), the program correctly returns: (n-1)^2 + (2n-1) = (n^2 - 2n + 1) + (2n -1) = n^2
Evaluating postfix expression with a stack
function postEVAL ---for i:=1 to n do begin ------if P[i] is a value then PUSH(P[i]) ------else if P[i] is a binary operator then begin ---------if S is empty then ERROR - missing value ---------b := POP ---------if S is empty then ERROR - missing value ---------a := POP ---------PUSH(the result of applying P[i] to a,b) ---------end ------else ERROR -illegal input ------end -----if stack has only one item then return POP else ERROR - missing operator ---end
insertion in BST
if tree is empty create a root node with the new key else compare key with the top node if key = node key replace the node with the new value else if key > node key ---compare key with the right subtree: --- if subtree is empty ---create a leaf node ---else add key in right subtree else key < node key ---compare key with the leA subtree: ---if the subtree is empty create a leaf node ---else add key to the leA subtree
Bellman-Ford (pseudocode)
procedure BellmanFord() ----- for each v : V ---------- d[v] = infinity; ----- d[s] = 0; ----- for i=1 to |V|-1 --------------- for each edge (u,v) : E -------------------- Relax(u,v, w(u,v)); ----- for each edge (u,v) : E ---------- if (d[v] > d[u] + w(u,v)) --------------- return "no solution"; ::: Running Time: O(VE)
Djikstra (pseudocode)
procedure Dijkstra(G) ----- for each v : V ---------- d[v] = infinity; ----- d[s] = 0; S = 0; Q = V; ----- while (Q != 0) ---------- u = ExtractMin(Q); ---------- S = S U {u}; ---------- for each v : u->Adj[] ---------- if (d[v] > d[u]+w(u,v)) --------------- d[v] = d[u]+w(u,v); ::: Running Time: O(V^2)
Ford-Fulkerson (4 lines of code) (pseudocode)
procedure FordFulkerson() ----- initialize flow f to 0; ----- while (there exists an augmenting path p) --------- do augment flow f along path p; ----- return f; ::: Running Time: O(Ef)
MCSS Cubic (pseudocode)
procedure MCSS(int[] a) ----- int maxSum = 0 ----- for(int i = 0; i < a.length; i++) ---------- for(int j = i; j < a.length; j++) --------------- int thisSum = 0;; --------------- for(int k = i; k <= j; k++) -------------------- thisSum += a[k]; --------------- if(thisSum > maxSum) -------------------- maxSum = thisSum; -------------------- seqStart = i; -------------------- seqEnd = j; ----- return maxSum; ::: Running Time: O(n^3)
MCSS Quadratic (pseudocode)
procedure MCSS(int[] a) ----- int maxSum = 0 ----- for(int i = 0; i < a.length; i++) ---------- int thisSum = 0;; ---------- for(int j = i; j < a.length; j++) --------------- thisSum += a[j]; --------------- if(thisSum > maxSum) -------------------- maxSum = thisSum; -------------------- seqStart = i; -------------------- seqEnd = j; ----- return maxSum; ::: Running Time: O(n^2)
Pre-Order Traversal trees
procedure PRE(v): ---{vist v} ---for each child w of v do PRE(w) ---end PRE(root)
Reverse a singly linked list
procedure REVERSE(L) ---if (SIZE(L)>1)then begin ------d = DELETE(FIRST(L),L) ------REVERSE(L) ------INSERT(d,LAST(L),L) ------end ---end
Post-Order Traversal tree
procedure first-to-lastPRE(v): ---{visit v} ---w = LMCHILD(v) ---while (w is not nil) do begin ------first-to-lastPRE(w) ------w=RSIB9w) ------end ---end
Find Binary Search Tree (pseudocode)
procedure searchBST(T,z) ----- if T is null: ---------- return null ----- if T.val == z: ---------- return T ----- if T.val < z ---------- return searchBST(node.right,z) ----- return searchBST(node.left,z) ::: Running Time: O(n)
Ternary Search (pseudocode)
procedure ternarySearch (A, key, start, end) ----- if (start > end) ---------- return false; ----- // First boundary: add 1/3 of length to start. ----- int mid1 = start + (end-start) / 3; ----- // Second boundary: add 2/3 of length to start. ----- int mid2 = start + 2*(end-start) / 3; ----- if (A[mid1] == key) ---------- return true; ----- else if (A[mid2] == key) ---------- return true; ----- else if (key < A[mid1]) ---------- // Search 1st third. ---------- return ternarySearch (A, key, start, mid1-1); ----- else if (key > A[mid2]) ---------- // Search 3rd third. ---------- return ternarySearch (A, key, mid2+1, end); ----- else ---------- // Middle third. ---------- return ternarySearch (A, key, mid1,mid2); ::: Running Time: O(log N)
proof by induction example: Summing powers of 2
repeatedly double a variable p and add it on to a running total that is kept in the variable x: input n x = p = 1 for i =1 to n do begin ---p = 2*p ---x = x+p ---end output x Induction can be used to show that for all inputs n >=0 the program computes x = 2^(n+1) - 1. (basis) : For input n=0: x = 1 = 2^(0+1) - 1 (inductive step) : for input n > 0, assume the theorem true for all inputs in the range 0 through n-1 (so in particular, on input n-1 it computes 2^((n-1)+1) -1. since on input n the program executes the same instructions as for input n-1 and then executes one additional iteration of the loop (where it adds 2^n to the current value of x), it computes: x = (2^((n-1)+1) - 1) + 2^n = 2*2^n - 1 = 2^(n+1) - 1 S = 1 +2+4+...+2^n 2S = 2+4+...+2^n +2^n+1 then the terms in 2S are the same as for S except for the first term of S and the last term of 2S, and hence S = (2S-S) = 2^(n+1) -1
Circular Queue(FRONT and REAR)
simply return the front and rear data items of the queue Q: ---function FRONT(Q) if size = 0 then {error} else return Q[front] end ---function REAR(Q) ------if size = 0 then {error} ------else if rear = 0 then return Q[n-1] ------else return Q[rear-1] ------end
level - order traversal tree
visit the child of a vertex v before going deeper into the subtrees, so that vertices are visited from highest to lowest level. procedure LEV(v): initialize a queue to contain a root. while queueu is not empty do begin ---v = DEQUEUE ---{visit} ---for each child w of v do ENQUEUE(w) ---end end LEV(root)
in-order traversal of a binary search tree
visit the left subtree, visit the root, visit the right subtree. procedure IN(v) ---if v != nil then begin ------IN(LCHILD(v)) ------{visit} ------IN(RCHILD(v)) ------end ---end IN(root)
inorder linked list tree
void inOrder(Tree *tree){ if (tree->isEmpty( )) return; inOrder(tree->getLegSubtree( )); visit(tree->getRoot( )); inOrder(tree->getRightSubtree( )); }
post order linked list tree
void postOrder(Tree *tree){ if (tree->isEmpty( )) return; postOrder(tree->getLegSubtree( )); postOrder(tree->getRightSubtree( )); visit(tree->getRoot( )); }
preorder linked list tree
void preOrder(Tree *tree){ if (tree->isEmpty( )) return; visit(tree->getRoot( )); preOrder(tree->getLegSubtree()); preOrder(tree->getRightSubtree()); }
best first
• Best first traversal explores a tree by expanding the most promising node chosen according to a specified rule or priority [This is usually associated with the class of algorithms called Greedy Algorithms]
what is huffman coding
• Huffman coding is a technique used to compress files for transmission • Uses statistical coding - more frequently used symbols have shorter code words • Works well for text and fax transmissions • An application that uses several data structures