Comparisons in Multiple Sorting Algorithms - c++

Currently this program will generate 10 random numbers and either sort (from least to greatest), reverse sort, or shuffle them. However, when trying to list the number of comparisons made, the number of comparisons printed out are completely incorrect. For example, it prints that there were 44 comparisons with bubble sort (this is the one that varies every time but is usually around 40), 45 with selection sort, and 9 with insertion sort. For now I'm only running the program with numbersSorted() just to make sure the comparisons work.
How can I print the correct number of comparisons made with each sorting method?
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int count1 = 0; //bubble
int count2 = 0; //selection
int count3 = 0; //insertion
vector<int> numbersSorted(int n);
vector<int> numbersReversed(int n);
vector<int> numbersShuffled(int n);
int main() {
srand(time(0));
numbersSorted(10);
//numbersReversed(10);
//numbersShuffled(10);
return 0;
}
vector<int> numbersSorted(int n)
{
vector <int> v(n);
for (auto &x : v)
x = rand() % 100;
cout << "Original list to be sorted: ";
for (auto x : v)
cout << x << " ";
cout << "\n\n";
// bubble sort
bool swapped = true;
for (int pass = 0; pass <= n - 2 && swapped; ++pass)
{
swapped = false;
for (int i = 0; i <= n - pass - 2; ++i)
{
++count1;
if (v.at(i) > v.at(i + 1))
{
swap(v[i], v[i + 1]);
swapped = true;
}
}
}
cout << "Bubble sort sorted: ";
for (auto x : v)
cout << x << " ";
cout << "\n";
cout << "There were " << count1 << " comparisons with bubble sort.\n" <<
endl;
// selection sort
for (int pass = 0; pass <= n - 2; ++pass)
{
// Find least element remaining in the list starting at index pass
int minIndex = pass;
// i = minIndex + 1, minIndex + 1, ..., n - 1
for (int i = minIndex + 1; i < n; i++)
{
++count2;
if (v[i] < v[minIndex])
{
minIndex = i;
}
// The element at index i is smaller than what I thought was the
min
}
swap(v[pass], v[minIndex]);
}
cout << "Selection sort sorted: ";
for (auto x : v)
cout << x << " ";
cout << "\n";
cout << "There were " << count2 << " comparisons with selection sort.\n" <<
endl;
//insertion sort
for (int pass = 0; pass <= n - 2; ++pass) {
// Take the element at pass+1 and move it to the left until it's in the
// right spot (i.e., as long as it's in the wrong spot).
// for i = pass, pass-1, ..., 0 while L[i] > L[i+1]
++count3;
for (int i = pass; i >= 0 && v[i] > v[i + 1]; --i) {
swap(v[i], v[i + 1]);
}
}
cout << "Insertion sort sorted: ";
for (auto x : v)
cout << x << " ";
cout << "\n";
cout << "There were " << count3 << " comparisons with insertion sort.\n" <<
endl;
//return v;
}
vector<int> numbersReversed(int n)
{
vector <int> v(n);
for (auto &x : v)
x = rand() % 100;
cout << "Original list to be reversed: ";
for (auto x : v)
cout << x << " ";
cout << "\n\n";
// bubble sort
bool swapped = true;
for (int pass = 0; pass <= n - 2 && swapped; ++pass)
{
swapped = false;
for (int i = 0; i <= n - pass - 2; ++i)
{
++count1;
if (v.at(i) > v.at(i + 1))
{
swap(v[i], v[i + 1]);
swapped = true;
}
}
}
//reverse the content of the vector
reverse(v.begin(),v.end());
cout << "Bubble sort reversed: ";
for (auto x : v)
cout << x << " ";
cout << "\n";
cout << "There were " << count1 << " comparisons with bubble sort.\n" <<
endl;
// selection sort
for (int pass = 0; pass <= n - 2; ++pass)
{
// Find least element remaining in the list starting at index pass
int minIndex = pass;
// i = minIndex + 1, minIndex + 1, ..., n - 1
for (int i = minIndex + 1; i < n; i++)
{
++count2;
if (v[i] < v[minIndex])
// The element at index i is smaller than what I thought was the
min
minIndex = i;
}
swap(v[pass], v[minIndex]);
}
reverse(v.begin(),v.end());
cout << "Selection sort reversed: ";
for (auto x : v)
cout << x << " ";
cout << "\n";
cout << "There were " << count2 << " comparisons with selection sort.\n" <<
endl;
// insertion sort
for (int pass = 0; pass <= n - 2; ++pass) {
// Take the element at pass+1 and move it to the left until it's in the
// right spot (i.e., as long as it's in the wrong spot).
// for i = pass, pass-1, ..., 0 while L[i] > L[i+1]
++count3;
for (int i = pass; i >= 0 && v[i] > v[i + 1]; --i) {
swap(v[i], v[i + 1]);
}
}
reverse(v.begin(),v.end());
cout << "Insertion sort reversed: ";
for (auto x : v)
cout << x << " ";
cout << "\n";
cout << "There were " << count3 << " comparisons with insertion sort.\n" <<
endl;
}
vector<int> numbersShuffled(int n)
{
vector<int> v(n);
for (auto &x : v)
{
x = rand() % 100;
++count1;
}
cout << "Numbers Shuffled: ";
for (auto x : v)
cout << x << " ";
cout << "\n";
cout << "There were " << count1 << " comparisons made. " << endl;
}

