Sorting an array fail - c++

I'm trying to sort an array made of random numbers from 1 to 10 in an ascending order. I've come up with this function:
void Sort(int a[10], int n)
{
int j = 0;
for (int i = 0; i < n-1; i++)
{
j = i+1;
if (a[i] > a[j])
{
int aux = a[i];
a[i] = a[j];
a[j] = aux;
}
}
}
But when I try to output the array, the function doesn't seem to have worked:
Sort(array, 10);
cout<<endl;
for (int i = 0; i < 10; i++)
{
cout<<array[i]<<" ";
}

The algorithm in your Sort function is wrong. It doesn't sort at all.
Anyway, don't reinvent the wheel, better use std::sort as:
#include <algorithm>
std::sort(array, array+10);
As for your Sort function, which you want to implement using bubble-sort algorithm, possibly for learning purpose. the correct implementation is this:
void Sort(int *a, int n)
{
for (int i = 0; i < n ; i++)
{
for (int j = i + 1; j < n ; j++)
{
if (a[i] > a[j])
{
int aux = a[i];
a[i] = a[j];
a[j] = aux;
}
}
}
}

You are only making n swaps. You need an outer loop on sort (assuming it's bubble sort) so that you continue doing that until you stop doing swaps.
bool Sort(int a[10], int n)
{
bool swapped = false;
int j = 0;
for (int i = 0; i < n-1; i++)
{
j = i+1;
if (a[i] > a[j])
{
int aux = a[i];
a[i] = a[j];
a[j] = aux;
swapped = true;
}
}
return swapped;
}
int main(int argc, char** argv) {
int a[10] = {5,4,3,1,2,6,7,8,9,10};
while (Sort(a,10));
for (int i=0;i<10;++i) {
std::cout << a[i] << std::endl;
}
}

That only does one pass over the data, here is an example showing you what happens
8 7 9 2 3 4 5
After going through your function the result would be
7 8 2 3 4 5 9

Related

Improving a solution

The description of a task goes like this:
We have n numbers, and we have to find quantity of unique sums of all the pairs in the array.
For example:
3 2 5 6 3
The sums of all the pairs(non-repeated) are 5 9 8 6 8 7 5 11 9 8
Unique are 5 9 8 6 7 11
Therefore output is 6
I have come up with this really primitive, and time-consuming (meaning complexity) solution:
int n = 0;
cin >> n;
vector<int> vec(n);
for (int i = 0; i < n; i++)
{
cin >> vec[i];
}
vector<int> sum;
for (int i = 0; i < n; i++)
{
for (int j = i+1; j < n; j++)
{
sum.push_back(vec[i] + vec[j]);
}
}
sort(sum.begin(), sum.end());
for (int i = 0; i < sum.size()-1;)
{
if (sum[i] == sum[i + 1]) sum.erase(sum.begin() + i);
else i++;
}
cout << endl << sum.size();
I feel like there could be a solution using Combinatorics or something easier. I have thought a lot and couldn't think of anything. So my request is if anyone can improve the solution.
As mentioned above what you need it is difficult to do this without computing the sum of all pairs, so I am not going to handle that, I am just going to advise about efficient data structures.
Analysis of your solution
Your code adds everything in advance O(n^2) then sorts O(n^2 log(n)), then remove duplicates. But since you are erasing from a vector, that ultimately has complexity linear with the number of elements to the end of the list. It means that the second loop will make the complexity of your algorithm O(n^4).
You can count the unique elements in a sorted array without removing
int count = 0;
for (int i = 0; i < sum.size()-1; ++i)
{
if (sum[i] != sum[i + 1]) ++count
}
This change alone makes your algorithm complexity O(n^2 log n).
Alternatives without sorting.
Here are alternatives that O(n^2) and storage depending on the range of the input values instead of the length of the vector (except for the last).
I am testing with 1000 elements smaller between 0 and 10000
vector<int> vec;
for(int i = 0; i < 1000; ++i){
vec.push_back(rand() % 10000);
}
Your implementation sum_pairs1(vec) (18 seconds)
int sum_pairs1(const vector<int> &vec){
vector<int> sum;
int n = vec.size();
for (int i = 0; i < n; i++)
{
for (int j = i+1; j < n; j++)
{
sum.push_back(vec[i] + vec[j]);
}
}
sort(sum.begin(), sum.end());
for (int i = 0; i < sum.size()-1;)
{
if (sum[i] == sum[i + 1]) sum.erase(sum.begin() + i);
else i++;
}
return sum.size();
}
If you know the range for the sum of the values you can use a bitset, efficient use of memory sum_pairs2<20000>(vec) (0.016 second).
template<size_t N>
int sum_pairs2(const vector<int> &vec){
bitset<N> seen;
int n = vec.size();
for (int i = 0; i < n; i++)
{
for (int j = i+1; j < n; j++)
{
seen[vec[i] + vec[j]] = true;
}
}
return seen.count();
}
If you know that the maximum sum is not so high (the vector is not very sparse), but you don't know at compilation time you can use a vector, you can keep track of minimum and maximum to allocate the minimum possible and also supporting negative values.
int sum_pairs2b(const vector<int> &vec){
int VMAX = vec[0];
int VMIN = vec[0]
for(auto v : vec){
if(VMAX < v) VMAX = v;
else if(VMIN > v) VMIN = v;
}
vector<bool> seen(2*(VMAX - VMIN) + 1);
int n = vec.size();
for (int i = 0; i < n; i++)
{
for (int j = i+1; j < n; j++)
{
seen[vec[i] + vec[j] - 2*VMIN] = true;
}
}
int count = 0;
for(auto c : seen){
if(c) ++count;
}
return count;
}
And If you want a more general solution that works well with sparse data sum_pairs3<int>(vec) (0.097 second)
template<typename T>
int sum_pairs3(const vector<T> &vec){
unordered_set<T> seen;
int n = vec.size();
for (int i = 0; i < n; i++)
{
for (int j = i+1; j < n; j++)
{
seen.insert(vec[i] + vec[j]);
}
}
return seen.size();
}

unable to sort an array, wrong output

#include<bits/stdc++.h>
using namespace std;
int
main ()
{
int a[3] = { 3, 2, 1 }, i, j, t = 0, k = 0;
int m;
for (int i = 0; i < 2; i++)
{
m = a[i];
for (int j = i++; j < 3; j++)
{
if (m > a[j])
{
m = a[j];
k = j;
}
}
t = a[i];
a[i] = m;
a[k] = t;
}
for (int i = 0; i < 3; i++)
{
cout << a[i];
}
return 0;
}
You seem to want to implement an insertion sort algorithm by hand. For this task, you should consider using std::sort. I refactored your code such that it basically does the same thing as you wanted and included some tips to make the code more readable and easier to debug for you and others:
#include <algorithm> //only include necessary headers
#include <iostream>
//do not use "using namespace std"
int main ()
{
int a[3] = { 3, 2, 1 };
/*
Declare local variables at the first point they are used an as local as possible.
It is much easier to read, if a no longer necessary variables leaves scope.
*/
for (int i = 0; i < 2; i++) {
int min = a[i]; //use names that tell something about what you are doing
int bestIndex = i;
for (int j = i+1; j<3; j++) { //here was your major bug: i++ also increcments i
if (a[j] < min){
min = a[j];
bestIndex = j;
}
}
std::swap(a[i], a[bestIndex]);
//try to use standard algorithms as often as possible. They document your code, are optimized and easier to read.
}
for (int i = 0; i < 3; i++){
std::cout << a[i];
}
return 0;
}
Look at this:
for (int i = 0; i < 2; i++)
{
for (int j = i++; j < 3; j++)
{
}
}
On the first iteration of the outer loop:
i is 0.
Then the inner loop increments it to 1.
Then the outer loop increments it to 2.
Then the outer loop is done, after just one iteration.
You want i+1 in the inner loop, not i++.
#include<bits/stdc++.h>
using namespace std;
int main ()
{
int a[3] = { 3,2,1}, t = 0, k = 0;
int m=0;
bool flag_change =false;
for (int i = 0; i < 2; i++)
{
m = a[i];
for (int j = i+1; j < 3; j++)
{
if (m < a[j]) //changing sing (<>) sort by ascending/sort by descending order
{
m = a[j];
k = j;
flag_change = true;
}
}
if(flag_change)
{
t = a[i];
a[i] = m;
a[k] = t;
flag_change = false;
}
}
for (int i = 0; i < 3; i++)
{
cout << a[i];
}
return 0;
}
I'm done correct you code. Code is working.But it is not good implementation.

Sorting Algorithm - Bubble Sort

I was trying to understand bubble sort. While implementing my own version of it for practicing, I implemented it in such a way:
public int[] sort(int[] nums) {
int x = 0;
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < i; j++) {
System.out.println(++x);
if (nums[j] > nums[i]) {
int temp = nums[j];
nums[j] = nums[i];
nums[i] = temp;
}
}
}
return nums;
}
Notice how the inner loop goes from 0 to i.
When I googled this algorithm to find the conventional implementation, I found this implementation:
public int[] sortnew(int[] nums) {
int x = 0;
for (int i = 0; i < nums.length - 1; i++) {
for (int j = 0; j < nums.length - i - 1; j++) {
System.out.println(++x);
if (nums[j] > nums[j+1]) {
int temp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = temp;
}
}
}
return nums;
}
Here i goes from 0 to array length - i - 1.
In both the cases the number of prints of 'x' are the same. This I believe indicates that the number of computations are same. Then what exactly is the difference between the two practically?
Thank you!

