How to optimize random sort algorithm? - c++

Here is some random sort program I wrote in C++. It works pretty fine for 10 elements or so. But for 15 elements it works so slow I can't even wait enough to get the result. Is there some way to optimize random sort algorithm?
Here's my code:
// randomsort.h
#ifndef RANDOMSORT_H
#define RANDOMSORT_H
#include <stdlib.h>
#include <time.h>
class RandomSort
{
private:
template <class T>
static bool isOrdered(T*, int);
public:
template <class T>
static int sort(T*, int);
};
template <class T>
bool RandomSort::isOrdered(T* arr, int size)
{
for(int i = 1; i < size; i++)
{
if(arr[i-1] > arr[i])
{
return false;
}
}
return true;
}
template <class T>
int RandomSort::sort(T* arr, int size)
{
int stepAmount = 0;
srand(time(NULL));
while(!isOrdered(arr, size))
{
int i = rand() % size;
int j = rand() % size;
std::swap(arr[i], arr[j]);
stepAmount++;
}
return stepAmount;
}
#endif // RANDOMSORT_H
And main.cpp file
// main.cpp
#include <iostream>
#include "randomsort.h"
int main()
{
int size;
std::cout << "Enter amount of elements to sort: ";
std::cin >> size;
std::cout << std::endl;
int arr[size];
for(int i = 0; i < size; i++)
{
arr[i] = (rand() % (size * 10));
}
std::cout << "Input array: " << std::endl;
for(int i = 0; i < size; i++)
std::cout << arr[i] << ' ';
std::cout << std::endl << std::endl;
int stepAmount = RandomSort::sort(arr, size);
std::cout << "Output array: " << std::endl;
for(int i = 0; i < size; i++)
std::cout << arr[i] << ' ';
std::cout << std::endl << std::endl;
std::cout << "Number of steps: " << stepAmount;
return 0;
}
Any suggestions?

Your code is completely random. So it can swap when it should not. An easy fix would be to swap only if you need it.
int i = rand() % size;
int j = rand() % size;
// to know which should be first
if (i > j)
std::swap(i, j);
if (arr[i] > arr[j])
std::swap(arr[i], arr[j]);
Your array probably will not be sorted immediately, so you could also test if it is sorted only every five steps (for example) instead of every step.
But i think the most important is, you should not expect good performances from such an algorithm.

Related

How to shift values of given array by moving first value to the last C++

I was struggling on how to move the first value to the las in order like shown in the picture
enter image description here
What should I do?
#include <iostream>
using namespace std;
void rotate(int A[], int n = 5)
{
int x = A[n - 1], i;
for (i = n - 1; i > 0; i--)
{
A[i] = A[i -1];
}
A[0] = x;
}
int main()
{
int A[] = { 1, 2, 3, 4, 5 }, i;
int n = sizeof(A) / sizeof(A[5]);
cout << "Given array is \n";
for (i = 0; i < n; i++)
cout << A[i] << ' ';
for (int j = 0; j < n; j++)
{
rotate(A, n);
cout << "\nStep " << j << " --> ";
for (i = 0; i < n; i++)
{
cout << A[i] << ' ';
}
}
return 0;
}
Your code is still quite "C" like. Here is an example that hopefully will teach you some C++ coding :
#include <algorithm>
#include <iostream>
#include <vector>
// passing arrays is easier using std::vector/std::array (no need to pass size seperately)
void rotate(std::vector<int>& values)
{
// using algorithm's std::swap you can better show WHAT you are doing
// vector and array also have a size() method so you don't
// have to use "C" style sizeof tricks.
for (std::size_t n = 0; n < values.size() - 1; ++n)
{
std::swap(values[n], values[n + 1]);
}
}
int main()
{
// prefer std::vector (or std::array) in C++. Not "C" style arrays
std::vector<int> values{ 1,2,3,4,5 };
rotate(values);
// use range based for loop if you can.
for (const auto value : values)
{
std::cout << value << " ";
}
return 0;
}

error: prototype for ' ' does not match any in class ' ';

