Reputation: 58097
I'm looking to implement a bubble sort. I have the following code that I wrote, which uses a for
loop inside of a do
loop. How can I make this into a bubble sort that uses two for
loops?
Here's my code:
do {
switched = false;
for (int i = 1; i < size; i++) {
if (a[i] < a[i-1]) {
int temp = a[i];
a[i] = a[i-1];
a[i-1] = temp;
switched = true;
}
}
} while (switched);
(This is tagged homework, but this is studying for the final exam, not actual homework.)
Upvotes: 2
Views: 446
Reputation: 18652
A simple improvement to bubble sort is to remember the last location where a swap occurred. After each pass the elements beyond that point are sorted. Next time through the loop only iterate up to the previous high water mark.
void bubble_sort(int *arr, int size)
{
for (int hwm; size > 1; size = hwm)
{
hwm = 0;
for (int i = 1; i < size; ++i)
{
if (arr[i] < arr[i-1])
{
std::swap(arr[i], arr[i-1]);
hwm = i;
}
}
}
}
Upvotes: 1
Reputation: 82599
Because you know the last element in the list will always be sorted (since it bubbled up to the top) you can stop there.
for(int x = size; x >= 0; x--) {
bool switched = false;
for(int i = 1; i < x; i++) {
if(blah) {
// swap code here
switched = true;
}
}
if(!switched) break; // not the biggest fan of this but it gets the job done
}
Upvotes: 6
Reputation: 417
Since the maximum number of times your inner loop will run is size
times, you know that the outer loop only can be bound by size
.
for (int x = 0; x < size; x++ )
{
switched = false;
for (int i = 1; i < size; i++)
{
if (a[i] < a[i - 1])
{
int temp = a[i];
a[i] = a[i - 1];
a[i - 1] = temp;
switched = true;
}
}
if(switched)
{
break;
}
}
Upvotes: 3
Reputation: 1570
A really silly method to use two for loops would be as follows:
for(bool switched=true;switched;)
{
switched=false;
for(int i=1; i<size; ++i)
{
if (a[i] < a[i-1])
{
int temp = a[i];
a[i] = a[i-1];
a[i-1] = temp;
switched = true;
}
}
}
A more serious answer might be as below... but now that I think about it this probably is not bubble sort:
for(int i=0; i<(size-1); ++i)
{
for(int j=(i+1); j<(size-1); ++j)
{
if(a[i]>a[j])
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
Upvotes: 0
Reputation: 308530
Think about the maximum number of times the do
loop can execute.
Upvotes: 0
Reputation: 393924
A bit obligate, but hey, you asked for it:
for(bool switched=true; switched;)
{
switched = false;
for (int i = 1; i < size; i++) {
if (a[i] < a[i-1]) {
int temp = a[i];
a[i] = a[i-1];
a[i-1] = temp;
switched = true;
}
}
}
Two for loops...
Upvotes: 5
Reputation: 183602
The first full pass through the loop (that is, the first iteration of your outer do
loop) is guaranteed to put the largest element in position a[size - 1]
. (Do you see why?) The next full pass is guaranteed not to change that, and, in addition, to put the second-largest element in position a[size - 2]
. (Again, do you see why?) And so on. So the first pass needs i
to go from 1
to size - 1
, but the second only needs i
to go from 1
to size - 2
, the third only needs i
to go from 1
to size - 3
, and so on. Overall, you need at most size - 1
passes (with the last pass just covering position 1
and comparing a[1]
to a[0]
to make sure the smallest element is in place).
So, your outer for
-loop needs to vary max_i
, initially set to size - 1
and ending up at 1
, and your inner for
-loop needs to vary i
from 1
to max_i
.
Upvotes: 0
Reputation:
You can run the inside loop size
times instead of checking switched
, by having an outer loop for(int j=0; j<size; ++j)
. To make it slightly less badly inefficient you can make the inner loop 1 step shorter each time.
Upvotes: 0