"no matching function call" with templated functions project - c++

I am writing a program to generate and sort an array of random numbers.
The compiler gives me the following error:
select.cxx: In function ‘void selectionsort(Item*, SizeType)
[withItem = int, SizeType = long unsigned int]’:
select.cxx:95: instantiated from here
select.cxx:16: error: no matching function for call to ‘swap(int*&, long unsigned int&, long unsigned int&)’
Here is my code:
#include <cassert>
#include <cstdlib>
#include <iostream>
#include <time.h>
using namespace std;
template <class Item, class SizeType>
void selectionsort(Item data[], SizeType n)
{
for (SizeType i = 0; i = n - 2; i++)
{
SizeType j = index_of_minimal(data, i, n);
swap(data, i, j); //data[i] swapped with data[j](minimum)
}
}
template <class Item, class SizeType>
std::size_t index_of_minimal(const Item data[], SizeType i, SizeType n)
{
size_t min = i; //holds index of minimum (initialized to i)
Item t1 = data[i]; //temporary holder for comparing values, initialized as i (starting value)
Item t2; //second holder
for (SizeType j = i++; j = n - 1; j++)
{
t2 = data[j];
if (t2 < t1)
{
t1 = data[j];
min = j;
}
}
return min;
}
template <class Item, class SizeType>
void swap(Item data[], SizeType i, SizeType j) //data[i] swapped with data[j](minimum)
{
Item temp; //holds value to be swapped
temp = data[i];
data[i] = data[j];
data[j] = temp;
}
template <class Item, class SizeType>
void listPrint(Item data[ ], SizeType n)
{
cout << "array:";
for (SizeType i = 0; i = n - 1; i++)
{
cout << " " << data[i];
}
cout << endl;
}
int myrand(int lower, int upper)
{
return (lower + rand() % ( upper - lower + 1 ) );
}
int main()
{
size_t n; //user input
//For random number generator//
srand(time(NULL));
cout << "Please enter a number:" << endl;
cin >> n;
while (n < 1)
{
cout << "Error: please enter a number 1 or larger" << endl;
cin >> n;
}
int rNumbers[n]; //declares int array of size n
int randomN; //to hold randomly generated number
for (size_t i = 0; i < n; i++)
{
randomN = myrand(1, 1000); //generates a random number as randomN
rNumbers[i] = randomN;
}
cout << "Unsorted ";
listPrint(rNumbers, n);
selectionsort(rNumbers, n);
cout << "Sorted ";
listPrint(rNumbers, n);
}
I have a feeling that the problem has to do with the data types passed to the swap function. I am also confused as to why the first line of the error states that SizeType = long unsigned int, when the data type of n as declared in main() is size_t.