Insertion Sort Variation

#include <iostream>
using namespace std;
void print_array(int array[], int size)
{
cout<< "insertion sort steps: ";
int j;
for (j=0; j<size;j++)
cout <<" "<< array[j];
cout << endl;
}
void insertion_sort(int a[], int n)
{
int i;
for(int j = 1; j < n; j++) {
i = 0;
while ((a[j] > a[i])) {
i = i+1;
}
int m = a[j];
for(int k = 0; k <= (j-i-1); k++) {
a[j-k] = a[j-k-1];
}
a[i] = m;
print_array(a,n);
}
}
int main() {
int array[6]= {3,2,4,5,1,6};
insertion_sort(array,6);
return 0;
}
I am trying to modify this the insertion sort that it uses a linear search technique that inserts the jth element in the correct place by first comparing it with the (j − 1)st element, then the (j − 2)th element if necessary, and so on.
So where it says i = 0; it should now be i = j-1;
My attempt:
void insertion_sort(int a[], int n)
{
int i;
for(int j = 1; j < n; j++) {
i = j-1;
while ((a[j] > a[i]) && (i > 0)) {
i = i-1;
}
int m = a[j];
for(int k = (j-i-1); k >= 0; k--) {
a[j-k] = a[j-k-1];
}
a[i] = m;
print_array(a,n);
}
}
Here is the output
insertion sort steps: 2 3 4 5 1 6
insertion sort steps: 4 2 2 5 1 6
insertion sort steps: 5 4 4 4 1 6
insertion sort steps: 5 4 4 1 4 6
insertion sort steps: 6 5 5 5 5 5
The first step is works correct by the 2nd step is when it all starts to fail.
The
while ((a[j] > a[i]) && (i > 0)) {
i = i-1;
}
is wrong, because it causes insertion of a[j] at index 0 if a[j] were not to be moved. Change that to
while (0 <= i && a[j] < a[i]) --i;
++i;
Also, the shifting loop is wrong and complicated - change it to
int m = a[j];
for (int k = j; k > i; k--) a[k] = a[k-1];
a[i] = m;

