Sorting array with BubbleSort - c++

l changed my code but still cant figure out why it wont sort array...bubble sort only moves all elements one place to the right in my program instead of sorting array...l tired bsort and ssort and both do same thing shift elements for 1 position
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void bsort(int n,int a[])
{
int i,j,k;
for(i=0;i<n-1;i++)
{
for(j=0;j<n-1;j++)
{
if(a[j]>a[j+1]);
{
k=a[j+1];
a[j+1]=a[j];
a[j]=k;
}
}
}
}
int main()
{
int i,j,k,m,n;
srand(time(0));
printf("Unesi broj clanova niza:");
scanf("%d",&n);
int a[n];
printf("Niz za sortiranje je:\n");
for(int i=0;i<n;i++) //Generisanje niza
{
a[i]=rand()%(81);
}
for(int i=0;i<n;i++)
{
printf("%3d",a[i]);
}
bsort(n,a);
printf("\n\nSortirani niz je:\n");
for(i=0;i<n;i++)
{
printf("%3d",a[i]);
}
}

There are several problems with your bubble sort implementation.
First, this line:
if (a[j] > a[j + 1]); {
is incorrect. The semi-colon terminates the conditional. As a result, the following block executes on every iteration of the inner loop and you end up unconditionally swapping a[j] and a[j+1] for every value of j. This means you're performing a nonsensical rearrangement of the array.
Second, you're not dealing correctly with edge cases in the inner loop. When j == 19, you access a[j+1], which is a[20], which is beyond the end of the array. You thus import garbage data into your array.
Lastly, even after correcting the above, your implementation is needlessly inefficient, in that your inner loop goes through the entire array on each iteration of the outer loop, which it doesn't have to. Hint: Try to think about how the initialization or termination condition of the inner loop could depend on i.
Update (after the OP's rewrite): You only addressed the second issue.

int main() {
int a[20];
srand(time(0));
// array values initialization
for (int i = 0; i < 19; i++) {
a[i] = rand() % (81);
}
// array sorting
bsort(a);
// array printing
for (int i = 0; i < 19; i++) {
printf("%3d", a[i]);
}
}

Related

C++ Bubble Sort Algorithm

I have the following code written in c++ and the algorithm works when in this scenario. I am knew to c++ and don't understand what I did wrong in my 2nd test.
#include <iostream>
using namespace std;
void bubbleSort(int numbers[], int size) {
for (int i = 0; i<size;i++) {
for (int j=0; j<size;j++) {
if (numbers[j] > numbers[j+1]) {
swap(numbers[j], numbers[j+1]);
}
}
}
}
int main() {
int numbers[] = {7,5,6,4};
bubbleSort(numbers,4);
for (int print = 0; print < 4; print++) {
cout << numbers[print] << endl;
}
return 0;
}
But, fails when I try to put in numbers that are already sorted:
#include <iostream>
using namespace std;
void bubbleSort(int numbers[], int size) {
for (int i = 0; i<size;i++) {
for (int j=0; j<size;j++) {
if (numbers[j] > numbers[j+1]) {
swap(numbers[j], numbers[j+1]);
}
}
}
}
int main() {
int numbers[] = {1,2,3};
bubbleSort(numbers,3);
for (int print = 0; print < 3; print++) {
cout << numbers[print] << endl;
}
return 0;
}
for (int j=0; j<size;j++) {
If size is 3, if the array has three values, for example, this loop iterates with values of j of 0, 1, and 2.
if (numbers[j] > numbers[j+1]) {
When j is 2 this compares numbers[2] with numbers[3].
There is no numbers[3]. This is undefined behavior. The loop is off by 1 value.
Additionally, the overall bubble sort implementation is flawed. In the shown code the inner loop iterates over the entire array (ignoring the off-by-1 bug), every time. In a classical bubble sort the first pass (the first iteration of the outer loop) results in the inner loop iterating over the entire array and "bubbling" the smallest/largest value to the end of the array. On the next pass the inner loop does not need to iterate over the entire array, but only up until the 2nd smallest/largest position of the array. And so on, each pass (the outer loop) results in the inner loop iterating over a smaller, and smaller subset of the array, "bubbling" the corresponding value to the appropriate stop.
In addition to fixing the off-by-1 bug you'll also need to adjust the overall logic of this bubble sort, if you wish to get a perfect grade for your homework assignment.
Implementing bubble sort in its entirety is problematic. In the example code, the inner loop repeatedly iterates over the full array while disregarding the shift by 1. The inner loop iterates over the whole array in a traditional bubble sort's first iteration of the outer loop, "bubbling" the smallest/largest value to the array's end. On the subsequent iteration, the inner loop only has to iterate up to the array's second-smallest/largest point rather than the full array. The inner loop then iterates through a smaller and smaller subset of the array, making bubbles of the associated the associated value to the proper stop with each successive run in the outside loop.

Why does the function return 0?

I have this function that should take a matrix, compare the diagonal elements of the matrix and find the smallest one.
Here it should compare y[0][1] and y[1][0].
#include <iostream>
int Min(int, int [][2]);
using namespace std;
int main() {
int min, y[2][2];
y[0][0]=5;
y[0][1]=4;
y[1][0]=-9;
y[1][1]=0;
min = Min(2, y);
cout<<min;
return 0;
}
int Min(int k, int x[][2]){
int min=x[0][0];
for(int i=0; i<k;i++){
if(x[i][i]<min){
min=x[i][i];
}
}
return min;
}
It always returns 0. Why?
Here it should compare y[0][1] and y[1][0].
Your function goes through the diagonal of the matrix, it hence checks y[0][0] and y[1][1]. They are 5 and 0. The result is zero, which is to be expected.
Here it should compare y[0][1] and y[1][0].
But that's not what you say here:
int min=x[0][0];
or here:
if(x[i][i]<min){
min=x[i][i];
}
Since i cannot be both 0 and 1 at the same time, this accesses x[0][0] and x[1][1].
And for those elements, 0 is the correct minimum.
As a side note, your Min function can only work with matrices of size 2, so the k parameter is unnecessary. Multi-dimensional arrays are annoying like that.
To iterate over all items instead of just [0][0] and [1][1] you need to do:
for(int i=0; i<k; i++)
{
for(int j=0; j<k; j++)
{
if(x[i][j]<min)
{
min=x[i][j];
}
}
}
int Min(int k,const int x[][2])
{
int min=x[0][0];
for(int i=0; i<k;i++)
{
for(int j=0;j<k;j++)
{
if(x[i][j]<min)
{
min=x[i][j];
}
}
}
Earlier it was always showing zero because it had a mess with the column index. Outer for loop iterates k-1 times with first iteration at i=0, and second at i=1 and during both iterations it assigns the same index to both row and column(i.e., x [0][0] and x[1][1]). Perhaps it must assign the index x[0][0], x[0][1], x[1][0], x[1][1]. Earlier, it had only two iterations(the outer for loop) but now it takes four iterations assigning the appropriate index to both column and rows the efficient number of times.

Using recursion in bubble sort

Hello everyone I am starting to learn Data structures and Algorithms and implemented bubble sort myself after learning the concept. Following is the code I have written with my understanding but the problem is it runs for only one cycle and does not sort recursively.
For example:
{ 5,1,4,2,8} is sorted one time -> {1,4,2,5,8,}
What can be the problem?
vector<int> bubble_sort(vector<int> vec){
int temp = 0;
for(int i = 0; i < vec.size()-1; i++){
temp = vec.at(i+1); // holds the adjacent element.
// the following loop swaps the adjacent elements if the previous one is big
if(vec.at(i) > vec.at(i+1)){
vec.at(i+1) = vec.at(i);
vec.at(i) = temp;
}
temp = 0;
}
for(int i = 0; i < vec.size()-1; i++){
if(vec.at(i) > vec.at(i+1)){
bubble_sort(vec);
}
}
return vec;
}
Your function takes a vector<int> vector by copy, hence after first swaps only this copy is send to recursively sort.
Just add & to your function parameter: vector<int> bubble_sort(vector<int> &vec) and it should work
If you want to implement recursion fully and do not want to use for loop in the code, then follow this example. It will be helpful.
#include <iostream>
using namespace std;
/* Function to print an array */
void printArray(int arr[], int n)
{
for (int i=0; i <= n; i++)
cout<<arr[i];
}
void bubble_sort_recursive(int arr[], int j, int n) {
// base case
if (n==0 || j>n){
return;
}
// single pass has been completed and the higher element moved to right for that subarray
// now call the recursive function by keeping aside the already sorted positioned element
//i.e next pass wil start from this call
if (j == n){
bubble_sort_recursive(arr,0,n-1);
}
// swap consecutive 2 elements - main basic of bubble sort
if (arr[j]>arr[j+1]){
int t = arr[j];
arr[j] = arr[j+1];
arr[j+1] =t;
}
// go forward for next element of a single pass
bubble_sort_recursive(arr,j+1,n);
}
int main() {
int arr[] = {5,4,3,2,1};
// get the length of array
int n = sizeof(arr)/sizeof(arr[0]);
// call from 0 to len-1 as index starts from 0
bubble_sort_recursive(arr,0,n-1);
// print the sorted array
cout<<"Sorted array:"<<endl;
printArray(arr, n-1);
}

Count Inversions with merge sort in C++

I'm working on my first few algorithms to build my C++ skills and am currently coding up a method of counting inversions with merge sort. I've managed to get a working merge sort together but I'm having a bit of trouble keeping track of the number of inversions. Any ideas of where to go from here? How can I keep track of the number of inversions on a recursive algorithm like this? Additionally I've seen a couple different implementations of this in my internet travels and have found most people stray away from the std::vector method, any idea why? Thanks for any help, my code is below!
#include <iostream>
#include <math.h>
#include <vector>
using namespace std;
vector<int> print(vector<int> input){
for(int i=0; i<input.size(); i++){
cout<<input[i]<<",";
}
cout<<endl;
return input;
}
vector<int> merge(vector<int> left,vector<int> right){
//set up some varibles
vector<int> output;
int i=0;
int j=0;
//loop through the lists and merge
while(i<left.size() && j<right.size()){
//push the smallest of the two to the vector output
if(left[i]<=right[j]){
output.push_back(left[i]);
i+=1;
}
if(left[i]>right[i]){
output.push_back(right[j]);
j+=1;
}
}
//push the remnants of the vectors to output
for(i; i<left.size(); i++){
output.push_back(left[i]);
}
for(j; j<right.size(); j++){
output.push_back(right[j]);
}
return output;
}//end merge
vector<int> merge_sort(vector<int> input){
//check the size of the vector
if(input.size()<2){
return input;
}
else{
//int new vectors
vector<int> left;
vector<int> right;
vector<int> output;
//find the middle of the input vector
int middle=(input.size())/2;
//build the left vector
for(int i=0; i<middle; i++){
left.push_back(input[i]);
}
//build the right vector
for(int i=middle; i<input.size(); i++){
right.push_back(input[i]);
}
//make recursive calls
left=merge_sort(left);
right=merge_sort(right);
//call merge
output=merge(left,right);
return output;
}
}
int main()
{
vector<int> output;
vector<int> input;
input.push_back(2);
input.push_back(1);
input.push_back(10);
input.push_back(4);
output=merge_sort(input);
print(output);
}
Good news: counting inversions is pretty easy from here.
Think about your "merge" method. Every time you put an element from the left vector into output, you are not changing its position relative to elements from the right. On the other hand, every time you add an element from the right vector, you are putting it "before" all elements still to be processed in the left vector, when it was prevously "after" them, i.e. creating (left.size - i) "inversions".
You can prove this easily by induction if needed.
So the answer is simply : pass an int* to your merge method, and increment it by (left.size - i) every time you push an element from the right vector.
EDIT: Working code sample
#include <iostream>
#include <vector>
// removed useless dependency math.h
using namespace std;
// void type -> does not return anything
void print (vector<int> input) {
// range-based for loop (since C++ 11)
// no brackets -> only one instruction in for loop
for(int i : input)
cout << i << ",";
}
vector<int> merge (vector<int> left, vector<int> right, int * inv_count) {
vector<int> output;
// multiple variable definition of the same type
int i=0, j=0;
// spaces around "<", after "while", before "{" for readability
while (i < left.size() && j < right.size()) {
// one-instruction trick again
if (left[i] <= right[j])
// i++ is evaluated to <previous value of i> and then increments i
// this is strictly equivalent to your code, but shorter
// check the difference with ++i
output.push_back(left[i++]);
// else because the two conditions were complementary
else {
output.push_back(right[j++]);
// pointer incrementation
*inv_count += (left.size() - i);
}
}
// first field of for ommited because there is no need to initialize i
for(; i < left.size(); i++)
output.push_back(left[i]);
for(; j < right.size(); j++)
output.push_back(right[j]);
return output;
}
vector<int> merge_sort (vector<int> input, int * inv_count) {
// no-braces-idiom again
// spaces around "<" and after "if" for readability
if (input.size() < 2)
return input;
// no need for else keyword because of the return
// multiple variable definition
vector<int> left, right;
int middle = input.size() / 2;
// one-instruction for loop
for(int i=0; i < middle; i++)
left.push_back(input[i]);
for(int i=middle; i < input.size(); i++)
right.push_back(input[i]);
// no need for intermediate variable
return merge( merge_sort(left, inv_count),
merge_sort(right, inv_count),
inv_count);
}
// consistent convention : brace on the same line as function name with a space
int main () {
// vector initialization (valid only since C++ 11)
vector<int> input = {2, 1, 10, 4, 42, 3, 21, 7};
int inv_count = 0;
// No need for intermediate variables again, you can chain functions
print( merge_sort(input, &inv_count) );
// The value inv_count was modified although not returned
cout << "-> " << inv_count << " inversions" << endl;
}
I modified your code to include a few usual C++ idioms. Because you used the C++14 tag, I also used tricks available only since C++11. I do not recommend using all of these tricks everywhere, they are included here because it is a good learning experience.
I suggest you read about pointers before diving deeper into C++.
Also note that this code is in no way optimal : too many intermediate vectors are created, and vectors are not useful here, arrays would be enough. But I'll leave this for another time.

How to sort an array in C++ in a specific way

I want somehow sort an array, so that it looks like -
a[0]>=a[1]<=a[2]>=a[3]<=a[4]
I don't know where to start.
Any suggestion would be appreciated!
Sort the entire array (Choose any sort algorithm you wish to). Then take each pair from the beginning and swap the elements in the pair
2,4,1,5,6,3,7,9,8,10
Sorted to : 1,2,3,4,5,6,7,8,9,10
Pair and swap : (2,1),(4,3),(6,5),(8,7),(10,9)
result : 2,1,4,3,6,5,8,7,10,9
Here's the code, obviously you can alter the array length and numbers to meet your specifications.
#include <iostream>
#include <algorithm>
using namespace std;
void special_Sort(int *array, int size){
//doesn't return a value, changes the values inside the array
int temp;
//for swapping purposes
sort(array, array+size);
//sorts the array in ascending order
for(int i=0; i<size; i=i+2){
temp=array[i];
array[i]=array[i+1];
array[i+1]=temp;
}
//array is now sorted
}
int main(){
// array declaration, call the function, etc...
int array[10]={2,4,1,5,6,3,7,9,8,10};
int *pointer;
pointer=&array[0];
special_Sort(pointer, 10);
// if you want to print the result
// for(int i =0; i<10; i++)
// cout<<array[i]<<" ";
return 0;
}
I'm assuming here that the relations are inclusive (in the sense that they continue to the end of the line - a[0]>=max(a[1],a[2],...), and a[1]<=min(a[2],a[3],..) and so on). Otherwise this isn't uniquely defined, as {5,4,3,2,1} can get sorted for example into {5,1,4,3,2} or {3,2,5,1,4}.
So, assuming this is the case, it's easily solved by sorting the entire array in descending order, then just interleave them -
a[0], a[n-1], a[1], a[n-2], ...
and so on. Just loop with two indices, one starting from the beginning and one from the end, or use something like this -
for (i=0; i<n/2; i++) {
result[i*2] = sorted[i];
result[i*2+1] = sorted[n-i];
}
if (n%2)
result[n-1] = sorted[n/2]
If you are only sorting it in a way that you want values to rise and fall arbitrarily, you can achieve this by checking values in your array and swapping elements if they do not satisfy the constraints of your sort.
Don't have a compiler on me at the moment and you'd have to implement the swap but something like this could work:
for(i=0; i < a.length(); i++){
//If index is even
if(i%2 == 0){
if(a[i] < a[i+1]){
swap(a[i], a[i+1]);
}
} else { ///If index is odd
if(a[i]>a[i+1]){
swap(a[i], a[i+1];
}
}
}
I don't disagree with the other answers posted here so you will have to find what you need depending on the relation of the even and odd indexed elements.
Steps taken:
1) generate some random array
2) sort array
3) switch elements as needed with alternate <=, >= comparisons
Here's the code that does that: (disregard the random generator, its just an easy way to generate an array)
#define sizeArr 50
int main(void)
{
int array[sizeArr];
int i, temp;
for(i=0;i<sizeArr;i++)
{
array[i]=randomGenerator(1, 1000);
Sleep(2);//force clock tick for new srand() to be effective in rand() generator
}
//sort array
qsort(array, sizeArr, sizeof(int), cmpfunc);
//pick the first non repeat 90th percent and print
for(i=0;i<sizeArr-1;i++)
{
if(i%2==0)//alternate between >= && <=
{
if(array[i+1] >= array[i])
{
temp = array[i+1];
array[i+1]=array[i];
array[i]=temp;
}
}
else
{
if(array[i+1] <= array[i])
{
temp = array[i+1];
array[i+1]=array[i];
array[i]=temp;
}
}
}
getchar();
return 0;
}
int cmpfunc (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int randomGenerator(int min, int max)
{
int random=0, trying=0;
trying = 1;
srand(clock());
while(trying)
{
random = (rand()/32767.0)*(max+1);
(random >= min) ? (trying = 0) : (trying = 1);
}
return random;
}