Docsity
Docsity

Prepare for your exams
Prepare for your exams

Study with the several resources on Docsity


Earn points to download
Earn points to download

Earn points by helping other students or get them with a premium plan


Guidelines and tips
Guidelines and tips

Explanation of Bubble Sort Algorithm and Its Correctness, Exams of Data Structures and Algorithms

An explanation of the bubble sort algorithm, its working, and the proof of its correctness using loop invariants. It also compares the worst-case running time of bubble sort with insertion sort.

Typology: Exams

2012/2013

Uploaded on 04/07/2013

seshu_lin3
seshu_lin3 🇮🇳

4

(3)

59 documents

1 / 4

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
CSE3358 Problem Set 1
Solution
Please review the Homework Honor Policy on the course webpage
http://engr.smu.edu/˜saad/courses/cse3358/homeworkpolicy.html
Problem 1: Bubble sort
We have studied Insertion sort in class and argued that it works correctly.
INSERTION-SORT(A)
1for j2to length[A]
2do keyA[j]
3ij1
4while i > 0 and A[i]> key
5do A[i+ 1]A[i]
6ii1
7A[i+ 1]key
At the beginning of each iteration of the “outer” for loop, which is indexed by j, the subarray consisting
of elements A[1..j 1] constitute the currently sorted elements, and the elements A[j+ 1..n], where
n=length[A], correspond to the elements that are still to be considered. In fact, elements A[1..j 1]
are the elements originally in positions 1 through j1, but now in sorted order. We can state this
property of A[1..j 1] formally as a loop invariant:
LOOP INVARIANT: At the start of each iteration of the for loop of lines 1-7, the subarray A[1..j 1]
consists of the elements originally in A[1..j 1] but in sorted order.
We use loop invariants to help us understand why an algorithm is correct. We must show three things
about a loop invariant:
Initialization: It is true prior to the first iteration of the loop
Maintenance: If it is true before an iteration of the loop, it remains true before the next
iteration
Termination: When the loop terminates, the invariant gives us a useful property that helps
show that the algorithm is correct
Let us see how these properties hold for insertion sort.
Initialization: We start by showing that the loop invariant holds before the first loop iteration, when
j= 2. The subarray A[1..j 1] = A[1..21] = A[1..1] = A[1], consists of just the single element A[1],
which is in fact the original element in A[1]. Moreover, this subarray is sorted (trivially, of course),
which shows that the loop invariant holds prior to the first iteration of the loop.
Maintenance: Next, we tackle the second property: showing that each iteration maintains the loop
invariant. Informally, the body of the outer for loop works by moving A[j1], A[j2], A[j3],
1
pf3
pf4

Partial preview of the text

Download Explanation of Bubble Sort Algorithm and Its Correctness and more Exams Data Structures and Algorithms in PDF only on Docsity!

CSE3358 Problem Set 1 Solution

Please review the Homework Honor Policy on the course webpage http://engr.smu.edu/˜saad/courses/cse3358/homeworkpolicy.html

Problem 1: Bubble sort We have studied Insertion sort in class and argued that it works correctly.

INSERTION-SORT(A) 1 for j← 2 to length[A] 2 do key←A[j] 3 i←j − 1 4 while i > 0 and A[i] > key 5 do A[i + 1]←A[i] 6 i←i − 1 7 A[i + 1]←key

At the beginning of each iteration of the “outer” for loop, which is indexed by j, the subarray consisting of elements A[1..j − 1] constitute the currently sorted elements, and the elements A[j + 1..n], where n = length[A], correspond to the elements that are still to be considered. In fact, elements A[1..j − 1] are the elements originally in positions 1 through j − 1, but now in sorted order. We can state this property of A[1..j − 1] formally as a loop invariant:

LOOP INVARIANT: At the start of each iteration of the for loop of lines 1-7, the subarray A[1..j − 1] consists of the elements originally in A[1..j − 1] but in sorted order.

We use loop invariants to help us understand why an algorithm is correct. We must show three things about a loop invariant:

  • Initialization: It is true prior to the first iteration of the loop
  • Maintenance: If it is true before an iteration of the loop, it remains true before the next iteration
  • Termination: When the loop terminates, the invariant gives us a useful property that helps show that the algorithm is correct

Let us see how these properties hold for insertion sort.

Initialization: We start by showing that the loop invariant holds before the first loop iteration, when j = 2. The subarray A[1..j − 1] = A[1.. 2 − 1] = A[1..1] = A[1], consists of just the single element A[1], which is in fact the original element in A[1]. Moreover, this subarray is sorted (trivially, of course), which shows that the loop invariant holds prior to the first iteration of the loop.

Maintenance: Next, we tackle the second property: showing that each iteration maintains the loop invariant. Informally, the body of the outer for loop works by moving A[j − 1], A[j − 2], A[j − 3],

and so on by one position to the right until the proper position for A[j] is found (lines 3-6), at which point the value of A[j] is inserted (line 7). A more formal treatment of this property would require us to state and show a loop invariant for the inner while loop (but we will not do it at this point).

