2-2 Correctness of bubblesort

Bubblesort is a popular, but inefficient, sorting algorithm. It works by repeatedly swapping adjacent elements that are out of order.

1
2
3
4
5
BUBBLESORT(A)
    for i = 1 to A.length - 1
        for j = A.length downto i + 1
            if A[j] < A[j - 1]
                exchange A[j] with A[j - 1]

a. Let $A'$ denote the output of $\text{BUBBLESORT}(A)$ To prove that $\text{BUBBLESORT}$ is correct, we need to prove that it terminates and that

$$A'[1] \le A'[2] \le \cdots \le A'[n], \tag{2.3}$$

where $n = A.length$. In order to show that $\text{BUBBLESORT}$ actually sorts, what else do we need to prove?

The next two parts will prove inequality $\text{(2.3)}$.

b. State precisely a loop invariant for the for loop in lines 2–4, and prove that this loop invariant holds. Your proof should use the structure of the loop invariant proof presented in this chapter.

c. Using the termination condition of the loop invariant proved in part (b), state a loop invariant for the for loop in lines 1–4 that will allow you to prove inequality $\text{(2.3)}$. Your proof should use the structure of the loop invariant proof presented in this chapter.

d. What is the worst-case running time of bubblesort? How does it compare to the running time of insertion sort?

a. $A'$ consists of the elements in $A$ but in sorted order.

b. Loop invariant: At the start of each iteration of the for loop of lines 2-4, the subarray $A[j..n]$ consists of the elements originally in $A[j..n]$ before entering the loop but possibly in a different order and the first element $A[j]$ is the smallest among them.

Initialization: Initially the subarray contains only the last element $A[n]$, which is trivially the smallest element of the subarray.

Maintenance: In every step we compare $A[j]$ with $A[j - 1]$ and make $A[j - 1]$ the smallest among them. After the iteration, the length of the subarray increases by one and the first element is the smallest of the subarray.

Termination: The loop terminates when $j = i$. According to the statement of loop invariant, $A[i]$ is the smallest among $A[i..n]$ and $A[i..n]$ consists of the elements originally in $A[i..n]$ before entering the loop.

c. Loop invariant: At the start of each iteration of the for loop of lines 1-4, the subarray $A[1..i − 1]$ consists of the $i - 1$ smallest elements in $A[1..n]$ in sorted order. $A[i..n]$ consists of the $n - i + 1$ remaining elements in $A[1..n]$.

Initialization: Initially the subarray $A[1..i − 1]$ is empty and trivially this is the smallest element of the subarray.

Maintenance: From part (b), after the execution of the inner loop, $A[i]$ will be the smallest element of the subarray $A[i..n]$. And in the beginning of the outer loop, $A[1..i − 1]$ consists of elements that are smaller than the elements of $A[i..n]$, in sorted order. So, after the execution of the outer loop, subarray $A[1..i]$ will consists of elements that are smaller than the elements of $A[i + 1..n]$, in sorted order.

Termination: The loop terminates when $i = A.length$. At that point the array $A[1..n]$ will consists of all elements in sorted order.

d. The $i$th iteration of the for loop of lines 1-4 will cause $n − i$ iterations of the for loop of lines 2-4, each with constant time execution, so the worst-case running time of bubble sort is $\Theta(n^2)$ which is same as the worst-case running time of insertion sort.

However, insertion sort has best-case running time of $\Theta(n)$ which is faster than the best-case running time $\Theta(n^2)$ of bubble sort.