I recently started coding in c++ and was doing a project. Currently I'm using multiple files, one as a header, one for cpp code, and one as a main file. I've been stuck on a problem for a while now and I just cant figure out whats wrong. Whenever I compile the cpp file I get the error prototype for ‘GradeCalculator::GradeCalculator(const int*, const int&)’ does not match any in class ‘GradeCalculator’. I would really love to get some help and explanation on whats going wrong, here's my code:
//main file:
#include <iostream>
#include "GradeCalculator.h"
#define NUM_ASSIGNMENTS 100
int main() {
int points[NUM_ASSIGNMENTS];
int newsize = 0;
GradeCalculator gradecalculator(points, newsize);
std::cout << "Grade Calculator\n" << std::endl;
std::cout << "================\n" << std::endl;
std::cout << "This program will calculate your grade average on your assignments.\n" << std::endl;
std::cout << "Your lowest grade will be dropped.\n" << std::endl;
newsize = gradecalculator.addPoints(points);
gradecalculator.printResults(points, newsize);
return 0;
}
//header file:
#ifndef DEMO_GRADECALC_H
#define DEMO_GRADECALC_H
#include <iostream>
class GradeCalculator{
private:
int points[100];
int size;
public:
GradeCalculator(int* points, int size);
int addPoints(int*points);
int dropLowest(int* points, int size);
explicit GradeCalculator(const int* points, const int size);
void printResults(int* points, int size);
virtual ~GradeCalculator();
};
#endif
//cpp file:
#include <iostream>
#include "GradeCalculator.h"
GradeCalculator::GradeCalculator(const int* points, const int &size){
}
int GradeCalculator::addPoints(int* points){
int sizeofarray = 0;
for( int j = 0; points[j] = '\0'; j++){
std::cin >> points[j];
sizeofarray ++;
}
return sizeofarray;
}
int GradeCalculator::dropLowest(int* points, int size) {
int lowest = points[0];
int lowestIndex = 0;
for( int i = 0; i < size; i++ ) {
if( points[i] < lowest ) {
lowest = points[i];
lowestIndex = i;
}
}
for( int i = lowestIndex; i < size-1; i++ ) {
points[i] = points[i+1];
}
return size - 1;
}
void GradeCalculator::printResults(int* points, int size){
dropLowest(points, size);
int newtotal;
for(int k = 0; points[k] = '\0'; k++){
newtotal += points[k];
}
float avg = newtotal/size;
std::cout << "Total Points: " << newtotal << "\n" << std::endl;
std::cout << "Average: " << avg << "\n" << std::endl;
}

Repeating Array elements

I am running a code for finding repeating array elements.
I am doing it using 2 functions, however when I run the code my application immedietaly crashes despite assigning it to random numbers from 1 to 99.
Here is the code. Thank you..
#include <ctime>
#include <iostream>
using namespace std;
int UniqueArray(int arr[], int notunique);
void printarray(int arr[]);
int main() {
int arr[20];
int dup = 0;
printarray(arr);
for (int i = 0; i < 20; ++i) {
UniqueArray(arr, dup);
}
}
int UniqueArray(int arr[], int notunique) {
notunique = 0;
int i, j;
int size = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < size; i++) {
for (j = i + 1; j < size; j++) {
if (arr[i] == arr[j]) {
notunique++;
cout << "Array has duplicates: " << arr[i] << " ";
}
}
}
return notunique;
cout << "There were " << notunique << " Repeated elements";
}
void printarray(int arr[]) {
int size = sizeof(arr) / sizeof(arr[0]);
srand(time(0));
arr[20] = rand () % +100;
for (int i = 0; i < 20; ++i) {
cout << arr[i] << " ";
}
}
This line:
arr[20] = rand () % +100;
does not fill an array of size 10 with random values. It indexes the 20th position, which is UB.
You could fill the array with random numbers, using std::generate, like this:
std::generate(arr, arr + 20, [] { return rand() % 100; });
Also, when finding the size of the array, you'll need to deduce the size:
template <size_t N>
void printarray(int (&arr)[N]) {
// ... use N which is the size of arr
or even better, use std::array, which does this for you.
Some minor issues:
Don't use using namespace std;.
In this snippet:
return notunique;
cout << "There were " << notunique << " Repeated elements";
the statement after the return will never get executed.
In this line:
arr[20] = rand () % +100;
you don't need the + operator.

Getting out of range exception when using while loop with vector in c++

I am getting an out of range exception with my while loop in my code.
I have tried to use an Array instead and the error does not occur with the same loop structure. I am confused why this would happen. I believe that the savedValue <= value[rank.at(current-1)]) statement is what is causing the error.
int suffixArray::size;
std::vector<int> suffixArray::rank;
int main( int argc, char* argv[]) {
std:: string test = "BANANA$";
suffixArray testString (test);
return 0;
}
#include <iostream>
#include <vector>
class suffixArray{
public: static int size;
public: static std::vector<int> rank;
public: suffixArray(std:: string concatenated ){
size =(int) concatenated.length();
std:: cout << size << std:: endl;
rank.resize(7);
char *suffixPointers[concatenated.length()];
int value[concatenated.length()];
for(int i =0; i <= size-1; i++){
suffixPointers[i] = &concatenated[i];
value[i] = (int)concatenated[i];
}
std::cout << "[";
for(int i = 0; i<= size-1; i++){
std::cout <<value[i] << " ";
}
std::cout << "]"<< std:: endl;
for(int i = 0; i<=size -1; i++){
if(i == 0){
rank.assign(i,i);
}
else if(value[i] > value[i-1]){
rank.assign(i,i);
}else{
int current =i;
int savedValue = value[i];
int prevSavedRank;
while(current-1 >= 0 && savedValue <= value[rank.at(current-1)]){
prevSavedRank= rank.at(current-1);
rank.assign(current-1, i);
rank.assign(current, prevSavedRank);
current--;
}
}
}
}
};
Adding more logging into your program reveals the problem: you rank.assign(0,0) - the first 0 specifies the new vector length, so this call removes all the elements in the vector (see std::vector::assign docs at cppreference) then call rank.at(0): 0 is not a valid index into an empty vector, so std::out_of_range.
You'll have to rethink your logic.
Program with extra logging:
#include <iostream>
#include <vector>
template <typename T>
struct Vector : std::vector<T>
{
void assign(size_t count, const T& value)
{
std::cout << "assign(count " << count << ", " << value << ")\n";
std::vector<T>::assign(count, value);
}
const T& at(size_t pos) const
{
std::cout << "at(" << pos << ")\n";
return std::vector<T>::at(pos);
}
};
class suffixArray{
public: static int size;
public: static Vector<int> rank;
public: suffixArray(std:: string concatenated ){
size =(int) concatenated.length();
std:: cout << size << std:: endl;
rank.resize(7);
char *suffixPointers[concatenated.length()];
int value[concatenated.length()];
for(int i =0; i <= size-1; i++){
suffixPointers[i] = &concatenated[i];
value[i] = (int)concatenated[i];
}
std::cout << "[";
for(int i = 0; i<= size-1; i++){
std::cout <<value[i] << " ";
}
std::cout << "]"<< std:: endl;
for(int i = 0; i<=size -1; i++){
if(i == 0){
rank.assign(i,i);
}
else if(value[i] > value[i-1]){
rank.assign(i,i);
}else{
int current =i;
int savedValue = value[i];
int prevSavedRank;
while(current-1 >= 0 && savedValue <= value[rank.at(current-1)]){
prevSavedRank= rank.at(current-1);
rank.assign(current-1, i);
rank.assign(current, prevSavedRank);
current--;
}
}
}
}
};
int suffixArray::size;
Vector<int> suffixArray::rank;
int main( int argc, char* argv[]) {
std:: string test = "BANANA$";
suffixArray testString (test);
}
Output:
7
[66 65 78 65 78 65 36 ]
assign(count 0, 0)
at(0)
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check: __n (which is 0) >= this->size() (which is 0)
I have tried to use an Array instead and the error does not occur with the same loop structure.
std::array and C-style arrays (T[]) are fixed sized containers, lacking an equivalent of the std::vector::assign you're using to resize your vector, so your program must have been modified quite heavily - not just a clean substitution of an array.