Related

how to solve this using Arrays?

I'm new to programming is there a way to solve this:
Take 10 integer inputs from user and print the following
number of positive numbers.
number of negative numbers.
number of odd numbers.
number of even numbers
#include <iostream>
using namespace std;
int main()
{
int numArray[10];
cout<<"Enter Number :";
for(int i=0; i<10; i++)
{
cin>>numArray[i];
}
for(int i=0; i<numArray[i]; i++)
{
if(numArray[i]>0)
{
cout<<"Positive Number "<<numArray[i] <<endl;
}
else
{
cout<<"Negative Number "<<numArray[i]<<endl;
}
if(numArray[i]%2==0)
{
cout<<"Odd number "<<numArray[i]<<endl;
}
else
{
cout<<"even number "<<numArray[i]<<endl;
}
}
return 0;
}
You could do this without arrays but I'm just gonna stick with your original intent for clarity.
#include <iostream>
#include <array>
using namespace std;
int main()
{
array<int, 10> numArray; //an array of ints, size 10. this is CPP style array, it is 'safer' than C-style array. (someone correct me)
//get your 10 inputs.
cout << "Enter Number :";
for(size_t i = 0; i < numArray.size(); i++)
{
cin >> numArray[i];
}
int positive_count = 0;
int negative_count = 0;
int even_count = 0;
int odd_count = 0;
//loop thru your 10 inputs, increment counters accordingly.
for(size_t i = 0; i < numArray.size(); i++)
{
if (numArray[i] < 0)
{
negative_count += 1;
}
if (numArray[i] > 0)
{
positive_count += 1;
}
if (numArray[i] % 2 == 0)
{
even_count += 1;
}
else
{
odd_count += 1;
}
}
cout << "Positive Number " << positive_count << endl;
cout << "Negative Number " << negative_count << endl;
cout << "even number " << even_count << endl;
cout << "Odd number " << odd_count << endl;
return 0;
}
You could do it in input loop:
int positives = 0, zeros = 0, odds = 0;
int negatives = 0, evens = 0;
for(size_t i = 0; i < numArray.size(); i++)
{
cin >> numArray[i];
// increment number of odds
odds += numArray[i] & 0x1;
// odds += numArray[i] % 2;
// increment number of positives
positives += (numArray[i] > 0);
// positives += (numArray[i] > 0 ? 1 : 0);
// increment zeros
zeros += !(numArray[i] | 0);
}
evens = 10 - odds;
negatives = 10 - zeros - positives;
cout << "Positive count " << positives << endl;
cout << "Negative Number " << negatives << endl;
cout << "Even number " << evens << endl;
cout << "Odd number " << odds << endl;
and here is newbie friendly version:
int positives = 0, zeros = 0, odds = 0;
int negatives = 0, evens = 0;
for(size_t i = 0; i < numArray.size(); i++)
{
cin >> numArray[i];
// increment number of odds
if (numArray[i] % 2 == 1)
odds++;
if (numArra[i] == 0)
zeros++;
else if (numArray[i] > 0)
positives++;
}
evens = 10 - odds;
negatives = 10 - zeros - positives;
cout << "Positives " << positives << '\n';
cout << "Negatives " << negatives << '\n';
cout << "Evens " << evens << '\n';
cout << "Odds " << odds << '\n';

