Why Bubble Sort needs nested loops? - c++

I am going to start the new question. I posed the question yesterday and wanted to know what's the problem in my program. The program is given below and you people pointed out that this following program does only one pass of the sorting and needs an outer loop as well. At that time I was good like OK. But again when I looked the program I got confused and need to ask Why we need Outer loop as well for the sort since only a single loop can do the sorting(In my opinion). First see program below then I present my logic at the end of the program.
#include <iostream.h>
#include <conio.h>
using namespace std;
main()
{
int number[10];
int temp = 0;
int i = 0;
cout << "Please enter any ten numbers to sort one by one: "
<< "\n";
for (i = 0; i < 10; i++)
{
cin >> number[i];
}
i = 0;
for (i = 0; i < 9; i++)
{
if (number[i] > number[i + 1])
{
temp = number[i + 1];
number[i + 1] = number[i];
number[i] = temp;
}
}
i = 0;
cout << "The sorted numbers are given below:"
<< "\n";
for (i = 0; i < 10; i++)
{
cout << number[i] << "\n";
}
getch();
}
I think the ONLY loop with the bubble condition should do the sorting. Look at the following loop of the program:
for (i=0;i<9;i++)
if(number[i]>number[i+1])
{
temp=number[i+1];
number[i+1]=number[i];
number[i]=temp;
}
Now I explain what I am thinking what this loop "should" do. It will first compare number[0] with number[1]. If the condition is satisfied it will do what is in IF statement's body. Then i will be incremented by 1(i++). Then on next iteration the values compared will be number[1] with number[2]. Then why it does not happen and the loop exits after only pass? In other words may be I'm trying to ask IF statement does not repeat itself in for loop? In my opinion it does. I'm very thankful for help and views, my question might be of small level but that is how I will progress.

Let me give you an example let's only take 3 numbers. So you input
13, 3 ,1
Now you start sorting how you did it. so it compares 13 and 3
13 > 3 so switch both of them.
now we have.
3, 13, 1
Now it'll compare as you said the next pair = 13 and 1
13 > 1 so the new order would be
3, 1, 13
now your loop is finished and you missed to compare 3 and 1
Actually the first loop only sorts the greatest number!

since only a single loop can do the sorting(In my opinion)
This is not correct. Without getting to details, a constant number of loops is not enough to sort, since sorting is Omega(nlogn) problem. Meaning, an O(1) (constant, including 1) number of loops is not enough for it - for any algorithm1,2.
Consider the input
5, 4, 3, 2, 1
a single loop of bubble sort will do:
4, 5, 3, 2, 1
4, 3, 5, 2, 1
4, 3, 2, 5, 1
4, 3, 2, 1, 5
So the algorithm will end up with the array: [ 4, 3, 2, 1, 5], which is NOT sorted.
After one loop of bubble sort, you are only guaranteed to have the last element in place (which indeed happens in the example). The second iteration will make sure the 2 last elements are in place, and the nth iteration will make sure the array is indeed sorted, resulting in n loops, which is achieved via a nested loop.
(1) The outer loop is sometimes hidden as a recursive call (quick sort is an example where it happens) - but there is still a loop.
(2) Comparisons based algorithms, to be exact.

For bubble sorting a pass simply moves the largest element to the end of array. So you need n-1 passes to get a sorted array, thats why you need other loop. Now for your code 1 pass means
if(number[0]>number[0+1])
{
temp=number[0+1];
number[0+1]=number[0];
number[0]=temp;
}
if(number[1]>number[1+1])
{
temp=number[1+1];
number[1+1]=number[1];
number[1]=temp;
}
.....6 more times
if(number[8]>number[8+1])
{
temp=number[8+1];
number[8+1]=number[8];
number[8]=temp;
}
so as you can see IF statement repeats itself, its just that after all 9 IFs the largets element moves to the end of array

This is not correct because
The algorithm gets its name from the way smaller elements "bubble" to the top of the list. (Bubble sort)
So, at the end of the first loop, we get the smallest element. So, for complete sorting, we have to keep total n loops. (where n = total size of the numbers)

Related

Why didn't my alternative sorting algorithm work?