How to sort elements into C++ matrix?

I'm new to C++ programming. I need to sort this matrix:
#include <iostream>
#include <iomanip>
#include <cstdlib>
using namespace std;
int main(int argc, char** argv) {
Mat10 a;
fillRand(a, 5, 5);
prnMat(a, 5, 5);
cout << endl;
return 0;
}
void fillRand(Mat10 m, int n, int k) {
for (int i = 0; i < n; i++)
for (int j = 0; j < k; j++)
m[i][j] = rand() % 1000;
}
void prnMat(Mat10 a, int m, int n) {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++)
cout << setw(8) << a[i][j];
cout << endl;
}
}
I need to sort the matrix from the beginning from the beginning. The smallest value must be at the beginning of the of the first column. The next must be below it and so on. The result must be sorted matrix - the smallest number must be at the beginning of the left column - the biggest value must be at the end of the matrix. Would you please help to solve the problem?
EDIT
Maybe I found possible solution:
void sort(int pin[10][2], int n)
{
int y,d;
for(int i=0;i<n-1;i++)
{
for(int j=0; j<n-1-i; j++)
{
if(pin[j+1][1] < pin[j][1]) // swap the elements depending on the second row if the next value is smaller
{
y = pin[j][1];
pin[j][1] = pin[j+1][1];
pin[j+1][1] = y;
d = pin[j][0];
pin[j][0] = pin[j+1][0];
pin[j+1][0] = d;
}
else if(pin[j+1][1] == pin[j][1]) // else if the two elements are equal, sort them depending on the first row
{
if(pin[j+1][0] < pin[j][0])
{
y = pin[j][1];
pin[j][1] = pin[j+1][1];
pin[j+1][1] = y;
d = pin[j][0];
pin[j][0] = pin[j+1][0];
pin[j+1][0] = d;
}
}
}
}
}
But since I'm new to programming I don't understand is this the solution?
Here is a simple example for you:
#include <vector>
#include <algorithm>
using namespace std;
//This is the comparation function needed for sort()
bool compareFunction (int i,int j)
{
return (i<j);
}
int main()
{
//let's say you have this matrix
int matrix[10][10];
//filling it with random numbers.
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
matrix[i][j] = rand() % 1000;
//Now we get all the data from the matrix into a vector.
std::vector<int> vect;
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
vect.push_back(matrix[i][j]);
//and sort the vector using standart sort() function
std::sort( vect.begin(), vect.end(), compareFunction );
//Finally, we put the data back into the matrix
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
matrix[i][j] = vect.at(i*10 + j);
}
After this, the matrix will be sorted by rows:
1 2
3 4
If you want it to be sorted by cols:
1 3
2 4
You need to replace matrix[i][j] in the last cycle only with matrix[j][i]
If you need to read about the the sort() function, you can do it here
Hope this helps.
You can simply call std::sort on the array:
#include <algorithm> // for std::sort
int main() {
int mat[10][10];
// fill in the matrix
...
// sort it
std::sort(&mat[0][0], &mat[0][0]+10*10);
}