How can I convert for loops into for-each loops?

My task is to convert my for loops into for-each loops.
The task begins with creating a two dimensional array 6x30. This represents 6 classes of 30 students each. Each position in the array contains a random number between 55 and 100 which represents a student score.
Next I display that array to the console.
Next I calculate the average score of each class.
Next I find the highest average among the 6 classes and display that to the screen.
I am using Xcode on MacBook Pro.
Question: How can I properly convert my for loops into for-each loops?
My code is below:
#include <iostream>
#include <iomanip>
using namespace std;
const int NUM_CLASSES = 6, NUM_STUDENTS_PER_CLASS = 30;
void bubbleSort(int arr[], int n){
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (arr[j] < arr[j + 1])
swap(arr[j], arr[j + 1]);
}
}
}
void classGradeGeneration() {
int arrayOne[NUM_CLASSES][NUM_STUDENTS_PER_CLASS], classAverage[NUM_CLASSES];
//Generating random average student scores until array filled
for (int classNumber = 0; classNumber < NUM_CLASSES; classNumber++) {
for (int column = 0; column < NUM_STUDENTS_PER_CLASS; column++) {
arrayOne[classNumber][column] = rand() % 46 + 55;
}
}
//Displaying array of student scores
for (int classNumber = 0; classNumber < NUM_CLASSES; classNumber++) {
cout << "Class " << classNumber + 1 << ": ";
for (int column = 0; column < NUM_STUDENTS_PER_CLASS; column++) {
cout << setw(3) << arrayOne[classNumber][column] << " ";
classAverage[classNumber] += arrayOne[classNumber][column];
}
cout << endl;
}
cout << endl;
int averageScore, averageOfClasses[NUM_CLASSES];
//Displaying average class scores
for (int temp = 0; temp < NUM_CLASSES; temp++) {
averageScore = classAverage[temp] / NUM_STUDENTS_PER_CLASS;
cout << "Class " << temp + 1 <<" Average score: " << averageScore << endl;
averageOfClasses[temp] = averageScore;
}
cout << endl;
bubbleSort(averageOfClasses, NUM_CLASSES); // Sorting average scores highest to lowest
cout << endl;
cout << "The highest average score is: " << averageOfClasses[0];
cout << endl;
}
int main () {
srand(time(NULL));
classGradeGeneration();
cout << endl << endl;
}
Below is a sample output:
You may use range-based for with std::array since C++11
constexpr int NUM_CLASSES = 6, NUM_STUDENTS_PER_CLASS = 30;
std::array<std::array<int, NUM_STUDENTS_PER_CLASS>, NUM_CLASSES> arr;
for (/*const*/ auto& ln : arr) {
std::cout << "LINE" << std::endl;
for (/*const*/ auto& elem : ln) {
std::cout << "elem" << std::endl;
}
}
or for_each if you want
std::for_each(arr.begin(), arr.end(), [](/*const*/ auto& line) {
std::cout << "LINE" << std::endl;
std::for_each(line.begin(), line.end(), [](/*const*/ auto& elem) {
std::cout << "elem" << std::endl;
});
});
But I prefer range-based for in this case.
If you use c-style array then for_each arguments will be pointers, not iterators.
int arr[NUM_CLASSES][NUM_STUDENTS_PER_CLASS], classAverage[NUM_CLASSES];
std::for_each(std::begin(arr), std::end(arr), [](/*const*/ auto& line) {
std::cout << "LINE" << std::endl;
std::for_each(std::begin(line), std::end(line), [](/*const*/ auto& elem) {
std::cout << "elem" << std::endl;
});
});
So your code may look like this
constexpr int NUM_CLASSES = 6, NUM_STUDENTS_PER_CLASS = 30;
std::array<std::array<int, NUM_STUDENTS_PER_CLASS>, NUM_CLASSES> arr;
// set random values
for (auto& ln : arr) {
for (auto& elem : ln) {
elem = std::rand() % 100;
}
}
// calculate
float avgScore = 0.0F;
for (const auto& ln : arr) {
const auto avgGroupScore = std::accumulate(std::begin(ln), std::end(ln), 0.0F) / (std::end(ln) - std::begin(ln));
avgScore = std::max(avgScore, avgGroupScore);
std::cout << "avg group score=" << avgGroupScore << "; current avgScore=" << avgScore << std::endl;
}