I was trying to implement a sorting code so i tried something completely without looking at any other reference codes or anything. Please tell me why my code doesnt show any output? It just runs for sometime and then stops suddenly.
I want to know where i am going wrong. I wanted to take any array as an input and sort the numbers in it in ascending order. So i just iterated throughput the array and compared adjacent elements and swaped them. Then i tried printing the numbers using their indices but it did not print anything on the screen.
#include <iostream>
using namespace std;
int main() {
int arr[6]={1,23,2,32,4,12};
int i=0;
while(i<6)
{
if(arr[i]>arr[i+1])
{
int x = arr[i];
arr[i]=arr[i+1];
arr[i+1]=x;
}
else
continue;
i++;
}
cout<<arr[0];
cout<<arr[1];
cout<<arr[2];
cout<<arr[3];
cout<<arr[4];
cout<<arr[5];
return 0;
}
I expected that the numbers will be printed in ascending order but nothing happened. And also tell me how to print an array all at once.
Thank you
Your sorting algorithm doesn't work because it performs only one pass of a variant of Bubble Sort or Insertion Sort. There has to be one more loop wrapped around your loop to repeat the operation N-1 times.
There are a number of ways to explain why multiple passes are required. Here is one explanation. Whenever we perform this step:
if (arr[i] > arr[i+1])
{
int x = arr[i];
arr[i] = arr[i+1];
arr[i+1] = x;
}
we transfer the arr[i+1] element into the arr[i] position. By doing so, we effectively skip the arr[i+1] element.
Here is what I mean. Suppose arr[i] is called x, arr[i+1] is called y and arr[i+2] is called z. We start with xyz, and exchange x and y to make yxz. But then on the next iteration of the loop, we compare x and z and have forgotten about y; x has moved forward in the array, pushing down y. Why is that a problem? Because y and z have not been compared; and those two are not necessarily in sorted order!
Suppose we have { 3, 2, 0 }. We compare 3 and 2, and swap them, giving us { 2, 3, 0}. Then we move on to comparing 3 and 0: we swap those and get { 2, 0, 3 }. See the problem? We neglected to deal with 2 and 0. That requires another pass through the array.
There is a family of algorithms which work by repeatedly scanning through an array and exchanging items. I suggest studying the following of the common algorithms in this family: insertion sort, selection sort and Shell sort. Also look at bubble sort, in order to understand why it's a poor algorithm compared to either insertion or selection sort that it is closely related to.
your loop condition is incorrect - the last iteration will compare arr[5] and arr[6] which gives index out of bound.
you update your iterator "i" only if you swap, so if your loop encounters the case where arr[i] <= arr[i+1], your iterator will never get updated and your program will run infinitely.
your algorithm implements just a first iteration of bubble sort i.e. it bubbles up (from left to right) the largest number and stops. so the final array looks like [1, 2, 23, 4, 12, 32]

How to compare all elements of vector one to vector two and if a max element exists then comparing all the elements of vector two to vector three?