Make sure that the other functions you call inside your template function are visible. So, define selection_sort() after swap() and index_of_minimal().
Side remark:
int rNumbers[n]; //declares int array of size n
declares a variable sized array, which is not standard C++ (some compilers support it though, but you shouldn't rely on this). If you want a run-time sized array, use std::vector instead.
Regarding your confusion at the end, size_t is a type alias, which in your implementation it happens to be for unsigned long int, so that's why the error mentions it.

Related

Implementing algorithms for Randomly generated array

So I have the following code to generate an array comprised of random numbers from 1-20000 and the array can have different sizes (100, 500, 1000 etc).
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <cstdlib>
#include <ctime>
using namespace std;
void insertSort(int input[]);
/*
void quickSort(int input[], int, int);
void mergeSort(int input[], int, int);
void merge(int input[], int, int, int);
void percolate(int numbers[], int, int);
void heapSort(int numbers[], int);
*/
int SIZE; //global Size variable
int main()
{
int i;
//int size;
int random_once[10000]; //maximum array size
srand(time(0));
cout << "How big would you like the list to be?" << "\n\n";
cout << "\t Enter any of the following: 100, 500, 1000, 2000, 5000, 8000, or 10000" << "\n";
cin >> SIZE;
for (int i=0; i<SIZE; i++)
{
random_once[i]=rand() % 20000; //generating a random number between 1 - 20000
// generate unique random number only once so no duplicates
for(int j=0; j<i; j++) if (random_once[j]==random_once[i]) i--;
}
cout<< " " << i << "\n\n\n ";
for(i=0; i<SIZE; i++) cout << " " << random_once[i] << "\t"; //outputting array to console
return 0;
}
//insert sort algorithm
void insertSort(int input[]) {
int i, j, temp;
for (i = 0; i < SIZE; i++) {
temp = input[i];
for (j = i; j > 0 && temp < input[j - 1]; j--) {
input[j] = input[j - 1];
}
input[j] = temp;
}
return;
}
I was wondering how I can have the insertion sort be printed out so that it prints out the sorted array after it used the insertion sort algorithm.
I was also wondering how I can print out the time complexity of the algorithm before being sorted and after so that I can compare it with other sorting algorithms.
EDIT (with added template)
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <chrono>
#include <string>
using namespace std;
void insertSort(int input[]);
/*
void quickSort(int input[], int, int);
void mergeSort(int input[], int, int);
void merging(int input[], int, int, int);
void percolate(int numbers[], int, int);
void heapSort(int numbers[], int);
*/
int SIZE; //global Size variable
template <typename F, typename... Args>
std::string callTime(F func, int array[], Args... args) {
using namespace chrono;
auto t1 = high_resolution_clock::now();
func(array, args...);
auto t2 = high_resolution_clock::now();
return to_string(duration_cast<milliseconds>(t2 - t1).count()) + "ms\n";
}
int main()
{
int i;
//int size;
int random_once[10000]; //maximum array size
srand(time(0));
//asking user for the size of the list
cout << "How big would you like the list to be?" << "\n\n";
cout << "\t Enter any of the following: 100, 500, 1000, 2000, 5000, 8000, or 10000" << "\n";
cin >> SIZE;
//for loop to generate numbers and nested for loop to handle duplicates
for (int i=0; i<SIZE; i++)
{
random_once[i]=rand() % 20000; //generating a random number between 1 - 20000
// generate unique random number only once so no duplicates
for(int j=0; j<i; j++) if (random_once[j]==random_once[i]) i--;
}//end generating for loop
cout<< " " << i << "\n\n\n ";
for(i=0; i<SIZE; i++) cout << " " << random_once[i] << "\t"; //outputting array to console
cout << "insertSort(): " << callTime(&insertSort, random_once);
return 0;
} //end main
//insert sort algorithm
void insertSort(int input[]) {
int i, j, temp;
for (i = 0; i < SIZE; i++) {
temp = input[i];
for (j = i; j > 0 && temp < input[j - 1]; j--) {
input[j] = input[j - 1];
}
input[j] = temp;
}
}
I am not sure if I get you right, but what you can do is to measure time before and after call of sorting functions. For time measurement C++ has various tools for example std::high_resolution_clock which I am using in code bellow. You can then observe how sorting algorithms behave on arrays of different sizes. There I wrote you template function which should be usable with every sort you plan to implement(don't forget to include chrono header):
#include <chrono>
template <typename F, typename... Args>
std::string callTime(F&& func, int array[], Args&&... args) {
using namespace std::chrono;
auto t1 = high_resolution_clock::now();
func(array, std::forward<Args>(args)...);
auto t2 = high_resolution_clock::now();
return std::to_string(duration_cast<milliseconds>(t2 - t1).count()) + "ms\n";
}
You can call it like this :
int main() {
// what you have before
cout << "insertSort(): " << callTime(insertSort, random_once);
//...
cout << "merge(): " << callTime&merge, random_once, /* other params */);
//...
return 0;
}
Note that you can change precision of duration cast:
duration_cast<microseconds>(t2 - t1).count() // now returns microseconds passed

Vector elements are not swapped in partition algorithm.

Problem is from the Elements of Programming Interviews Book (2012).
Problem 6.1 pg 53: "Write a functions that take an array A (I used vector) and an index i into A, and rearranges the elements such that all elements less than A[i] appear first, followed by elements equal to A[i], followed by elements greater than A[i]. Your algorithm should have O(1) space complexity and O(|A|) time complexity.
My code doesn't do anything to the vector.
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
void swapit(vector<T> v, int i, int j)
{
T temp;
temp = v[i];
v[i] = v[j];
v[j] = temp;
}
template <typename T>
void dutch_flag_partition(vector<T> &v, int pivotindex)
{
T pivot = v[pivotindex];
int lower = 0;
int equals = 0;
int larger = v.size() - 1;
while(equals <= larger)
{
cout << equals << " " << larger<< endl;
if(v[equals] < pivot)
{
swapit(v, lower++, equals++);
}
else if(v[equals] == pivot)
{
++equals;
}
else
{
swapit(v, equals, larger--);
}
}
}
int main()
{
int arr[] = {1,11,3,5,3,10,0,22,50,33,4,22,23,100,9};
vector<int> v (arr, arr + sizeof(arr)/sizeof(arr[0]));
dutch_flag_partition(v, 5);
for(int i = 0; i < v.size(); ++i)
{
cout << v[i] << " ";
}
cout << endl;
return 0;
}
void swapit(vector<T> v, int i, int j) { ... }
This does not modify the vector you passed in. Instead, it creates a copy for this function. You probably want to use a reference:
void swapit(vector<T> & v, int i, int j) { ... }

Array sorting, Array input, Array Output

I'm having some problems with this program. It is meant to input random numbers into an array, change its dimensions, sort them, the output the sorted array. For some reason, the array will only fill with one number (-858993460) and I cannot figure out why. Any help would be greatly appreciated.
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <cstring>
using namespace std;
void InputArray(int[][5], int, int);
void OutputArray(int[], int);
void SelectionSort(int[], int);
void CopyArray(int[][5], int, int, int[], int);
int main()
{
int sample_1[80];
int sample_2[16][5];
InputArray(sample_2, 16, 5);
CopyArray(sample_2, 16, 5, sample_1, 80);
cout << "Before sorting, contents of the array:" << endl << "----------------------" << endl;
OutputArray(sample_1, 80);
SelectionSort(sample_1, 80);
cout << "After sorting, contents of the array:" << endl << "----------------------" << endl;
OutputArray(sample_1, 80);
return 0;
}
//generate random numbers for a two dimensional array
void InputArray(int array[][5], int m, int n)
{
int i, j;
srand(time(NULL));
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
array[i][j] = rand() % 1000;
}
}
}
//display values in a one-dimensional array
void OutputArray(int array[], int number)
{
int i;
for (i = 0; i < number; i++)
{
cout << array[i] << "\t";
}
}
// selection sort of a one-dimensional array
void SelectionSort(int numbers[], int array_size)
{
int i, j, a;
for (i = 0; i < array_size; ++i) {
for (j = i + 1; j < array_size; ++j) {
if (numbers[i] > numbers[j]) {
a = numbers[i];
numbers[i] = numbers[j];
numbers[j] = a;
}
}
}
return;
}
//x and y and two dimensions of array_2d; n is the dimension of array_1d
//copy values from array_2d[][] to array_1d[]
//assume x*y equals n
void CopyArray(int array_2d[][5], int x, int y, int array_1d[], int n)
{
memcpy(array_2d, array_1d, sizeof(array_1d));
return;
}
void CopyArray(int array_2d[][5], int x, int y, int array_1d[], int n)
{
memcpy(array_2d, array_1d, sizeof(array_1d));
}
That's your problem right there. The size of the array_1d is unspecified here. The sizeof() operator does not know the size of the array that's being copied.
In fact, I'm surprised that this even compiles, although I'm too lazy to test it with gcc.
What you need to do is calculate the size of the array yourself, multiply it by sizeof(int), and use that instead of the existing sizeof() operator.