Find all triplets in an array that sum to a given value.There are duplicates in the array

This is the code I wrote-
void FindTriplet(int arr[], int size, int x) {
sort(arr,arr+size);
for(int i=0;i<size-2;i++)
{
int l=i+1;
int r=size-1;
while(l<r)
{
int sum=arr[i]+arr[l]+arr[r];
if(sum==x)
{
cout << arr[i] << " " << arr[l] << " " << arr[r] << endl;
l++;
r--;
}
else if(sum<x)
{
l++;
}
else
{
r--;
}
}
}
}
The complexity of O(n^3) is not acceptable.
But this code is failing on cases like-
1 1 1 1 where required sum is 3.
Ans. 1 1 1 repeated 4 times
You have do handle duplicates when you found correct sum:
if (sum==x)
{
// skip and count duplicates
const auto oldL = l;
do {
++l;
} while (l <= r && arr[oldL] == arr[l]);
const auto oldR = r;
do {
--r;
} while (l <= r && arr[oldR] == arr[r]);
// resulting count
const auto count = (arr[oldL] == arr[oldR]
? (l - oldL) * (l - oldL - 1) / 2
: ((l - oldL) * (oldR - r)));
for (int j = 0; j != count; ++j) {
std::cout << arr[i] << " " << arr[oldL] << " " << arr[oldR] << std::endl;
}
}
Demo
You'd better make use of STL classes. I wrote some code for you.
#include <iostream>
#include <vector>
#include <map>
using namespace std;
void findTripletSums(const std::vector<int>& arr, int tripleSum)
{
std::map<int,int> arrMap; // counts the number of times the number is repeated
for(auto a : arr)
{
arrMap[a]++;
}
for(auto itrI = arrMap.begin(); itrI != arrMap.end(); ++itrI)
{
int arrI = itrI->first;
if(arrI*3 == tripleSum && itrI->second >= 3)
{
cout << arrI << " " << arrI << " " << arrI << "; ";
return;
}
auto itrJ = itrI;
for(++itrJ; itrJ != arrMap.end(); ++itrJ)
{
int arrJ = itrJ->first;
int complement = tripleSum-arrI-arrJ;
if(complement < itrJ->first)
{
break;
}
if(complement == arrJ)
{
if(itrJ->second >= 2)
{
cout << arrI << " " << arrJ << " " << arrJ << "; ";
}
break;
}
if(arrMap.find(complement) != arrMap.end())
{
cout << arrI << " " << arrJ << " " << complement << "; ";
}
}
}
}
int main()
{
findTripletSums({0,1,3,3,2,4,6}, 7);
cout << "\n";
findTripletSums({1,2,3,4,5,6}, 7);
cout << "\n";
findTripletSums({0,1,1,1,1,2}, 3);
return 0;
}
It prints:
0 1 6; 0 3 4; 1 2 4; 1 3 3;
1 2 4;
0 1 2; 1 1 1;