I want to compare all element of vector x to all elements of vector y and if I find a element greater in vector y than being compared to, I have to take that particular element of vector y and compare to all elements of vector z and if it is true return true else if i don't find a greater element in first iteration i,e when elements of vector x are compared to vector y i have to break the loop and return false.
I tried to iterate through all the elements of stackarmies but I don't know how to take the first element of vector one and compare with all the elements of vector, since all the vectors are merged into the last vector.
vector<int> stack;
int noofstack, noofoperations, stackno, OperationType;
// Taking the input number of stacks
cin >> noofstack;
vector<vector<int>> stackarmies;
for (int i = 0; i < noofstack; i++)
{
int stacksize;
//Since vectors are dynamic and we don't need to declare the size but as per the problem statement I've added it/
cin >> stacksize;
for (int k = 0; k < stacksize; k++)
{
//Taking the input of all the vectors one by one and then adding all the vectors into one vector
int armyheight;
cin>>armyheight;
stack.push_back(armyheight);
}
stackarmies.push_back(stack);
Test cases
Input 1
2
3 3 5 4
3 1 1 2
Resulting stackarmies: { {3, 5, 4}, {3, 5, 4, 1, 1, 2} }
Desired output: False
We will take first element of vector 1 : 3 and compare with all
elements of vector 2 , in vector 2 no element is greater than 3.
Input 2
2
3 1 0 4
3 2 1 3
Resulting stackarmies: { {1, 0, 4}, {1, 0, 4, 2, 1, 3} }
Desired output: True
We will take first element of vector 1 : 1 and compare with all
elements of vector 2, in vector 2, the first element is greater than 1,
so true
Input 3
2
3 1 9 0
2 0 11
Resulting stackarmies: { {1, 9, 0}, {1, 9, 0, 0, 11} }
Desired output: True
We will take first element of vector 1 : 1 and compare with all
elements of vector 2, in vector 2, the last element is greater than 1,
so true
Input 4
3
3 0 8 0
3 4 0 11
3 0 9 0
Resulting stackarmies: { {0, 8, 0}, {0, 8, 0, 4, 0, 11} , {0, 8, 0, 4, 0, 11, 0, 9, 0} }
Desired output: True
We will take the second element of vector 1: 8 and compare with
all elements of vector 2 , 11 is greater than 8 so we will compare 11 of
vector 2 with vector , since there are no values greater than 11, so it's
false
I don't know how to take the first element of vector one and compare with all the elements of vector, since all the vectors are merged into the last vector.
You're getting ahead of yourself. Why do you want all the vectors merged into the last vector? Answer: you don't; that's just what happened. Why did all the vectors merge into the last vector? Answer: because you have a bug in your code that reads the data. Fix that bug instead of spending ten times as much effort trying to handle the malformed data.
That whole spiel about what you intend to do next is nothing more than a distraction that wastes the time of the people from whom you are asking help. Ask for help with the real problem (the loading bug) instead of driving people away with a confusing question that assumes bad data is good.
There are several ways to fix the bug. I think the most helpful approach is one that would have avoided the bug in the first place. You try to do too much in a single function. Divide and conquer; when you have a non-trivial sub-step, create a function to handle it. Good programming practices lead to fewer bugs.
Specifically, reading the heights of the fighters in a stack is non-trivial. Delegate that to a helper and reduce the body of your outer for loop to a single line.
for (int i = 0; i < noofstack; i++)
{
//* This is non-trivial, so use a helper function.
stackarmies.push_back(read_fighter_heights());
}
This helper function is responsible for reading a line of data, generating a stack (a vector<int>) from it, and returning that stack. That covers most of the body of your loop, leaving only the simple task of pushing the returned stack onto your vector of stacks.
Creating this helper function from your existing code is fairly simple. Mostly, just move the body of the loop into an appropriate function definition. In addition, you should notice that stack is needed (only) in this function, so also move that variable's declaration into the new function's definition.
vector<int> read_fighter_heights()
{
vector<int> stack;
int stacksize;
//Since vectors are dynamic and we don't need to declare the size but as per the problem statement I've added it/
cin >> stacksize;
for (int k = 0; k < stacksize; k++)
{
//Taking the input of all the vectors one by one and then adding all the vectors into one vector
int armyheight;
cin>>armyheight; //* Reading a single integer is trivial, so no need for another function here.
stack.push_back(armyheight);
}
return stack;
}
Presto! Problem solved. All you had to do was be more organized.
Addendum: The reason this solves the problem is that extra step of moving the declaration of stack. In the original code, this variable was declared outside the outer loop, and it was never cleared. The result was that it accumulated values from each line that was read. In this version, the variable is re-initialized before reading each line, so values do not accumulate. You could get the same result by moving the line in the original code, without splitting off a new function. However, splitting off a new function is a good habit to get into, as it almost forces you to declare stack at the right level, avoiding the problem in the first place.
bool CompareVectors(vector<vector<int>> st)
{
bool result = true;
for (int k = 0; k < st.size(); k++)
{
if (k != st.size() - 1)
{
if (result)
{
for (auto i = st[k].begin(); i != st[k].end(); ++i)
{
for (auto j = st[k+1].begin(); j != st[k+1].end(); ++j)
{
if (*i < *j)
{
result = true;
break;
}
else
{
result = false;
}
}
if (result)
{
break;
}
}
}
}
}
return result;
}

Difficulty with an accumulator in a nested for loop

I'm pretty new at C++, and I have to write code for a matching game, and I'm having trouble with the function that detects matches.
Below is a simpler, watered down version of the game I made to try to debug the match function.
Basically I have a bunch of numbers stored in a 2D array, and I need to cycle through the grid to see if there are any matches (3 of the same character in a row, vertically or horizontally, constitutes a match). The user gets one point for every match.
Every time there's a match, I need to accumulate a variable that stores the user's score. I think the code is pretty intuitive, the loops and if statements are checking the second and third elements after the ith element, and if they are all the same, a match has been detected.
The problem I'm having is that points are not being added to the count variable when they should. The "things" array is meant to emulate the game board, and I've designed it so it has at least one match, which my if statements don't seem to be detecting. How do I fix it so "count" will store points?
I've never posted anything on here before, so I'm sorry for the slightly screwy formatting, but here's the code:
#include <iostream>
using namespace std;
int main()
{
int things[3][3] = {{3, 3, 3}, {2, 8, 4}, {3, 7, 2}};
int count = 0;
for (int i = 0; i <= 3; i++)
{
for (int j = 0; j <= 3; j++)
{
if (things[i] == things[i+1])
count++;
if (things[i] == things[i+2])
count++;
if (things[i] == things[i+3])
count++;
else
{
if (things[j] == things[j+1])
count++;
if (things[j] == things[j+2])
count++;
if (things[j] == things[j+3])
count++;
}
}
}
return 0;
}
3 of the same character in a row, vertically or horizontally, constitutes a match
Too code this correctly You need to first have the correct algorithm.
So this is how I would write it in pseudo code:
For every row:
- For first n-2 columns in this row
- if current match result and next 2 match results are the same : increment counter
For every column:
- For first n-2 rows in this column
- if current match result and next 2 match results are the same : increment counter

I am trying my sorting method, which works well with data with no repeates entries, but am getting random numbers in place of repeated numbers?

I have been trying a sorting method in which I subtract each number stored in an array by other elements in the same array. Then, I saw a pattern that the number of differences which come to be negative, is the rank or position of element in the Sorted one. But, things go wrong when I am using repeated entries.
My basic method is :
Take every element of the SampleArray.
subtract it from every element of the SampleArray
check if the difference comes to be negative.
if it is then, increase a variable called counter.
And use this counter as the position of element in sorted array.
For example: lets take (5,2,6,4)
first take 5, subtract it from each of the numbers which will give results (0,-3,1,-1), so counter will become 2, which will be the index of 5 in the sorted Array. And repeat it for each of the elements.
for 5, counter will be 2.
for 2, counter will be 0.
for 6, counter will be 3.
for 4, counter will be 1.
And hence the sorted Array will be {2,4,5,6}.
First, see the code :
#include <iostream>
using namespace std;
void sorting(int myArray[], int sizeofArray);
int main()
{
int checkArray[] = {5,4,2,20,12,13,8,6,10,15,0}; //my sample Arry
int sized;
sized=sizeof checkArray/sizeof(int);//to know the size
cout << sized << endl;
sorting(checkArray, sized);
}
void sorting(int myArray[], int sizeofArray)
{
int tempArray[sizeofArray];
for (int i=0; i<sizeofArray; i++)
{
int counter=0;
for (int j=0;j<sizeofArray; j++ )
{
int checkNum = myArray[j]-myArray[i];
if (checkNum<0)
counter++; //to know the numbers of negatives
else
counter+=0;
}
tempArray[counter]=myArray[i];
}
for (int x=0;x<sizeofArray; x++)
{
cout << tempArray[x] << " " ;
}
}
Now, if we run this program with entries with no repetitions then, it sorts out the array, But if we use repeated entries like
int checkArray[] = {8,2,4,4,6}
the tempArray gets its first element as 2 as counter will be zero.
the tempArray gets its second element as 4 as counter will be 1.
but, the tempArray can't get its third one as counter will be still 1, and thus prints some randomNo in place of this. (here the things go wrong).
Can you please suggest a method to solve this?
This is an odd way of writing insertion sort, https://en.wikipedia.org/wiki/Insertion_sort
I would assume you can change your condition to:
if (checkNum<0 || (checkNum==0 && j<i))
But I would suggest using a proper sorting routine instead
The idea is to separate duplicates by saying that if the values are the same we sort according to their order in the sequence; as if the sequence was a pair of the value and the sequence number (0, 1, 2, 3, 4, 5, ...).
The issue here is that for any 2 equally sized numbers the nested loop will return the same counter value. Thus for such a counter value tempArray[counter + 1] will never be initialized.
The way to solve this would be to maintain a vector<bool> denoting what each position had been written and write to the next valid position if that is the case.
But supporting a second vector is just going to make your O(n2) code slower. Consider using sort instead:
sort(begin(checkArray), end(checkArray))

factorial array for tic tac toe

I am currently trying to teach myself C++ and programming in general. So as a beginner project i'm making a genetic algorithm that creates an optimal AI for a Tic-Tac-Toe game. I am not enrolled in any programming classes so this is not homework. I'm just really interested in AI.
So i am trying to create a multidimensional array of a factorial, in my case 9! . For example if you made one of 3! it would be array[3][6] = { {1, 2, 3}, {1, 3, 2}, {2, 3, 1}, {2, 1, 3}, {3, 2, 1}, {3, 1, 2}}. Basically 3! or 3*2*1 would be the amount of ways you could arrange 3 numbers in order.
I think that the solution should be simple yet im stuck trying to find out how to come up with a simple solution. I have tried to swap them, tried to shift them right, increment ect.. the methods that work are the obvious ones and i don't know how to code them.
So if you know how to solve it that's great. If you can give a coding format that's better . Any help is appreciated.
Also i'm coding this in c++.
You can use next_permutation function of STL
http://www.cplusplus.com/reference/algorithm/next_permutation/
I actually wrote an algorithm for this by hand once. Here it is:
bool incr(int z[NUM_INDICES]){
int a=NUM_INDICES-1;
for(int i=NUM_INDICES-2;i>=0;i--)
if(z[i]>z[i+1]) a--;
else break;
if(a==0) return false;
int b=2147483647,c;
for(int i=a;i<=NUM_INDICES-1;i++)
if(z[i]>z[a-1]&&z[i]-z[a-1]<b){
b=z[i]-z[a-1];
c=i;
}
int temp=z[a-1]; z[a-1]=z[c]; z[c]=temp;
qsort(z+a,NUM_INDICES-a,sizeof(int),comp);
return true;
}
This is the increment function (i.e. you have an array like [3,2,4,1], you pass it to this, and it modifies it to [3,4,1,2]). It works off the fact that if the last d elements of the array are in descending order, then the next array (in "alphabetical" order) should satisfy the following conditions: 1) the last d+1 elements are a permutation among themselves; 2) the d+1-th to last element is the next highest element in the last d+1 elements; 3) the last d elements should be in ascending order. You can see this intuitively when you have something like [2,5,3, 8,7,6,4,1]: d = 5 in this case; the 3 turns into the next highest of the last d+1 = 6 elements; and the last d = 5 are arranged in ascending order, so it becomes [2,5,4, 1,3,6,7,8].
The first loop basically determines d. It loops over the array backwards, comparing consecutive elements, to determine the number of elements at the end that are in descending order. At the end of the loop, a becomes the first element that is in the descending order sequence. If a==0, then the whole array is in descending order and nothing more can be done.
The next loop determines what the d+1-th-to-last element should be. We specified that it should be the next highest element in the last d+1 elements, so this loop determines what that is. (Note that z[a-1] is the d+1-th-to-last element.) By the end of that loop, b contains the lowest z[i]-z[a-1] that is positive; that is, z[i] should be greater than z[a-1], but as low as possible (so that z[a-1] becomes the next highest element). c contains the index of the corresponding element. We discard b because we only need the index.
The next three lines swap z[a-1] and z[c], so that the d+1-th-to-last element gets the element next in line, and the other element (z[c]) gets to keep z[a-1]. Finally, we sort the last d elements using qsort (comp must be declared elsewhere; see C++ documentation on qsort).
If you want a hand crafted function for generating all permutations, you can use
#include <cstdio>
#define REP(i,n) FOR(i,0,n)
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define GI ({int t;scanf("%d",&t);t;})
int a[22], n;
void swap(int & a, int & b) {
int t = a; a = b; b = t;
}
void perm(int pos) {
if(pos==n) {
REP(i,n) printf("%d ",a[i]); printf("\n");
return;
}
FOR(i,pos,n) {
swap(a[i],a[pos]);
perm(pos+1);
swap(a[pos],a[i]);
}
return;
}
int main (int argc, char const* argv[]) {
n = GI;
REP(i,n) a[i] = GI;
perm(0);
return 0;
}