Cannot convert parameter 1 from 'int' to 'int []'

For an assignment for my programming class, I am getting this error:
Error 1 error C2664: 'binarySearch' : cannot convert parameter 1 from 'int' to 'int []' Line 34.
#include<iostream>
using namespace std;
int selectionSort(int[], int);
int binarySearch(int[], int, int);
int sorted;
int main()
{
int size;
int i;
int desirednum;
cout << "How many values do you want to enter?";
cin >> size;
int* userarray = 0;
userarray = new int[size];
for (i = 0; i < size; i++)
{
cout << "Enter a value: ";
cin >> userarray[i];
}
int sorted = selectionSort(userarray, size);//calls the selection sort function
cout << "What value are you looking for: ";//asks what value they are searching for
cin >> desirednum;
int location = binarySearch(sorted, size, desirednum);
delete[] userarray;
return 0;
}
int selectionSort(int numbers[], int size)
{
int i, j, min, minidx, temp, desirednum, sorted = 0;
cout << "What value are you looking for: ";
cin >> desirednum;
for (i = 0; i < (size - 1); i++)
{
min = numbers[i];
minidx = i;
for (j = i + 1; j < size; j++)
{
if (numbers[j] < min)
{
min = numbers[j];
minidx = j;
}
}
if (min < numbers[i])
{
temp = numbers[i];
numbers[i] = min;
numbers[minidx] = temp;
sorted++;
}
}
return sorted;
}
int binarySearch(int& user_array, int amount, int value)
{
int left, right;
int* middle;
left = 0;
right = amount - 1;
while (left <= right)
{
middle = (int*)((left + right) / 2);
if (value == user_array[middle])
{
return *middle;
}
}
}
Your signature (the declaration) is
int binarySearch(int[], int, int);
But your definition is:
int binarySearch(int& user_array, int amount, int value)
This is not the same. The user_array is simply taking an int by reference. You want to take in an array (or a pointer).
As an aside, amount is rather misleading. size would be more accurate and typical.
Here's an example of the expected syntax and usage:
void printArray(int array[], int size) {
for(int i = 0; i < size; ++i) {
std::cout << array[i];
}
}
// Usage
int array[] = {1,2,3};
printArray(array, 3);
Note that the type of the parameter is int[] and not int& (which is merely a reference to an int). You can also use int*.
I haven't looked at C++ in a bit but I can tell in your call to your binarysearch() function, you are passing in a single int and not an integer array. You are passing in the variable "sorted" into binarysearch as the first parameter. "sorted" was declared as int and was assigned the return value of the selectionsort function. selectionsort() is defined with a return type of int.
I think the main problem is you should be passing in the variable "userarray" as the first parameter to binarysearch(). Look at the name if the first parameter to binarysearch().
The value being returned from selectionsort (sorted) appears to only be a counter keeping track of how many swaps had to occur in order to perform the selection sort. If you don't need that info (I don't see any use of that variable) then you could make the selectionsort a void function.
Edit - Also (thanks to Mike), I just noticed the differences in the function declaration vs. definition.