Output (at most) 4 vector Elements in a Row

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <vector>
#include <conio.h>
using namespace std;
int main()
{
cout << "Enter the numbers: " << endl << "Write eof() when you want to end" << endl;
int x;
vector<int> num;
//enter numbers till eof() is encountered
while (cin >> x) {
num.push_back(x);
}
//sort the vector
sort(num.begin(), num.end());
//get size of the vector
typedef vector<double>::size_type vec_sz;
vec_sz size = num.size();
//loop to print 4 numbers according to size
for (auto i = 0; i < size; i++)
{
cout << num[i];
if (i == size - 1)
break;
i++;
cout << " " << num[i];
if (i == size - 1)
break;
i++;
cout << " " << num[i];
if (i == size - 1)
break;
i++;
cout << " " << num[i];
if (i == size - 1)
break;
cout << endl;
//<< " " << num[i + 1] << " " << num[i + 2] << " " << num[i + 3] <<
}
_getch();
return 0;
}
I want to print 4 numbers at a time of a vector of int's. When I tried to print the vector by doing i+=4 in the for loop, the compiler complained that 'i' was going over the size of the vector and the program crashed.
Right now, what I have is works, but I find it really boring the way it's implemented right now and there must be a nice way to do it.
So my questions are -
1) How can I tidy up the code more?
2) When using a loop, how does the compiler access the memory in which vector contents are stored?
3) How to implement error checking so that the loop variable does not access elements beyond the vector size?
for (int i = 0; i < size; i++)
{
cout << num[i];
if ((i % 4) == 3)
cout << endl;
else
cout << " ";
}
if ((size % 4) != 0)
cout << endl;
One solution could be,
for( int i = 0; i < size; ++i ) {
int nextNumber = i + 1; // Just so you don't mix up the index
if ( ( nextNumber % 4 ) == 0 ) {
std::cout << num[ i ] << std::endl;
}
else {
std::cout << num[ i ] << ' ';
}
}
This allows you to easily change to other sizes by changing only one number. (ie, from 4 to 5, etc )
My entry to this competition is using a free function to your aid:
template <typename RAN_IT>
RAN_IT four_or_last(RAN_IT begin, RAN_IT end){
for (RAN_IT it = begin; it != begin + 4; it++){
if (it == end)
return end;
}
return begin + 4;
}
The loop can then be described as:
for (auto it = num.begin(); it != num.end(); /*inc in inner loop*/) {
for (auto in = it; in != four_or_last(it, num.end()); in++) {
std::cout << *in << " ";
}
it = four_or_last(it, num.end());
std::cout << std::endl;
}

Print an array in C++