C++ Turning arrays into functions?

I have been attempting this for hours to no avail, as you can see in my code I have separate functions, they were all together in main, but I am required to turn each into a separate function. However when I try anything I get errors, even when I try to pass parameters. Can someone point me in the right direction?
#include <iostream>
#include <cstdlib>
#include <ctime>
void printarray();
void average();
void largestnumber();
using namespace std;
int main()
{
printarray();
average();
largestnumber();
}
void printarray() {
srand(time(0));
int n[10], tot = 0;
for (int i = 0; i < 10; i++)
{
n[i] = (1 + rand() % 100);
cout << n[i] << endl;
}
}
void average() {
int j, tot = 0, n[10];
for (j = 0; j < 10; j++)
{
tot += n[j];
}
cout << "The average of the numbers in the array are " << tot / j << endl;
}
void largestnumber() {
int w = 1, int n[10];
int temp = n[0];
while (w < 10)
{
if (temp < n[w])
temp = n[w];
w++;
}
cout << "The largest number in the array is " << temp << endl;
}
The array you are working with needs to be passed in to each function, so the same array is used everywhere. It is a good idea to pass the size as well, just for flexibility reasons.
Now your functions pretty much work as you wrote them.
#include <iostream>
#include <cstdlib>
#include <ctime>
void printarray(int n[], size_t size);
void average(int n[], size_t size);
void largestnumber(int n[], size_t size);
using namespace std;
int main()
{
const size_t arr_size = 10;
int n[arr_size];
printarray(n, arr_size);
average(n, arr_size);
largestnumber(n, arr_size);
}
void printarray(int n[], size_t size) {
srand((unsigned int)time(0));
int tot = 0;
for (size_t i = 0; i < size; i++)
{
n[i] = (1 + rand() % 100);
cout << n[i] << endl;
}
}
void average(int n[], size_t size) {
size_t j;
int tot = 0;
for (j = 0; j < size; j++)
{
tot += n[j];
}
cout << "The average of the numbers in the array are " << tot / j << endl;
}
void largestnumber(int n[], size_t size) {
size_t w = 1;
int temp = n[0];
while (w < size)
{
if (temp < n[w])
temp = n[w];
w++;
}
cout << "The largest number in the array is " << temp << endl;
}
One simple improvement is to break the printarray out into an initarray function that fills the array and printarray that prints the content.
It would also be a good idea to do some checking for things like an empty array (functions assume n[0] exists, for instance).
The next obvious step is to put all this in a class. Also, if you are allowed to, the c array should be replaced with a vector, as that does a great job of keeping all the resource information together.