C++ Bubble Sorting - c++

Hey i got this algorithm from my class called Bubble Sort. It uses two "for" one inside the other. But when i tried to do it with "while" it didnt work, aren't they equivalent ?
void bubbleSort(int v[], int n) { // void workingBubble(int v[], int n){
int fim = n - 1; // int i, fim;
int i = 0; // for(fim=n-1; fim>0; fim--){
int aux; // for(i=0; i<fim; i++){
while (fim > 0) { // if(v[i] > v[i+1]){
while (i < fim) { // int temp = v[i];
if (v[i] > v[i + 1]) { // v[i] = v[i+1];
aux = v[i]; // v[i+1] = temp;
v[i] = v[i + 1]; // }
v[i + 1] = aux; // }
} // }
i++; // }
} //
fim--; //
}}
I commented the one that worked next to the other so i could compare, i thought it was the same but with while instead of for
Array = {10, 2, 8, 11, 5, 3, 27, 1}
Array after bubble sort = {2, 8, 10, 5, 3, 11, 1, 27}

Reset i to 0 each time before the inner loop:
void bubbleSort(int v[], int n) {
int fim = n - 1;
int i;
int aux;
while (fim > 0) {
i = 0;
while (i < fim) {
if (v[i] > v[i + 1]) {
aux = v[i];
v[i] = v[i + 1];
v[i + 1] = aux;
}
i++;
}
fim--;
}
}

Related

Is what I'm doing an Insertion sort, I think the logic is correct but unconventional?