I'm trying to do some of my C++ homework, but I seem to have run into an issue. I need to make it so that the user inputs 8 numbers, and those said 8 get stored in an array. Then, if one of the numbers is greater than 21, to output said number. The code is below, and it's kind of sloppy. Yes, first year C++ learner here :p
#include <iostream>
using namespace std;
int main() {
const int NUM_ELEMENTS = 8; // Number of elements
int userVals[NUM_ELEMENTS]; // User numbers
int i = 0; // Loop index
int sumVal = 0; // For computing sum
int prntSel = 0; // For printing greater than 21
// Prompt user to populate array
cout << "Enter " << NUM_ELEMENTS << " integer values..." << endl;
for (i = 0; i < NUM_ELEMENTS; ++i) {
cin >> userVals[i];
}
for (int i = NUM_ELEMENTS - 1; i > 21; i--)
cout << "Value: " << sumVal << endl;
// Determine sum
sumVal = 0;
for (i = 0; i < NUM_ELEMENTS; ++i) {
sumVal = sumVal + userVals[i];
}
cout << "Sum: " << sumVal << endl;
return 0;
}
Don't reinvent the wheel, use standard algorithms:
std::copy_if(std::begin(userVals), std::end(userVals),
std::ostream_iterator<int>(std::cout, "\n"),
[] (auto x) { return x > 21; });
I improved the rest of your program as well:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <numeric>
#include <vector>
auto constexpr count = 8;
int main() {
std::vector<int> numbers(count);
std::cout << "Enter " << count << " integer values...\n";
std::copy_n(std::istream_iterator<int>(std::cin), numbers.size(), numbers.begin());
std::copy_if(numbers.begin(), numbers.end(),
std::ostream_iterator<int>(std::cout, "\n"),
[] (auto x) { return x > 21; });
auto sum = std::accumulate(numbers.begin(), numbers.end(), 0);
std::cout << "Sum: " << sum << '\n';
return 0;
}
See it live on Coliru!
Ok, I'm going to explain this to you and keep it simple. This loop
`for (int i = NUM_ELEMENTS - 1; i > 21; i--)`
will never execute because in your first iteration you are checking if (NUM_ELEMENTS-1=7)>21. You are then decrementing i so this will take the series (6,5,4,...) and nothing would ever happen here.
If you have to sum the numbers greater than 21, which I presume is what you need then you will have to remove the above loop and modify your second loop to:
for (i = 0; i < NUM_ELEMENTS; i++) {
if(userVals[i]>21)
sumVal = sumVal + userVals[i];
}
This way, you add the numbers in the array that are only greater than 21. The index of userVals is determined by the i variable which also acts as a counter.
You're on the right track. There's just a few things wrong with your approach.
#include <iostream>
#include <stdlib.h>
using namespace std;
int main() {
const int NUM_ELEMENTS = 8;
int userVals[NUM_ELEMENTS];
int i = 0;
int sumVal = 0;
int prntSel = 0;
int size = sizeof(userVals) / sizeof(int); // Get size of your array
// 32/4 = 8 (ints are 4 bytes)
cout << "Enter " << NUM_ELEMENTS << " integer values..." << endl;
for (i = 0; i < NUM_ELEMENTS; ++i) {
cin >> userVals[i];
}
for(int i = 0; i < size; i++) {
if(userVals[i] > 21) { // Is number > 21?
cout << userVals[i] << endl; // If so, print said number
exit(0); // And exit
}
else
sumVal += userVals[i]; // Else sum your values
}
cout << "Sum: " << sumVal << endl;
return 0;
}
#include <iostream>
using namespace std;
int main() {
const int NUM_ELEMENTS = 8; // Number of elements
int userVals[NUM_ELEMENTS]; // User numbers
int i = 0; // Loop index
int sumVal = 0; // For computing sum
int prntSel = 0; // For printing greater than 21
// Prompt user to populate array
cout << "Enter " << NUM_ELEMENTS << " integer values..." << endl;
for (i = 0; i < NUM_ELEMENTS; ++i) {
cin >> userVals[i];
}
// for (int i = NUM_ELEMENTS - 1; i > 21; i--)
// cout << "Value: " << sumVal << endl;
for( i = 0; i < NUM_ELEMENTS; ++i )
{
if( userVals[ i ] > 21 )
{
cout << "Value: " << i << " is " << userVals[ i ] << endl;
}
}
for (i = 0; i < NUM_ELEMENTS; ++i) {
sumVal = sumVal + userVals[i];
}
cout << "Sum: " << sumVal << endl;
return 0;
}
Try
for (int i = NUM_ELEMENTS - 1; i > 21; i--)
cout << "Value: " << sumVal << endl;
to
for (i = 0; i < NUM_ELEMENTS; ++i) {
if(userVals[i] > 21)
cout << "Value: " << userVals[i] << endl;
}
This line isnt needed as well, as you arent using it.
int prntSel = 0; // For printing greater than 21
for (int i = NUM_ELEMENTS - 1; i > 21; i--)
cout << "Value: " << sumVal << endl;
Here you are printing the value of sumVal, not the value of the array in the position i. The line should be:
cout << "Value: " << usersVals[i] << endl;
Also that that your for is not doing what you think it does. for doesn't use the condition you gave to decide if will execute the current iteration or not, it uses the condition to decide if the loop should continue or not. So when you put i > 21, means that it will continue running while i is bigger than 21. To achieve your goal, you should make a test (if statement) inside the loop.
The final result it would be:
for (i = 0; i < NUM_ELEMENTS; ++i) {
if (usersVals[i] > 21) {
cout << "Value: " << usersVals[i] << endl;
}
}