Termination: Finally, we examine what happens when the loop terminates. For insertion sort, the outer for loop ends when j exceeds n, i.e. when j = n + 1. Substituting n + 1 for j in the wording of the loop invariant, we have that the subarray A[1..n] consists of the elements originally in A[1..n], but in sorted order. But the subarray A[1..n] is the entire array! Hence, the entire array is sorted, which means that the algorithm is correct.

Consider the following algorithm known as Bubble sort. It works by repeatedly swapping adjacent elements that are out of order:

BUBBLE-SORT(A)

1 for i← 1 to length[A] 2 do for j←length[A] downto i + 1 3 do if A[j] < A[j − 1] 4 then exchange A[j] ↔ A[j − 1]

(a) (5 points) Explain in english, very clearly, how the algorithm BUBBLE-SORT works (for this you need to understand what the code is doing and construct from it a process in your mind, one thing you could do to help is try it on some small examples, say 6 numbers, and see what it is doing).

ANSWER: BUBBLE-SORT works by first scanning the array A from A[n] all the way down to A[1] and exchanging any adjacent elements that are out of order. This first scan guarantees that the smallest element in A[1..n] (i.e. the smallest element of A) will end up in A[1]. BUBBLE-SORT then scans the array A for a second time from A[n] all the way down to A[2] and exchanges again any adjacent elements that are out of order. This second scan guarantees that the smallest element in A[2..n] (i.e. the next smallest element of A) will end up in A[2]. BUBBLE-SORT continues to perform scans in this way (up tp n scans), and in every scan it guarantees that the element with rank i ends up in A[i]. After the last scan, the array A is sorted.

(b) (5 points) Let A′^ denote the output of BUBBLE-SORT(A). To prove that BUBBLE-SORT is correct, we need to prove that (1) it terminates and that (2) A′[1] ≤ A′[2] ≤...≤ A′[n], where n = length[A]. What else must we proved to show that BUBBLE-SORT actually sorts?

ANSWER: We need to show also that A′^ is some permutation of A. Otherwise, there is no guarantee that the elements of A′^ are those of A. For instance, here’s an algorithm that takes an array A as input, terminates, and produces an array A′^ such that A′[1] ≤ A′[2] ≤...≤ A′[n], but does not necessarily sort A.

FUNNY-SORT(A) 1 for i← 1 to length[A] 2 do A[i]←i

Maintenance: We need to show that each iteration maintains the loop invariant. Assume the loop invariant holds prior to iteration i, i.e. the subarray A[1..i − 1] contains the smallest (i − 1) elements of A in sorted order. We need to show that the invariant still holds prior to iteration i + 1. Let’s see what happens in iteration i. In iteration i, we place the smallest element of A[i..n] in A[i] without touching A[1..i − 1]. Therefore, the smallest i elements of A will be in the subarray A[1..i] in sorted order prior to iteration i + 1.

Termination: Finally we examine what happens when the loop terminates. The loop ends when i exceeds length[A] = n, i.e. when i = n + 1. Substituting n + 1 for i in the wording of the loop invariant, we have that the subarray A[i..n] contains the smallest n elements of A in sorted order. But this is the whole array, which gives the desired result.

(e) (5 points) What is the worst-case running time of BUBBLE-SORT? Use Θ notation as we did in class. How does it compare to the running time of insertion sort?

ANSWER:

BUBBLE-SORT(A)

1 for i← 1 to length[A] 2 do for j←length[A] downto i + 1 Θ(n − i) 3 do if A[j] < A[j − 1] Θ(1) 4 then exchange A[j] ↔ A[j − 1] Θ(1)

As we can see from the above, the running time T (n) =

∑n i=1 Θ(n^ −^ i)[Θ(1) + Θ(1)] =^

∑n i=1 Θ(n^ − i)Θ(2) =

∑n i=1 Θ(n^ −^ i)Θ(1) =^

∑n i=1 Θ(n^ −^ i) = Θ(

∑n i=1(n^ −^ i)) = Θ((n^ −^ 1)n/2) = Θ(n (^2) ). So this is

comparable to Insertion sort in terms of asymptotic efficiency.

(f) (5 points) Which one you think is faster in practice, INSERTION-SORT or BUBBLE-SORT, and why?

ANSWER: Regardless of the input array A, Bubble sort scans A[1..n], then A[2..n], then A[3..n], ..., A[n..n]. Therefore, the amount of work done by BUBBLE-SORT is Θ(n + (n − 1) + (n − 2) + ... + 1) which is equal to Θ(1 + 2 + ... + (n − 1) + n). This is the worst-case scenario of Insertion sort where in every iteration the maximum amount of shifting is done. Therefore, practically, Insertion sort performs better than Bubble sort.

(g) (10 points) Implement both in any programming language of your choice. Try them on randomly generated inputs of size 10, 20, 50, 100, 500, 1000. Report their real running times as measured by the system clock. Does the numbers agree with your intuition on part (f)?