This code is supposed to be an Insertion sort but is it implemented as such? I'm lost. The first loop goes through the array and checks if the next element is smaller than the current element. The nested loop inserts the next element(j) correctly in its place in the sorted portion of the array.
#include <iostream>
using namespace std;
// Print array
void printArray(int array[], int arraySize)
{
for (int i = 0; i < arraySize; i++)
{
cout << array[i] << " ";
}
cout << endl;
}
int main()
{
int array1[] ={5, 3, 1, 9, 8, 2, 4, 7};
int array1Size = sizeof(array1)/sizeof(int);
printArray(array1, array1Size);
for (int i = 0; i < array1Size - 1; i++)
{
int oldNum = array1[i];
if (array1[i] > array1[i + 1])
{
array1[i] = array1[i + 1];
array1[i + 1] = oldNum;
}
int newI = array1[i];
// Check if arranged correctly
if ( i > 0)
{
// Swap bigger number and newI
for (int j = i - 1; newI < array1[j]; j--)
{
if (j < 0)
{
break;
}
array1[j + 1] = array1[j];
array1[j] = newI;
}
}
printArray(array1, array1Size);
}
return 0;
}
The key to insertion sort is to maintain a "sorted zone" and expand it in loop. In the beginning the zone is only one element, and finally it's all the list. We take an element outside the sorted zone and decide which position in sorted zone that it should be placed in.
BTW, loop invariant is easy to understand but powerful and awesome. Recommended.
int main() {
int array1[] ={5, 3, 1, 9, 8, 2, 4, 7};
int array1Size = sizeof(array1)/sizeof(int);
// loop invariant: array1[0..i-1] is sorted
// array1[i] is the element to be inserted
for (size_t i = 1; i < array1Size; i++) {
int temp = array1[i];
// find the right place to insert array1[i]. Can be replaced by binary search(but moving elements is more expensive than comparing)
size_t j = i; // j is used to save the right place
for (; j > 0 && array1[j-1] > temp; j--) {
array1[j] = array1[j-1];
}
array1[j] = temp;
}
return 0;
}
This for loop
for (int j = i - 1; newI < array1[j]; j--)
{
if (j < 0)
{
break;
}
array1[j + 1] = array1[j];
array1[j] = newI;
}
can invoke undefined behavior when j is equal to -1 due to this expression in the condition of the for loop
newI < array1[j]
And the code is too complicated. For example this code snippet
if (array1[i] > array1[i + 1])
{
array1[i] = array1[i + 1];
array1[i + 1] = oldNum;
}
where two elements are swapped is redundant. And this if statement
if ( i > 0)
{
also is redundant. It is enough to start the outer loop from 1 instead of from 0.
It is better to define a separate function. It can look for example the following way
void InsertionSort( int a[], size_t n )
{
for (size_t i = 1; i < n; i++)
{
if (a[i] < a[i - 1])
{
int tmp = a[i];
size_t j = i;
for ( ; j != 0 && tmp < a[j - 1]; --j )
{
a[j] = a[j - 1];
}
a[j] = tmp;
}
}
}
Pay attention to that the operator sizeof yields a value of the type size_t. You should use this type size_t for the variable that will be store the number of elements in the array. In general the type int is not large enough to store sizes of arrays.
If your compiler supports C++ 17 then instead of using the expression with the sizeof operator
int array1Size = sizeof(array1)/sizeof(int);
you could write at least
#include <iterator>
//...
int array1Size = std::size( array1 );
Also as the function printArray does not change the passed array then it first parameter should be declared with the qualifier const.
void printArray(const int array[], int arraySize);
Here is a demonstration program that shows usage of a separate function that sorts arrays using the insertion sort method..
#include <iostream>
#include <iterator>
void InsertionSort( int a[], size_t n )
{
for (size_t i = 1; i < n; i++)
{
if (a[i] < a[i - 1])
{
int tmp = a[i];
size_t j = i;
for ( ; j != 0 && tmp < a[j - 1]; --j )
{
a[j] = a[j - 1];
}
a[j] = tmp;
}
}
}
int main()
{
int array1[] ={5, 3, 1, 9, 8, 2, 4, 7};
for ( const auto &item : array1 )
{
std::cout << item << ' ';
}
std::cout << '\n';
InsertionSort( array1, std::size( array1 ) );
for ( const auto &item : array1 )
{
std::cout << item << ' ';
}
std::cout << '\n';
}
The program output is
5 3 1 9 8 2 4 7
1 2 3 4 5 7 8 9

Wrong Output for Merge Sort Algorithm

I am new to programming, and I have been learning about Merge Sort Algorithm, I wrote the following code:
#include <iostream>
using namespace std;
void Merge(int *arr1, int i, int m, int n, int j)
{
int sizeOfNewArray = j - i + 1;
int sizeOfFirstArray = m - i + 1;
int sizeOfSecondArray = j - n + 1;
int *finalArray = new int[sizeOfNewArray];
int *k = &finalArray[i];
int *ptr1 = &arr1[i];
int *ptr2 = &arr1[n];
while (i < sizeOfFirstArray && j < sizeOfSecondArray)
{
if (*ptr1 >= *ptr2)
{
*k = *ptr1;
i++;
k++;
}
else if (*ptr1 < *ptr2)
{
*k = *ptr2;
j++;
k++;
}
}
while (i < sizeOfFirstArray)
{
*k = *ptr1;
i++;
k++;
}
while (j < sizeOfSecondArray)
{
*k = *ptr2;
j++;
k++;
}
}
void MergeSort(int *arr1, int i, int j)
{
if (i != j)
{ //i represnts first index of array, j represents last index of array
int m = (i + j) / 2;
MergeSort(arr1, i, m);
MergeSort(arr1, m + 1, j);
Merge(arr1, i, m, m + 1, j);
}
if (i == j)
{
return;
}
}
int main()
{
int arr[] = {8, 6, 7, 1, 2, 4, 3, 5};
MergeSort(arr, 0, 7);
for (int i = 0; i < 8; i++)
{
cout << arr[i] << endl;
}
return 0;
}
According to me, this program should return the sorted array 1,2,3,4,5,6,7,8. However,on executing this code, it prints
8
6
7
1
2
4
3
5
I have tried debugging the code, but I am not able to find out what the error is. Can someone please have a look at the code, and tell me where is the error?
Apologies in advance for any silly error and thanks for taking out your time and concern.
Merge merges into the finalArray, which has nothing to do with arr1. Once Merge returns, finalArray ceases to exist (leaking memory), and arr1 remains untouched.
Before return, copy finalArray back to arr1, and delete[] it.

/bin/run.sh: line 4: 18 Segmentation fault (core dumped) ./exe

#include <bits/stdc++.h>
using namespace std;
int solve(int A, vector<int> &B) {
vector<int> pre(A);
vector<int> suff(A);
vector<int> p;
vector<int> s;
int sum = 0;
int ans = 0;
for (int i = 0; i < A; i++) {
sum = sum + B[i];
}
if (sum % 3 != 0)
return 0;
sum = sum / 3;
for (int i = 0; i < A; i++) {
if (i == 0) {
pre[i] = B[i];
if (pre[i] == sum) {
p.push_back(i);
}
continue;
}
pre[i] = B[i] + pre[i - 1];
if (pre[i] == sum) {
p.push_back(i);
}
}
for (int i = A - 1; i >= 0; i--) {
if (i == A - 1) {
suff[A - 1] = B[A - 1];
if (suff[i] == sum) {
s.push_back(i);
}
continue;
}
suff[i] = B[i] + pre[i + 1];
if (suff[i] == sum) {
s.push_back(i);
}
}
for (int i = 0; i < p.size(); i++) {
for (int j = s.size(); j >= 0; j++) {
if (s[j] > p[i] + 1) {
ans++;
}
}
}
return ans;
}
int main() {
int A = 5;
vector<int> B = {1, 2, 3, 0, 3};
cout << solve(5, B);
return 0;
}
The code keeps getting dumped at pre[i]=B[i]. The code is very simple for counting the number of ways to split all the elements of the array into 3 contiguous parts so that the sum of elements in each part is the same.
I just made a prefix and suffix sum array.

incorrect output of merge sort

I am trying to write a merge sort algorithm using template functions in c++. The output is close but not correct. When I give the function the array [7, 6, 4, 8, 1, 2, 3], it returns [1, 1, 2, 2, 3, 3, 8]. I specifically believe that the problem is in the merge function rather than the merge sort function. Any help would be much appreciated. Here is my code:
template <class T1>
void mergeSort(T1 array[], int lower, int upper)
{
if (lower < upper)
{
int middle = (lower + upper) / 2;
mergeSort(array, lower, middle);
mergeSort(array, middle + 1, upper);
merge(array, lower, middle, upper);
}
}
template <class T1>
void merge(T1 array1[], int lower, int middle, int upper)
{
int i = 0,
j = 0,
k = 0;
int size1 = middle - lower + 1;
int size2 = upper - middle;
T1* temp1 = new T1[size1];
T1* temp2 = new T1[size2];
for (int i = 0; i < size1; i++)
{
temp1[i] = array1[lower + i];
}
for (int j = 0; j < size2; j++)
{
temp2[j] = array1[middle + 1 + j];
}
while (i < size1 && j < size2)
{
if (temp1[i] < temp2[j])
{
array1[k] = temp1[i];
i++;
}
else
{
array1[k] = temp2[j];
j++;
}
k++;
}
if (i == size1)
{
while (j < size2)
{
array1[k] = temp2[j];
k++;
j++;
}
}
else
{
while (i < size1)
{
array1[k] = temp1[i];
k++;
i++;
}
}
}
int main(){
int a[] = { 7, 6, 4, 8, 1, 2, 3 };
mergeSort(a, 0, 6);
}
Output:
1 1 2 2 3 3 8
In your merge function you shouldn't initialize k to 0 because it will write the result of merge in the wrong place. Instead you should initialize k to lower. Because that is the start index of the part you are actually sorting.

Why this inversion count merge sort algorithm is giving wrong answer

Here is code I have written for inversion count in c++. If you write some other recursion method. Please try to explain it to me.
I am storing inversion count in countI. I am getting 2 as output for array A[] i have declared in main function.
#include<iostream>
#include<math.h>
using namespace std;
int countI = 0;
void merge(int A[], int p, int q, int r)
{
int n1 = q - p + 1;
int n2 = r - q;
int *L;
L = new int[n1];
int *R;
R = new int[n2];
for (int i = 1; i <= n1; i++)
{
L[i] = A[p + i - 1];
// cout << A[p + i - 1]<<endl;
//cout << L[i];
}
for (int j = 1; j <= n2; j++)
R[j] = A[q + j];
int i = 1, j = 1;
// cout << "li " << L[n1]<<"\t"<<R[n2];
for (int k = p; k <= r; k++)
{
if ((L[i] <= R[j] && i <= n1) || j>n2)
{
A[k] = L[i];
//cout << A[k];
i++;
}
else
{
A[k] = R[j];
j++;
if (i<n1)
countI += n1 - i+1; //here I am counting the inversion.
//cout <<endl<<"R"<< R[j];
}
}
}
void mergeSort(int A[], int p, int r)
{
if (p < r)
{
// cout << A[8];
int sum = p + r;
//int q = (sum) / 2 + (sum % 2);
int q = (sum) / 2;
mergeSort(A, p, q);
mergeSort(A, q + 1, r);
merge(A, p, q, r);
}
}
int main()
{
//I am considering array from index 1
int A[] = { 0, 1, 3, 5,2,4,6 };
// int arr[100001];
int i = 1;
int n = 0;
//while (scanf("%d", &n) != EOF) { arr[i++] = n; }
mergeSort(A, 1, 6);
for (int i = 1; i <= 6; i++)
{
cout << A[i] << " ";
}
cout << "\n " << countI;
system("pause");
return 0;
}
You should note C++ uses 0 index based arrays.
The first element of L and R are 0, not 1.
The same thing when you call mergeSort in you main.
try mergeSort(A, 0, 5)
While your consistent with your mistake of indexing starting at 1. You run off the end of your arrays by 1. This can cause your program to crash; however, when it doesn't you often get weird answers (which are hard to debug) because you're improperly accessing and writing over memory.
Here is some pseudo code (for 0 indexed based arrays) that will count inversions while performing merge sort.
merge(A, p, m , q){
B = [] // array size of q - p + 1
i = p, j = m+1, k = 0, inv = 0
while (i <= m && j <= q){
if (A[i] < A[j])
B[k++] = A[i++]
else{
B[k++] = A[j++]
inv += m - i + 1
}
}
while (i <= m) // copy rest of left side to temp array
B[k++] = A[i++] // otherwise it may be overwritten
i = 0;
while (i < k){ // copy temp array elements back to A
A[p+i] = B[i]
++i
}
return inv
}
merge_sort(A, p, q){
if (p == q)
return 0;
m = floor((p + q)/2)
inv1 = merge_sort(A, p, m)
inv2 = merge_sort(A, m+1, q)
return inv1 + inv2 + merge(A, p, m, q)
}
// you can call it like this:
A = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} // 10 Elements
inversions = merge_sort(A, 0, 9) // sort and count inversions from index 0 to index 9