I am writing a sorting program that needs to take a an array, fill it with 1000 random numbers, then copy the array into a second array. After that the program is supposed to use the selectionSort function and the insertSort function .
But when I use the functions I am supposed to keep track of all the swaps and key comparisons. I have figured out how to do that for the insertSort. I cannot figure out how to do this for the selectionSort
Here is my code:
template <class elemType>
void selectionSort(elemType list[], int length)
{
int loc, minIndex;
int swaps =0;
for (loc = 0; loc < length; loc++)
{
minIndex = minLocation(list, loc, length - 1);
swap(list, loc, minIndex);
}
cout<<"swaps = "<<swaps<<endl;
} //end selectionSort
template <class elemType>
void swap(elemType list[], int first, int second)
{
elemType temp;
temp = list[first];
list[first] = list[second];
list[second] = temp;
} //end swap
template <class elemType>
int minLocation(elemType list[], int first, int last)
{
int loc, minIndex;
minIndex = first;
for (loc = first + 1; loc <= last; loc++)
{ if (list[loc] < list[minIndex])
minIndex = loc;
}
return minIndex;
} //end minLocation
template <class elemType>
void insertionSort(elemType list[], int length)
{
int swaps = 0;
int comp = 0;
for (int firstOutOfOrder = 1; firstOutOfOrder < length;
firstOutOfOrder++)
if (list[firstOutOfOrder] < list[firstOutOfOrder - 1])
{
elemType temp = list[firstOutOfOrder];
int location = firstOutOfOrder;
do
{
list[location] = list[location - 1];
location--;
comp +=1;
} while(location > 0 && list[location - 1] > temp);
list[location] = temp;
swaps +=1;
}
cout<<"swaps = "<<swaps<<endl;
cout<<"comps = "<<comp<<endl;
} //end insertionSort
#include<iostream>
#include <ctime>
#include <cstdlib>
#include "searchSortAlgorithms.h"
using namespace std;
int main (){
//generate a new random set each time
srand(time(0));
int a[1000] = {0};
int b[1000] = {0};
for(int i= 0; i<1000; i++)
{
a[i] = rand()% 1000;
b[i] = a[i];
}
insertionSort(a, 1000);
selectionSort(b, 1000);
return 0;
}
The swaps and comparisons print out for the inertionSort, but I am unfamiliar with how I would get it to work with the selectionSort since the sort algorithm calls other functions in a for loop.
Any input would be appreciated it.
Actually, your selection sort has a fixed number of comparations (length * (length-1) / 2) and swaps (length).
If you want to count them anyway,
// Count variables can be defined in main(), and passed through
// to swap(), minLocation().
template <class elemType>
void swap(elemType list[], int first, int second)
{
// Count swap here
}
template <class elemType>
int minLocation(elemType list[], int first, int last)
{
..
for (loc = first + 1; loc <= last; loc++)
{
// Count comparation here
}
..
}
By the way, your counting of comparations in insertion sort is not complete either.
for (int firstOutOfOrder = 1; firstOutOfOrder < length; firstOutOfOrder++)
{
// You miss the count here.
if (list[firstOutOfOrder] < list[firstOutOfOrder - 1])
Related
I'm working with Template Functions and am looking to create one that sorts both ints and strings. I have managed to get it working with ints but having trouble with strings.
Here is my code so far.
#include <iostream>
#include <string>
using namespace std;
template <class T>
void print(T arr[], int n);
template <class T>
void swap(T arr[], int i, int j);
template <class T>
T getSmallest(T arr[], int start, int end);
template <class T>
void selectionSort(T arr[], int n);
int main()
{
int n = 10;
int iarr[] = { 3,5,9,2,1,7,8,4,0,6 };
selectionSort<int>(iarr, n);
print<int>(iarr, n);
cout << endl;
string sarr[] = { "skunk", "hedgehog", "aardvark", "zebra", "rat", "cat", "hippopotamus", "hamster", "manatee", "red panda" };
selectionSort<string>(sarr, n);
print<string>(sarr, n);
cout << endl;
return 0;
}
// PRE: length of arr = n
// PARAM: arr = array of integers of length n
// POST: prints arr[0:n]
template <class T>
void print(T arr[], int n) {
for (int i = 0; i < n; i++) {
cout << arr[i] << endl;
}
}
// PRE: i, j < length of arr
// PARAM: arr = array of integers of length n, i and j are indexes
// POST: swaps arr[i] with arr[j]
template <class T>
void swap(T arr[], int i, int j) {
T temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// PRE: 0 <= start < end <= length of arr
// PARAM: arr = array of integers
// start = start index of sub-array
// end = end index of sub-array + 1
// POST: returns index of smallest value in arr{start:end}
template <class T>
T getSmallest(T arr[], int start, int end) {
T smallest = start;
for (int i = start + 1; i < end; ++i) {
if (arr[i] < arr[smallest]) {
smallest = i;
}
}
return smallest;
}
// PRE: length of arr = n
// PARAM: arr = array of integers of length n
// POST: sorts arr in ascending order
template <class T>
void selectionSort(T arr[], int n) {
for (int i = 0; i < n - 1; ++i) {
int smallest = getSmallest(arr, i, n);
swap(arr, i, smallest);
}
}
I know I need to find some way to make "smallest" somehow able to work for strings. But simply turning it from int to template T isn't working. Any suggestions?
You almost have it.
The only thing off is that getSmallest() returns an index regardless of what T is. So that part should not be templated.
template <class T>
int getSmallest(T arr[], int start, int end) {
int smallest = start;
This function
template <class T>
T getSmallest(T arr[], int start, int end) {
T smallest = start;
for (int i = start + 1; i < end; ++i) {
if (arr[i] < arr[smallest]) {
smallest = i;
}
}
return smallest;
}
has an invalid return type. For an array of objects of the type std::string it will have the return type std::string.
It should look like
template <class T>
int getSmallest(T arr[], int start, int end) {
int smallest = start;
for (int i = start + 1; i < end; ++i) {
if (arr[i] < arr[smallest]) {
smallest = i;
}
}
return smallest;
}
Do not forget to change also the function template declaration
template <class T>
int getSmallest(T arr[], int start, int end)
You changed to many int to T.
template <class T>
T getSmallest(T arr[], int start, int end) {
T smallest = start;
for (int i = start + 1; i < end; ++i) {
if (arr[i] < arr[smallest]) {
smallest = i;
}
}
return smallest;
}
If you use int for the index then smallest should be int and the return type should be int, not T. Actually I suggest to use size_t for indices (unless you want to pass iterators):
template <class T>
size_t getSmallest(T arr[], size_t start, size_t end) {
size_t smallest = start;
for (size_t i = start + 1; i < end; ++i) {
if (arr[i] < arr[smallest]) {
smallest = i;
}
}
return smallest;
}
This question already has answers here:
How do I use arrays in C++?
(5 answers)
Why aren't variable-length arrays part of the C++ standard?
(10 answers)
Closed 1 year ago.
I am trying to make a program that reads files with numbers and sort the numbers with different algorithms and there is multiple files that are going to be read and each file has a different amount of integers. so what i need to do is read those integers and cast them into a array.
but for some reason in c++ you cant have a array with an undefined size so what is a solution that i can use? And i can't use vectors (school project)
Here is my program
#ifndef SORT_H
#define SORT_H
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
// =============================================================================
// FILE READER
// =============================================================================
void fileReader(string fileName, int arr[]){
ifstream myfile(fileName);
int pos = 0;
string number;
if(myfile.is_open()){
while (getline(myfile, number))
{
arr[pos] = stoi(number);
pos++;
}
}
}
// =============================================================================
// SWAPER
// =============================================================================
void swap(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
// =============================================================================
// QUICKSORT
// =============================================================================
int partition(int arr[], int beg, int end){
int pivot = arr[end];
int index = beg - 1;
for(int j = beg; j < end; j++){
if(arr[j] <= pivot){
index++;
swap(&arr[index], &arr[j]);
}
}
swap(&arr[index+1], &arr[end]);
return (index+1);
}
void quicksortAlgo(int arr[], int beg, int end){
if(beg < end){
int pi = partition(arr, beg, end);
quicksortAlgo(arr, beg, pi-1);
quicksortAlgo(arr, pi+1, end);
}
}
template <typename T>
void quicksort(T arr[], int n)
{
quicksortAlgo(arr, 0, n-1);
for(int x = 0; x < n; x++)
cout << arr[x] << endl;
}
// =============================================================================
// HEAPSORT
// =============================================================================
void heapify(int arr[], int n, int i){
int max = i;
int left = 2*i + 1; // Left side
int right = 2*i + 2; // Right side
cout << "max: " << arr[max] << endl;
// if there is a left child for root and if is
// bigger then root
if(left < n && arr[max] < arr[left]){
max = left;
}
// If there is a right child of root and if is
// bigger then root
if(right < n && arr[max] < arr[right]){
max = right;
}
if(max != i){
swap(&arr[i], &arr[max]);
heapify(arr, n, max);
}
}
void heapsortAlgo(int arr[], int n){
for (int i = n/2 - 1; i >= 0; i--){
heapify(arr, n, i);
}
for (int i = n-1; i >= 0; i--){
swap(&arr[0], &arr[i]);
heapify(arr, i, 0);
}
}
template <typename T>
void heapsort(T arr[], int n)
{
heapsortAlgo(arr, n);
for (int i = 0; i < n; i++){
cout << arr[i] << " ";
}
}
// =============================================================================
// INTSERTIONSORT
// =============================================================================
template <typename T>
void insertionsort(T arr[], int n)
{
int holePostion;
int valueToInsert;
for (int i = 1; i < n; i++){
valueToInsert = arr[i];
holePostion = i;
while(holePostion > 0 && arr[holePostion-1] > valueToInsert){
arr[holePostion] = arr[holePostion - 1];
holePostion = holePostion - 1;
}
arr[holePostion] = valueToInsert;
}
}
int main(){
string filedest;
string arrSize;
cout << "enter file destenation: ";
cin >> filedest;
int arr[];
int n = sizeof(arr) / sizeof(arr[0]);
fileReader(filedest, arr);
quicksort(arr, n);
return 0;
}
#endif
As #MikeCAT mentioned, you can use std::vector<T>.
You can add push elements at the back of the vector by std::vector<T>::push_back().
Alternatively, you can also resize the vector array by using std::vector<T>::resize() and then add elements at a specific location similar to what you are doing in your fileReader() function. You can also insert elements at a specific location by calling std::vector<T>::insert()
.
Do have a look at the time complexities if you have a time constraint in your programming task.
I'm trying to create a program merge-sort on an array of int butI keep having troubles running this merge sort, it gives me a segment fault but I couldn't find anything wrong with it. In void mergesort when I put first <= last then the segment fault appears if not, then 5 5 5 5 is being print.
#include <iostream>
using namespace std;
void merge(int *arr, int size, int first, int middle, int last)
{
int temp[size];
for(int i = first; i<=last; i++)
{
temp[i] = arr[i];
}
int i=first, j=middle+1, k=0;
while(i<=middle && j<=last)
{
if(temp[i] <= temp[j])
{
arr[k] = temp[i];
i++;
}
else
{
arr[k]=temp[i];
j++;
}
k++;
}
while(i<=middle)
{
arr[k]=temp[i];
k++;
i++;
}
}
void mergesort(int *arr, int size, int first, int last)
{
if(first<last)
{
int middle = ( first + last )/2;
mergesort(arr,size,first,middle);
mergesort(arr,size,middle+1,last);
merge(arr,size,first,middle,last);
}
}
int main()
{
cout <<"Him";
const int size = 10;
int numbers [] = {5,10,1,6,2,9,3,8,7,4};
mergesort(numbers,size,0,9);
for( int i= 0; i<size; ++i)
{
cout << numbers[i] << " ";
}
return 0;
}
There are (at least) two bugs. This:
else
{
arr[k]=temp[i];
j++;
}
should be this:
else
{
arr[k]=temp[j];
j++;
}
and this:
int i=first, j=middle+1, k=0;
should be this:
int i=first, j=middle+1, k=first;
In general, you ought to learn to step through the code, at least by putting diagnostic output statements here and there. Once you have the hang of that you can move up to a good debugger.
The standard library already implements a function that merges correctly: std::inplace_merge. Implementation adapted from this more general post
void mergesort(int * first, int * last)
{
std::ptrdiff_t N = std::distance(first, last);
if (N <= 1) return;
int * middle = std::next(first, N / 2);
mergesort(first, middle);
mergesort(middle, last);
std::inplace_merge(first, middle, last);
}
int main()
{
cout <<"Him";
const int size = 10;
int numbers [] = {5,10,1,6,2,9,3,8,7,4};
mergesort(numbers, numbers+size);
for( int i= 0; i<size; ++i)
{
cout << numbers[i] << " ";
}
return 0;
}
Suggestion 1:
Instead of that line:
int temp[size];
If you need a dynamic size array use:
int temp = new int[size];
Then once you are done with it
delete[] temp;
Edit: As Neil suggested using std::vector is may be more useful than arrays in such situations (if you are allowed to use it).
Your code has 3 bugs, Also you can reduce your code length too if required.
void merge(int *arr, int size, int first, int middle, int last)
{
int temp[size];
for(int i = first; i<=last; i++)
temp[i] = arr[i];
int i=first, j=middle+1, k=first; // 1st Change, Set k to first instead of 0
while(i<=middle && j<=last)
{
if(temp[i] <= temp[j])
arr[k++] = temp[i++];
else
arr[k++]=temp[j++]; // 2nd Change, use j instead of i
}
while(i<=middle)
arr[k++]=temp[i++];
while(j<=last) // 3rd Change you missed this case
arr[k++]=temp[j++];
}
Live Code
http://imgur.com/TnUACAc
This is the link that shows the result.
And this result is how my result of C++ must be like
As this result shows, there are Bubble sort, Selection Sort, and Insertion Sort,
and every process of each sort is shown to the black screen.
For example, (Bubble Sort)
20 10 40 30
20 10 30 40
10 20 30 40.
I have to use void displayPtrArray to show like that.
#include <iostream>
#include <string>
#include <array>
#include <iomanip>
using namespace std;
void reset(int array[], const int size);
void displayIntArray();
void displayPtrArray(const int array[], int size);
void BubbleSort(int array[], int size);
void SelectionSort(int array[], int size);
void InsertionSort(int a[], int size);
const int RR = 4;
int main()
{
int arr[RR];
reset(arr, RR);
}
void reset(int array[], const int size)
{
cout << "The originial array has been reset to:" << endl;
int array[RR] = { 20, 40, 10, 30 };
for (int n = 0; n < size; n++)
{
cout << setw(5) << array[n];
}
cout << endl << endl;
}
void displayPtrArray(const int array[], int size)
{
}
void displayIntArray()
{
}
void BubbleSort(int array[], int size)
{
bool swap;
int temp;
do
{
swap = false;
for (int count = 0; count < (size - 1); count++)
{
if (array[count] > array[count + 1])
{
temp = array[count];
array[count] = array[count + 1];
array[count + 1] = temp;
swap = true;
}
}
} while (swap);
}
void selectionSort(int array[], int size)
{
int startScan, minIndex, minValue;
for (startScan = 0; startScan < (size - 1); startScan++)
{
minIndex = startScan;
minValue = array[startScan];
for (int index = startScan + 1; index < size; index++)
{
if (array[index] < minValue)
{
minValue = array[index];
minIndex = index;
}
}
array[minIndex] = array[startScan];
array[startScan] = minValue;
}
}
void InsertionSort(int a[], int size)
{
for (int i = 1; i<size; i++)
{
int j;
int current = a[i];
for (j = i - 1; j >= 0 && a[j]> current; j--)
{
a[j + 1] = a[j];
}
a[j + 1] = current;
}
}
I use the function for every sort, but if that is wrong please tell me.
And teach me how to show the process of each sort with
void displayPtrArray
I really don't know..... T_T...........
PLEASE HELP !!
You already have the exact code you need for displayPtrArray! The for loop defined in reset should do it.
Looking at the expected output, the array gets displayed every time there's a change to it. For bubble sort, the array changes when you do your swap (at the end of the if statement), so you want to add your call to displayPtrArray in the line after swap = true.
For selection sort, the array changes at the end of your outer for loop, so you should add the call to displayPtrArray in the line after array[startScan] = minValue;.
For insertion sort, the array changes at every iteration of the inner for loop and also in the last line of the outer for loop, so you'll probably have to call displayPtrArray in both of those places.
Note: just in case you aren't familiar with the syntax, you call the function like this: displayPtrArray(array, size); where array is the name of your array variable (the name is array in bubble and selection sorts; it's a in insertion sort) and size is the size of the array (named consistently in all three of your sorting functions).
Actually, viewing the process of the sorting is rather simple. You just have to output during the sorting process. You don't need to call another function for that. Try something like this
void BubbleSort(int array[], int size)
{
bool swap;
int temp;
do
{
swap = false;
for (int count = 0; count < (size); count++)
{
if (array[count] > array[count + 1])
{
temp = array[count];
array[count] = array[count + 1];
array[count + 1] = temp;
swap = true;
}
cout << "\nThe array is ";
for ( int i = 0; i < ( size - 1 ); i++ )
cout << array[i] << "\t"; // Look here
cout << "\nThe value of temp is " << temp << endl; // and here
}
} while (swap);
}
I posted last night about an array class, and now I'm having trouble with a sorting class. About half of the functions are defined, either by the professor or by the algorithms he gave us, but a lot of the definitions are confusing me. I'm not sure what makes them any different from the ones above it.
#ifndef SORTS_H
#define SORTS_H
#include <iostream>
#include <string>
#include "Array.h"
using namespace std;
template <class T>
void insertionSort(Array<T> &a);
template <class T>
void selectionSort(Array<T> &a);
template <class T>
void selectionSort(T a[], int n);
template <class T>
void mergesort(T *input, int size);
template <class T>
void mergesort(T *input, int left, int right, T *scratch);
template <class T>
T less(T x, T y);
template <class T>
void mergesort(Array<T> &input, int left, int right, Array<T>&scratch);
template <class T>
void mergesort(Array<T> & input);
Array<int> & random(int n);
template <class T>
void selectionSort(T a[], int n) {
int i, j, tmp;
int min_idx = 0;
for (size_t i = 0; i < n-1; i++) {
min_idx = i;
for (size_t j = i+1; j < n; j++) {
if (a[j] < a[min_idx]) {
min_idx = j;
}
tmp = a[i];
a[i] = a[min_idx];
a[min_idx] = tmp;
}
}
}
template <class T>
void selectionSort(Array<T> &a) {
int tmp;
int min_idx = 0;
for (int i = 0; i < a.getSize() - 1; i++) {
min_idx = i;
for (int j = i + 1; j < a.getSize(); j++) {
if (a[j] < a[min_idx]) {
min_idx = j;
}
tmp = a[i];
a[i] = a[min_idx];
a[min_idx] = tmp;
}
}
}
template <class T>
void insertionSort(Array<T> &a) {
// put your code here
}
template <class T>
bool sorted(Array<T> a) {
for (int i = 1; i < a.getSize(); i++)
if (a[i - 1] > a[i]) return false;
return true;
}
Array<int> & random(int n) {
Array<int> *tmp = new Array<int>(n);
for (int i = 0; i < n; i++)
(*tmp)[i] = rand() % 1000;
return *tmp;
}
template <class T>
T less(T x, T y) {
if (x < y) {
return x;
}
else {
return y;
}
}
template <class T>
void mergesort(T *input, int left, int right, T *scratch) {
if (right == left + 1) {
return;
}
else {
int i = 0;
int length = right - left;
int midpoint_distance = length / 2;
int l = left, r = left + midpoint_distance;
mergesort(input, left, left + midpoint_distance, scratch);
mergesort(input, left + midpoint_distance, right, scratch);
/* merge the arrays together using scratch for temporary storage */
for (i = 0; i < length; i++) {
/* Check to see if any elements remain in the left array; if so,
* we check if there are any elements left in the right array; if
* so, we compare them. Otherwise, we know that the merge must
* use take the element from the left array */
if (l < left + midpoint_distance &&
(r == right || min(input[l], input[r]) == input[l])) {
scratch[i] = input[l];
l++;
}
else {
scratch[i] = input[r];
r++;
}
}
/* Copy the sorted subarray back to the input */
for (i = left; i < right; i++) {
input[i] = scratch[i - left];
}
}
}
template <class T>
void mergesort(T *input, int size) {
int *scratch = new int[size];
mergesort(input, 0, size, scratch);
delete [] scratch;
}
template <class T>
void mergesort(Array<T> &input, int left, int right, Array<T>&scratch) {
if (right == left + 1) {
return;
}
else {
int i = 0;
int length = right - left;
int midpoint_distance = length / 2;
int l = left, r = left + midpoint_distance;
mergesort(input, left, left + midpoint_distance, scratch);
mergesort(input, left + midpoint_distance, right, scratch);
/* merge the arrays together using scratch for temporary storage */
for (i = 0; i < length; i++) {
/* Check to see if any elements remain in the left array; if so,
* we check if there are any elements left in the right array; if
* so, we compare them. Otherwise, we know that the merge must
* use take the element from the left array */
if (l < left + midpoint_distance &&
(r == right || min(input[l], input[r]) == input[l])) {
scratch[i] = input[l];
l++;
}
else {
scratch[i] = input[r];
r++;
}
}
/* Copy the sorted subarray back to the input */
for (i = left; i < right; i++) {
input[i] = scratch[i - left];
}
}
}
template <class T>
void mergesort(Array<T> &input) {
// put your code here
}
#endif
I also noticed that there is a void insertionSort(Array<T> &a); function, but the algorithm I was given is:
void insertionSort(int a[], int n){
int tmp;
int i, j;
for (i = 1; i < n; i++) {
tmp = a[i];
for (j = i - 1; j >= 0; j--)
if (a[j] > tmp) a[j + 1] = a[j];
else break;
a[j + 1] = tmp;
}
}
Am I supposed to implement this the same way, just replacing int a[] with, say... &arr? I'm guessing since this includes array.h and the array class has T * arr;, I should be pointing to the address of that array? Would this also work for each definition that has the address operator in its parameter?
The difference is one, as you say, takes a typical int array a[], but how would you know the size? So this version requires the user to send it to the function with n as the number of elements. In your Array class you provide a size so there's no need for it. In general you're providing overloads for multiple situations.
I'm not sure what you mean by replacing int a[] w/ &arr, the signature is there, use what was given to you unless you're supposed to change it.
If you go back to your question about the Array class you can see an answer which uses the reference just as you would normally, i.e,
template <class T>
Array<T>::Array(const Array &other) : size(other.size), arr(new T[size])
{ // ^^^^^^
for (int i = 0; i < size; ++i)
arr[i] = other.arr[i];
} // ^^^^^
now apply it to this situation.
Also,
template <class T>
void selectionSort(Array<T> &a) {
// I'm not sure I understand what this is supposed to do that's different from the above selectionSort.
// I know that & is the reference operator, so should I just return whatever &a is?
}
You won't be returning anything here considering void as the return and the use of the reference. You pass by reference as opposed to by value so that what you do in the function is persistent. You could choose to pass back the sorted array and not use a reference but I'm fairly certain it'd be slower overall considering the assignment and copy. That's why the example from your other question is using const Array &other. It prevents the entire array, which may be large, from being copied and sent to the function as well as being changed.