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.)
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
}
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...
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;
}
}
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;
}
}
}
}
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.
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.
Think about the maximum number of times the do loop can execute.
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;
}
}
}
Related
I'm trying to write a simple bubble sort algorithm but it isn't working. The array is unchanged when it is printed at the end.
I have used the debugging tools on my IDE and it tell's me that the second for loop isn't incrementing but I can't tell why it isn't.
I'm still new to learning C++ and algorithms in general, so pointers on this would be helpful.
Here's the code, many thanks.
#include <iostream>
int main(){
int A[] = {13, 89, 43, 74, 45, 16};
int n = sizeof(A)/sizeof(*A);
for (int i=0; i<n; i++) { //pass through the algorithm n-1 times
int flag = 0;
for (int j=0; j<n-i-1; j++) { //optimise checks, avoid checking sorted part of array
if (A[j] > A[j+1]) {
int temp = A[j];
A[j] = A[j+1];
A[j+1] = temp;
flag = 1; //shows a swap happened
}
if (flag == 0) { //no swaps have occurred so the loop is over
break;
}
}
}
for (int i = 0; i < n; i++) {
std::cout << A[i] << " ";
}
return 0;
}
Your algorithm is wrong. You should check the flag after the second loop has finished
int flag = 0;
for (int j=0; j<n-i-1; j++) { //optimise checks, avoid checking sorted part of array
if (A[j] > A[j+1]) {
int temp = A[j];
A[j] = A[j+1];
A[j+1] = temp;
flag = 1; //shows a swap happened
}
}
if (flag == 0) { //no swaps have occurred so the loop is over
break;
}
The fact that you are initialising the flag before the second loop, but checking it inside the second loop should have been a clue that something was not quite right. So should have the debugger telling you that the second loop was not incrementing.
Sometimes when you look at your own code you'll just see what you think you wrote, not what you actually wrote. Looknig at your own code objectively is a habit you need to train yourself to do.
Just One Mistake:
if (flag == 0) { //no swaps have occurred so the loop is over
break;
}
This should be out of the second for-loop.
#include <iostream>
int main(){
int A[] = {13, 89, 43, 74, 45, 16};
int n = sizeof(A)/sizeof(*A);
for (int i=0; i<n; i++) { //pass through the algorithm n-1 times
int flag = 0;
for (int j=0; j<n-i-1; j++) { //optimise checks, avoid checking sorted part of array
if (A[j] > A[j+1]) {
int temp = A[j];
A[j] = A[j+1];
A[j+1] = temp;
flag = 1; //shows a swap happened
}
}
if (flag == 0) { //no swaps have occurred so the loop is over
break;
}
}
for (int i = 0; i < n; i++) {
std::cout << A[i] << " ";
}
return 0;
}
Initially when A[j] > A[j+1] is checked, 13 > 89 is false, flag remains 0 and the break statement executes. That's why there is no change in the array. You should check the flag after the second loop has finished as mentioned in the other answers. Have you heard about rubber duck debugging? Give it a try. It helps a lot.
Trying to write some code, and erase() is giving me a runtime error. What's wrong with the way I used erase?
class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
int size = nums.size();
vector<int> list;
for(int i = 1; i <= size; i++)
list.push_back(i);
for(int i = 0; i < size; i++) {
int num = nums[i];
list[num - 1] = 0;
}
for(int i = 0; i < size; i++) {
if(list[i] == 0) {
list.erase(list.begin() + i);
}
}
return list;
}
};
Here's the problem I am trying to solve
Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.
Find all the elements of [1, n] inclusive that do not appear in this array.
Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.
Example:
Input:
[4,3,2,7,8,2,3,1]
Output:
[5,6]
Since all the non solutions were marked 0, you can remove all 0's in the vector using list.erase( remove (list.begin(), list.end(), 0), list.end() );
My first suggestion, concentrate on this:
for(int i = 0; i < size; i++) {
if(list[i] == 0) {
list.erase(list.begin() + i);
}
}
You are removing elements from list which changes the size. This will lead to accessing elements beyond your list.
I'm having a little problem with getting my head around this homework task. The task says: "Write a function called MoveSmallest that moves all the minimal integer elements at the start of the array. All the remaining items must stay at their places. (the array and its size are parameters)
Example: the array: 2, 3, 5, 1, 2, 3, 6, 4, 2, 1, 1 changes into 1, 1, 1, 2, 3, 5, 2, 3, 6, 4, 2
void MoveSmallest(int A[],int n)
{
int Min;
for(int i=0;i<n;i++)
{
if(i==0)
{
Min=A[i];
}
else if(A[i]<=Min)
{
Min=A[i];
}
}
So far I've only figured to check which one is the smallest element of the array. I don't have any ideas what to do next.
Once you have found the minimum value, all there is left to do is moving things around in order to have the minimum values at the beginning of the array.
You can do this by permuting the values until you have arrived to the "left" of the array (i.e index 0).
void MoveSmallest(int A[],int n)
{
int Min;
for(int i=0;i<n;i++)
{
if(i==0)
{
Min=A[i];
}
else if(A[i]<=Min)
{
Min=A[i];
}
}
for(int i = 0; i < n; i++)
{
if(A[i] == Min)
{
for(int j = i; j > 0; j--)
{
int tmp = A[j];
A[j] = A[j-1];
A[j-1] = tmp;
}
}
}
}
You could also use std::swap to do the permutation, instead of the temporary variable tmp.
Starting from the end of the array, keep track of how many minimal elements you have encountered. Then whenever you encounter a non-minimum element, move it to the right the number of minimal elements you have encountered so far:
void MoveSmallest(int A[], int n)
{
int min;
//Find min logic
//shift non-min elements and count min elements
int cnt = 0;
for (int i = n-1; i >=0; --i)
{
if (A[i] == min)
cnt++;
else
A[i+cnt] = A[i];
}
//Add min elements
for (int i = 0; i < cnt; ++i)
A[i] = min;
}
This will run in O(n) time and O(1) space.
Since your posts mention "basic C++" but not mention what is "basic", here is another solution. This is under the assumption that creating arrays for "work" purposes is considered "basic C++".
void MoveSmallest(int A[], int n)
{
// get the minimum value
int Min = A[0];
for (int i = 1; i < n; ++i)
{
if (A[i] < Min)
Min = A[i];
}
// get the count of the number of minimum values
int minCount = 0;
for (int i = 0; i < n; ++i)
{
if (A[i] == Min)
++minCount;
}
if (minCount > 0)
{
// create a work array and fill in the first
// minCount values with the minimum value
int *B = new int[n];
for (int i = 0; i < minCount; ++i)
B[i] = Min;
// now fill in the rest of the work array with the values
// in the A[] array that are not equal to Min
int current_pos = minCount;
for (int i = 0; i < n; ++i)
{
if (A[i] != Min)
B[current_pos++] = A[i];
}
// Now copy work array back to A array
for (int i = 0; i < n; ++i)
A[i] = B[i];
// get rid of work array
delete[] B;
}
}
Live Example
This runs in linear time O(n), as opposed to quadratic time O(n*n).
The disadvantage of course is that you need room for the work array, so the memory cost is linear O(n).
I am trying out my first nested for loop and I can't seem to see the problem. As the code is written, all 9 values come out as the number '9'. I want them to be 1 through 9.
int arraySize = 9;
for (int i = 0; i < arraySize; i++)
{
for (int j = 1; j < (arraySize + 1); j++)
{
gameBoard[i] = j;
}
}
Been looking at this too long - I am sure the solution is obvious... Thanks for the help.
Your outer loop goes through each slot in the array.
Your inner loop assigns 1 through 9 to current slot of the array.
Since the last assignment of your inner loop is 9, you have an array full of 9s.
You don't need nested loops for this. As Log1c mentioned above, you can do this with a single loop:
for (int i = 0; i < arraySize; i++)
{
gameBoard[i] = i + 1;
}
what would be the c++ equivalent to this matlab code? I started it off but i'm not sure what value B would be, i think A is correct.
MATLAB
array = (-1:.001:1)';
A = max(find(array < 1.0e-2));
B = min(find(array > 1 - 1.0e-2));
C++ attempt
for(i = 0; i < array.size; i++){
if(array[i] < 1.0e-2){
k++
A = k;
}
if(array[i] > (1- 1.0e-2)){
//not sure what to do here
B = ?;
}
}
for(i = 0; i < array.size; i++){ // Would be faster if you reversed loop direction
if(array[i] < 1.0e-2)
A = i;
}
for(i = 0; i < array.size; i++) {
if(array[i] > 1-1.0e-2) {
B = i;
break;
}
}
For the second bit, I would do this instead inside the same loop:
if(array[array.size-i-1] > (1 - 1.0e-2)) B = array.size - i;
and initialize B to array.size before the loop.
Essentially, you are finding the element with the lowest index in the array which is also larger than 1 - 1.0e-2. If you start at the element with the highest index and then traverse the entire array and update each time you satisfy the criteria, you will end up with what you need. A similar logic applies for the first part, but you will need to set A = i+1 instead of incrementing k because there is no guarantee the array is sorted.
Basically the command A = max(find(array < 1.0e-2)); Is looking for the largest index of the array that is greater than 1.02e-2.
To see how this happens just break down the statement into parts:
array < 1.0e-2) returns a vector of logical indices.
find( ... ) converts the logical indices to numeric indices
max(...) returns the largest value from the list of numeric indices.
A C++ equivalent would look something like:
int A = -1;
int maxVal = 1.0e-2;
for (int i = array.length-1; i>=0; i--)
if (array[i] < maxVal){
A = i;
break;
}
To get B just setup another loop:
int B = -1;
int minVal = 1 - 1.0e-2;
for (int i=0; i<array.length; i++)
if (array[i] > minVal){
B = i;
break;
}