I wrote a selection sort program in C++. I have checked and rechecked the code, but the logic is perfectly fine. But the code is not sorting the array properly:
// Selection Sort
#include <iostream>
using namespace std;
inline void swap( int& x, int& y) {
int temp = x;
x = y;
y = temp;
}
int main() {
const int n = 10;
int list[n];
string line(14, '-');
cout << '\n' << line << "\nSelection Sort\n" << line << '\n';
cout << "Enter " << n << " elements:\n";
for( int i = 0; i < n; ++i ) {
cin >> list[i];
}
for( int i = 0; i < n-1; ++i ) {
int small = i;
for( int j = 1; j < n; ++j ) {
if( list[j] < list[small] ) {
small = j;
}
}
if( list[small] < list[i] ) {
swap( list[i], list[small]);
}
}
cout << "Sorted Array:\n";
for( int i = 0; i < n; ++i ) {
cout << list[i] << ' ';
}
return 0;
}
Where am I going wrong? The algorithm of Selection sort is given here: Selection Sort- wikipedia
Sample input with 10 numbers:
7 8 9 10 11 12 13 14 15 16
Output:
7 9 10 11 12 13 14 15 8 16
The inner loop is surely wrong here:
for( int j = 1; j < n; ++j ) {
should be
for( int j = i+1; j < n; ++j ) {
Also, the condition at the end of the loop
if( list[small] < list[i] ) {
swap( list[i], list[small]);
}
is excessive. It is satisfied by definition after the inner loop exits.
See: Sorting algorithms - selection sort for the pseudocode and a nicely animated demo on different kinds of data.
In the inner loop of the sorting loop, you have written: for( int j = 1; ...)
Now, every time, the inner loop is not going from 1 to n-1, but instead is going from i+1 to n-1
So change the loop to for( int j = i+1; ...)
Also, you may change the swapping condition to small != i, but this is optional.
I've inspected your code and you have a logic error for the selection sort to succeed. In the inner loop, the initialization of the inner loop is always j = 1. This should change to:
for( int j = i+1; j < n; ++j ) {
if( list[j] < list[small] ) {
small = j;
}
}
and also change the condition value of your outer loop to i < n to ensure the loop goes from start to end.
The inner loop should be
for(j=i+1;j<n;j++)
{
if( list[j] < list[small] ) {
small = j;
}
}
And if they small is not equal to I variable then swap
if(small != i)
{
swap();
}
Related
I have an 2d array of char, and I am trying to order them in alphabetical order. In each rows there is a word build of chars and I am trying to sort it.
I built something, but I don't understand why this is not working. If you have a solution for me, please explain what you are doing, in order to understand why I don't success.
Thanks !
char matrix[4][5] = {
{'h','e','l','l','o'},
{'r','e','a','d','y'},
{'a','p','p','l','e'},
{'p','o','i','n','t'},
};
char temp;
bool flag = false;
display(matrix);
for (int i = 0; i < 4 - 1; i++)
{
for (int rows = 0; rows < 10-1; rows++)
{
flag = false;
for (int cols = 0; cols < 5; cols++)
{
if (matrix[rows][cols] > matrix[rows + 1][cols])
{
flag = true;
break;
}
}
if (flag)
{
for (int index = 0; index < 5; index++)
{
temp=matrix[rows][index];
matrix[rows][index]=matrix[rows+1][index];
matrix[rows+1][index]=temp;
}
}
}
}
I will post this answer, even if it may not be what you want to do (but will be helpful for others who may want to do things this way).
Instead of sorting the 2D array, the trick is to not sort it, and instead sort an array of indices that point into the array. That is much more simpler than trying to manipulate the array itself.
Here is a very simple example:
#include <algorithm>
#include <cstring>
#include <iostream>
int main()
{
char matrix[4][5] = {
{'h','e','l','l','o'},
{'r','e','a','d','y'},
{'a','p','p','l','e'},
{'p','o','i','n','t'},
};
// create the indices
int index[] = { 0,1,2,3 };
// sort the indices based on the data in the array
std::sort(index, index + 4, [&](int n1, int n2)
{ return strncmp(matrix[n1], matrix[n2], 5) < 0; });
// Output the results
for (int i = 0; i < 4; ++i)
{
// Note how we access the original matrix using the index array
std::cout.write(matrix[index[i]], 5);
std::cout << " -- Using array at row " << index[i] << "\n";
}
}
Output:
apple -- Using array at row 2
hello -- Using array at row 0
point -- Using array at row 3
ready -- Using array at row 1
The final results show that the indices just point to the row that would be used if we want to access the array in a sorted manner. The original array was not adjusted.
That's it.
#include <bits/stdc++.h>
using namespace std;
char matrix[4][5] = {
{'h','e','l','l','o'},
{'r','e','a','d','y'},
{'a','p','p','l','e'},
{'p','o','i','n','t'} };
int n = 4, m = 5, k = 0;// number of rows and columns
char temp;
int main()
{
for ( int i = 0; i < n; i++ )
for ( int j = i + 1; j < n; j++ )
{
k = 0;
while ( matrix[i][k] == matrix[j][k] && k < m )
k++;
if ( k < m && matrix[i][k] > matrix[j][k] ) // ASCII code comparison
for ( int k = 0; k < m; k++ )
{
temp = matrix[i][k];
matrix[i][k] = matrix[j][k];
matrix[j][k] = temp;
}
}
for ( int i = 0; i < n; i++ )
{
for ( int j = 0; j < m; j++ )
cout << matrix[i][j];
cout << "\n";
}
}
I was trying to do the following:
Have a matrix, print the entire thing out, print at end of every row the biggest element of said row and print at the bottom of every column the smallest element of said column.
I'm pretty much a beginner at C++.
So here's what I've done so far:
#include <iostream>
#include <iomanip>
#define M 50
#define N 50
using namespace std;
int main()
{
int m,n;
int a[M][N];
int b[M],c[N];
do {
cout<<"m=";
cin>>m;
cout<<endl<<"n=";
cin>>n;
cout<<endl;
}
while(m!=n);
for(int i=0;i<m; i++) {
for(int j=0; j<n; j++){
cout<<"a["<<i<<"]["<<j<<"]=";
cin>>a[i][j];
}
}
int max_row;
max_row=0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (a[i][j] > max_row) {
max_row = a[i][j];
b[i] = max_row;
}
}
}
for (int i=0; i<m; i++)
{ for(int j=0; j<n; j++){
cout<<setw(3)<<a[i][j]<<"\t";
}
cout<<"|"<<b[i];
cout<<endl;
}
for(int i=0; i<m; i++){
cout<<setw(3)<<"-";}
cout<<endl;
for(int j=0; j<n; j++)
{cout<<c[j]<<"\t";
}
system("pause");
}
Most of the time the max_row are the correct ones such as this case:
3 2 1 |3
4 6 5 |6
7 8 9 |9
Other times they get messed up and it goes like this:
1 2 3 |3
4 33 6 |33
7 8 9 |-858993460
I really have no idea what causes it and since there are no error messages I got really confused. Also I have no idea how to make the min column ones. Any help would be appreciated.
The problem with these loops
max_row=0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (a[i][j] > max_row) {
max_row = a[i][j];
b[i] = max_row;
}
}
}
is that the value of max_row should be initialized with each iteration of the outer loop. Otherwise all rows after the first row deal with the maximum value of the previous row and in general can not have en element that is greater than the current value of max_row. So the corresponding element of the array b will not be initialized.
Also the user can enter for the matrix negative values in this case your program will output zeroes instead of maximum values.
To find maximum elements in rows and minimum elements in columns it is enough to have one pair of nested loops/
Here is a demonstrative program/
#include <iostream>
#include <iomanip>
int main()
{
const size_t N = 3;
int a[N][N] =
{
{ 1, 2, 3 },
{ 4, 33, 6 },
{ 7, 8, 9 }
};
int b[N], c[N];
for ( size_t i = 0; i < N; i++ )
{
b[i] = a[i][0];
c[i] = a[0][i];
for ( size_t j = 1; j < N; j++ )
{
if ( b[i] < a[i][j] ) b[i] = a[i][j];
if ( a[j][i] < c[i] ) c[i] = a[j][i];
}
}
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
std::cout << std::setw( 3 ) << a[i][j] << '\t';
}
std::cout << '|' << b[i] << '\n';
}
for ( size_t i = 0; i < N; i++ )
{
std::cout << std::setw( 3 ) << '-' << '\t';
}
std::cout << '\n';
for ( size_t i = 0; i < N; i++ )
{
std::cout << std::setw( 3 ) << c[i] << '\t';
}
std::cout << '\n';
return 0;
}
Its output is
1 2 3 |3
4 33 6 |33
7 8 9 |9
- - -
1 2 3
I am trying to write a program which checks if 3 (or more) elements of an array are the same.
I have written a code which works almost perfectly, but it gets stuck when there are 3 pairs of equal elements and I'm not sure how to fix it.
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int n, a[10],skirt=0;
cin >> n;
for(int i = 0; i < n; i++)
{
cin >> a[i];
}
for(int i = 0; i < n; i++)
{
for(int j = i + 1; j < n; j++)
{
if(a[i] == a[j])
{
skirt++;
}
}
}
cout<<skirt<<endl;
if(skirt>=3)
{
cout << "TAIP" << endl;
}
else
{
cout << "NE" << endl;
}
}
When I input
6
3 3 2 2 1 1 i
get "TAIP" but I need to get "NE".
You can use the following algorithm: first sort the array. Then iterate each adjacent pair. If they are equal, then increment counter, if not then reset counter to 1. If counter is 3, return true. If loop does not return true, then return false.
Add the following condition in the outer for loop
for(int i = 0; i < n - 2 && skirt != 3; i++)
^^^^^^^^^^^^^^^^^^^^^^^
{
skirt = 1;
^^^^^^^^^
for(int j = i + 1; j < n; j++)
{
if(a[i] == a[j])
{
skirt++;
}
}
}
Of course before the loop you should check whether n is not less than 3. For example
if ( not ( n < 3 ) )
{
for(int i = 0; i < n - 2 && skirt != 3; i++)
{
skirt = 1;
for(int j = i + 1; j < n; j++)
{
if(a[i] == a[j])
{
skirt++;
}
}
}
}
Here is a demonstrative program
#include <iostream>
using namespace std;
int main()
{
int a[] = { 6, 3, 3, 2, 2, 1, 1 };
int n = 7;
int skirt = 0;
if ( not ( n < 3 ) )
{
for(int i = 0; i < n - 2 && skirt != 3; i++)
{
skirt = 1;
for(int j = i + 1; j < n; j++)
{
if ( a[i] == a[j] )
{
skirt++;
}
}
}
}
cout << skirt << endl;
if ( skirt == 3 )
{
cout << "TAIP" << endl;
}
else
{
cout << "NE" << endl;
}
return 0;
}
Its output is
1
NE
because the array does not have 3 equal elements.
Reset skirt to 0 every time you increase i if it is less than 3, or break out the loop otherwise.
Another way to do this is using a std::map, which keeps a count of the number of times a given value occurs in your array. You would stop looking as soon as you have a number that has three occurrences.
Here's a 'minimalist' code version:
#include <iostream>
#include <map>
using std::cin; // Many folks (especially here on SO) don't like using the all-embracing
using std::cout; // ... statement, "using namespace std;". So, these 3 lines only 'use'
using std::endl; // ... what you actually need to!
int main() {
int n, a[10], skirt = 0;
std::map<int, int> gots;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
for (int i = 0; i < n && skirt < 3; i++) {
skirt = 1;
if (gots.find(a[i]) != gots.end()) skirt = gots[a[i]] + 1;
gots.insert_or_assign(a[i], skirt);
}
cout << (skirt >= 3 ? "TAIP" : "NE") << endl;
return 0;
}
I'm not saying this is any better (or worse) than the other answers - just another way of approaching the problem, and making use of what the Standard Library has to offer. Also, with this approach, you could easily modify the code to count how many numbers occur three or more times, or any number of time.
Feel free to ask for further clarification and/or explanation.
the program works but the problem is the sorted numbers doesnt appear. All it brings up is 1 and that's all. Where is the error?
#include <iostream>
using namespace std;
int const N = 20;
void pirmaisMasivs(int N);
int main (){
cout << "Numbers being sorted - 5,4,2,6,1,3,8,9,10,7 > " << pirmaisMasivs;
}
void pirmaisMasivs(int N){
int temp;
int masivs[10] = {5,4,2,6,1,3,8,9,10,7};
for( int i = 0; i < N - 1; i++ ){
for( int j = 0; j < N - 1; j++ ){
if( masivs[ j ] > masivs[ j + 1 ]){
temp = masivs[ j ];
masivs[ j ] = masivs[ j + 1];
masivs[ j + 1 ] = temp;
}
}
}
}
Your code has several problems.
First your declare your overall count of numbers to be sorted as int const N = 20;, but later you use 10 as a fixed literal count. The N = 20 is apparently wrong. The loops will cause an overrun of the array bounds.
Another problem is, that you do not output your sorted array in any means.
You just try call the sort method. Furthermore, you declare your array of integers to be sorted within your sort method, so you have no chance to access the sorted array outside of this method to print it.
Here is a completely reworked version of your program:
#include <iostream>
using namespace std;
int const N = 10;
int masivs[N] = {5,4,2,6,1,3,8,9,10,7};
void pirmaisMasivs() {
int temp;
for( int i = 0; i < N - 1; i++ ) {
for( int j = 0; j < N - 1; j++ ) {
if( masivs[ j ] > masivs[ j + 1 ]) {
temp = masivs[ j ];
masivs[ j ] = masivs[ j + 1];
masivs[ j + 1 ] = temp;
}
}
}
}
void printMasivs() {
for( int i = 0; i < N; i++ ) {
if ( i == 0 ) {
cout << masivs[ i ];
}
else {
cout << ", ";
cout << masivs[ i ];
}
}
}
int main () {
cout << "Numbers being sorted:\n";
printMasivs();
cout << "\n";
pirmaisMasivs();
cout << "\n";
printMasivs();
}
#include <iostream>
using namespace std;
// Selection Sort function.
// Parameter 'a' is the size of the array.
void ss(int AR[] , int a) {
int small;
for (int i = 0 ; i <a ; i++) {
small = AR[i];
for (int j = i+1 ; j <a ; j++) {
if (AR[j]< small) {
int k = AR[j];
AR[j] = AR[i];
AR[i] = k;
}
}
}
}
int main() {
cout << "Enter the size of Your Aray";
int a;
cin >> a;
int AR[a];
cout << endl;
for (int i = 0; i < a; i++) {
cin >> AR[i];
cout << endl;
}
ss(AR, a);
cout << "The Sorted Array is";
for (int i=0; i < a; i++) {
cout << AR[i] << " ";
cout << endl;
}
}
When I enter the following:
15
6
13
22
23
52
2
The result returned is:
2
13
6
15
22
23
52
What is the bug preventing the list from being sorted numerically as expected?
The function can look like
void ss ( int a[], size_t n )
{
for ( size_t i = 0 ; i < n ; i++ )
{
size _t small = i;
for ( size_t j = i + 1; j < n ; j++ )
{
if ( a[j] < a[small] ) small = j;
}
if ( i != small )
{
int tmp = a[small];
a[small] = a[i];
a[i] = tmp;
}
}
}
It doesn't seem to be the SelectionSort I know. in the algorithm I know during every loop I look for the smallest element in the right subarray and than exchange it with the "pivot" element of the loop. Here's the algorithm
void selectionSort(int* a, int dim)
{
int posMin , aux;
for(int i = 0; i < dim - 1; ++i)
{
posMin = i;
for(int j = i + 1; j < dim; ++j)
{
if(a[j] < a[posMin])
posMin = j;
}
aux = a[i];
a[i] = a[posMin];
a[posMin] = aux;
}
}
and it seems that you change every smaller element you find, but also change the position of the "pivot". I hope the answer is clear.
Everything is ok in the original function, only that the small variable need to be refreshed when two vector elements will be switched.
Also in if statement set the small variable to the new value of AR[i].