FirstChance Exception StackOverFlow Merge Sort Shell Sort Bubble Sort

Hey guys I'm working on some sorts and am trying to implement a bubble sort, a merge sort, and a shell sort. I use an outdated technique but I was wondering if you guys could let me know why I keep getting the following error:
First-chance exception at 0x01135EF7 in sortApplication2.exe: 0xC00000FD: Stack overflow (parameters: 0x00000000, 0x00542000).
Unhandled exception at 0x01135EF7 in sortApplication2.exe: 0xC00000FD: Stack overflow (parameters: 0x00000000, 0x00542000).
I am using Visual Studio 2012 if that plays any part. My code is in three different files so I'll post each separately.
My header file:
#pragma once
class sort
{
public:
sort();
void random1(int array[]);
void random2(int array[]);
void random3(int array[]);
void bubbleSort(int array[], int length);
/*void merge(int *input, int p, int r);
void merge_sort(int *input, int p, int r);*/
void shellSort(int array[], int length);
};
My class implementation file:
#include "sort.h"
#include <time.h>
#include <iostream>
using namespace std;
sort::sort()
{}
void sort::random1(int array[])
{
// Seed the random-number generator with current time so that
// the numbers will be different every time the program runs.
for(int i = 0; i < 25; i++)
{
srand ((unsigned) time(NULL));
int n = rand(); //generates a random number
array[i] = n; //places it into the array
}
}
void sort::random2(int array[])
{
// Seed the random-number generator with current time so that
// the numbers will be different every time the program runs.
for(int i = 0; i < 10000; i++)
{
srand ((unsigned) time(NULL));
int n = rand(); //generates a random number
array[i] = n; //places it into the array
}
}
void sort::random3(int array[])
{
// Seed the random-number generator with current time so that
// the numbers will be different every time the program runs.
for(int i = 0; i < 100000; i++)
{
srand ((unsigned) time(NULL));
int n = rand(); //generates a random number
array[i] = n; //places it into the array
}
}
void sort::bubbleSort(int array[], int length)
{
//Bubble sort function
int i,j;
for(i = 0; i < 10; i++)
{
for(j = 0; j < i; j++)
{
if(array[i] > array[j])
{
int temp = array[i]; //swap
array[i] = array[j];
array[j] = temp;
}
}
}
}
/*void sort::merge(int* input, int p, int r) //the merge algorithm of the merge sort
{
int mid = (p + r) / 2;
int i1 = 0;
int i2 = p;
int i3 = mid + 1;
// Temp array
int x = r -p + 1;
int *temp;
temp = new int [x];
// Merge in sorted form the 2 arrays
while ( i2 <= mid && i3 <= r )
if ( input[i2] < input[i3] )
temp[i1++] = input[i2++];
else
temp[i1++] = input[i3++];
// Merge the remaining elements in left array
while ( i2 <= mid )
temp[i1++] = input[i2++];
// Merge the remaining elements in right array
while ( i3 <= r )
temp[i1++] = input[i3++];
// Move from temp array to master array
for ( int i = p; i <= r; i++ )
input[i] = temp[i-p];
}
void sort::merge_sort(int *input, int p, int r) //the merge sort algorithm
{
if ( p < r ) //When p and r are equal the recursion stops and the arrays are then passed to the merge function.
{
int mid = (p + r) / 2;
merge_sort(input, p, mid); //recursively calling the sort function in order to break the arrays down as far as possible
merge_sort(input, mid + 1, r);//recursively calling the sort function in order to break the arrays down as far as possible
merge(input, p, r); //merge function realigns the smaller arrays into bigger arrays until they are all one array again
}
}*/
void sort::shellSort(int array[], int length) //Shell sort algorithm
{
int gap, i, j, temp;
for( gap = length / 2; gap > 0; gap /= 2) //gap is the number of variables to skip when doing the comparisons
{
for( i = gap; i < length; i++) //This for loop sets the variable to use as the gap for the comparisons
{
for (j = i - gap; j >= 0 && array[j] > array[j + gap]; j -= gap)
{
temp = array[j]; //the array variables are swapped
array[j] = array[j + gap];
array[j + gap] = temp;
}
}
}
}
And my driver file:
#include "sort.h"
#include <iostream>
using namespace std;
int main()
{
int bubbleArray1[25]; //these are the arrays to be sorted. three for each sort. each has a length of 25, 10000, or 100000.
int bubbleArray2[10000];
int bubbleArray3[100000];
int mergeArray1[25];
int mergeArray2[10000];
int mergeArray3[100000];
int shellArray1[25];
int shellArray2[10000];
int shellArray3[100000];
sort Sorts;
Sorts.random1(bubbleArray1);
Sorts.random1(mergeArray1);
Sorts.random1(shellArray1);
Sorts.random2(bubbleArray2);
Sorts.random2(mergeArray2);
Sorts.random2(shellArray2);
Sorts.random3(bubbleArray3);
Sorts.random3(mergeArray3);
Sorts.random3(shellArray3);
cout << "BubbleSort1 is now being sorted.\n";
Sorts.bubbleSort(bubbleArray1, 25);
cout << "BubbleSort2 is now being sorted.\n";
Sorts.bubbleSort(bubbleArray2, 10000);
cout << "BubbleSort3 is now being sorted.\n";
Sorts.bubbleSort(bubbleArray3, 100000);
cout << "End bubble sorts.\n";
/*cout << "MergeSort1 is now being sorted.\n";
Sorts.merge_sort(mergeArray1, 0, 25);
cout << "MergeSort2 is now being sorted.\n";
Sorts.merge_sort(mergeArray2, 0, 10000);
cout << "MergeSort3 is now being sorted.\n";
Sorts.merge_sort(mergeArray3, 0, 100000);
cout << "End merge sorts.\n";*/
cout << "ShellSort1 is now being sorted.\n";
Sorts.shellSort(shellArray1, 25);
cout << "ShellSort1 is now being sorted.\n";
Sorts.shellSort(shellArray2, 10000);
cout << "ShellSort1 is now being sorted.\n";
Sorts.shellSort(shellArray3, 100000);
cout << "End shell sorts.\n";
cout << "Array\tElements\n";
cout << "BubbleSort1\t";
for(int i = 0; i < 25; i++)
{
cout << bubbleArray1[i] << " ";
}
cout << "\nMergeArray1\t";
for(int i = 0; i < 25; i++)
{
cout << mergeArray1[i] << " ";
}
cout << "\nShellArray1\t";
for(int i = 0; i < 25; i++)
{
cout << shellArray1[i] << " ";
}
return 0;
}
I know it's a lot of code. And there are probably many ways I could make the code better.
I would just like to know what's causing the error up above since I can't find it using my compiler.
You are allocating too much memory on the stack. Variables with 'automatic' storage class go on the stack. Allocate heap instead.
So, instead of:
int shellArray3[100000];
Do:
int* shellArray3 = new int[100000];
Or better yet, use std::vector.
If you don't want to use heap memory, you could also use the static storage class for something like this. To do that:
static int shellArray3[100000];
That will allocate one instance of the variable for the whole program rather than allocating a copy for each function entry on the stack.