I've been working on a class for an insertion sort thing that I'm playing around with. However, when I run my program, it seems to work just fine for the most part (gets to return 0; in main and then freezes). I don't know why or how it's freezing, and it's gotten me quite confused.
The only method that is called from the insertionSort object is sort, if you don't count generateNums.
Main.cpp:
#include "stdafx.h"
#include "insertionSort.h"
#include <iostream>
int main()
{
int* gotNums;
const int INT_LENGTH = 100;
//Create new insertionSort object
insertionSort insSort(INT_LENGTH); //Length: 100
std::cout << "hey";
return 0;
}
insertionSort.h:
#pragma once
class insertionSort
{
private:
int* _nums; //Sorted and unsorted nums
int _sortedBegins; //Point at which sorted items begin. This minus one is the first unsorted item
int _length;
void shiftUnsorted();
public:
insertionSort(int length);
int* getNums();
void sortNums();
void generateNums();
};
insertionSort.cpp
#include "stdafx.h"
#include "insertionSort.h"
#include <random>
#include <iostream>
//Constructor and destructors
insertionSort::insertionSort(int length)
{
_nums = new int(length + 1); //+1 to accomodate empty space between sorted & unsorted.
std::cout << "made arr ";
_sortedBegins = length + 1;
std::cout << "made sorted ";
_length = length + 1;
std::cout << "made len ";
this->generateNums();
}
/* Custom functions */
//Populate array with new numbers
void insertionSort::generateNums() {
for (int i = 0; i < _length - 1; i++) { //Don't fill the last array; it's an empty place for the sorted items.
_nums[i] = rand() % 100 + 1; //generate number between 1 and 100
}
_nums[_length] = -1; //Create buffer
}
//The main part of it all - sort the array
void insertionSort::sortNums() {
int currPos = _sortedBegins - 1; //Loop backwards through the unsorted items so that there is minimal shifting.
int currInt;
while (currPos > 0) {
currInt = _nums[currPos];
for (int i = _length; i > _sortedBegins; i++) {
if (i < currInt) { //Time to shift the sorted to the left
_nums[_sortedBegins - 1] = 0; //Shift buffer left
for (int i2 = _sortedBegins + 1; i2 <= i; i2++) { //Shift main sorted content left
_nums[i2] = _nums[i2 + 1];
}
_nums[i] = currInt;
break;
}
}
currInt--;
}
}
//Get nums from array
int* insertionSort::getNums() {
return _nums;
}
//Shift unsorted items to the left to make way for new data in sorted. NOTE: does not assign new value to sortedBegins.
void insertionSort::shiftUnsorted() {
for (int i = 0; i < _sortedBegins - 1; i++) {
_nums[i] = _nums[i + 1];
}
_nums[_sortedBegins - 1] = 0;
//And, it's hopefully shifted!
}
Anyone got an idea as to why this isn't working properly?
Thanks,
- Sam
Change:
_nums[_length] = -1; //Create buffer
to:
_nums[_length - 1] = -1; //Create buffer
Valid indexes for _nums are from 0 to length-1. Your code is writing outside the array, which causes undefined behavior.
The for loop in sortNums is also doesn't look right:
for (i = _length; i > _sortedBegins; i++) {
It makes no sense to start at _length, which is after the end of the array. And adding to it goes even farther out of the array. I haven't really analyzed the logic in that loop, so I'm not sure what the correct code is. But you need to start by making sure you stay inside the array.
But since your program doesn't currently call sortNums, it won't cause a problem now.
When shiftUnsorted does
_nums[_sortedBegins - 1] = 0;
you'll write outside the array if _sortedBegins is 0. You don't currently call this, either. When you add the call to it, make sure it can never be called when that's true, or add a check for this into the function.
This code looks suspicious to me:
_nums = new int(length + 1);
I would have expected square brackets instead of round parentheses. Because like this, you are only creating a pointer to a single int that is initialized with the value 101. But instead you wanted to create an array of 101 ints and later fill it with values. So write this:
_nums = new int[length + 1];
Related
I'll explain my code first before going into my question in more details.
The program will continue to count the next number until the nth number is generated, and then print out that number.
Here's how it works.
With a given sequence of starting numbers, for example, 0,3,6
The 1st number is 0.
The 2nd number is 3.
The 3rd number is 6.
Now, consider the last number, 6. Since that was the first
time the number had been spoken, the 4th number spoken is 0.
(if the last number has been spoken before, then, the next number
is the difference between the turn number when it was last spoken
and the turn number of the time it was most recently spoken before
then. )
since the last number, which is the 4th number (0) has been
spoken before, the most recent place where 0 appears before the last
number is turn 1. Therefore, the 5th number is 4 - 1, which is 3.
...keep counting until the nth number.
My code works fine when n is 2022, but the program stop running when n = 30,000,000
The is how I allocate memory to my arrays
int *test_case_one = new int[30000000];
Below is my entire code
#include <iostream>
#include <string>
using namespace std;
void test_cases( int Array[]);
int isfound( int table[], int current, int range);
int main()
{
int *test_case_one = new int[30000000];
test_case_one[0] = 1;
test_case_one[1] = 3;
test_case_one[2] = 2;
test_cases(test_case_one);
delete[] test_case_one;
}
void test_cases( int Array[])
{
int *table = new int[30000000];
int turn;
int last;
table[0] = Array[0];
table[1] = Array[1];
table[2] = Array[2];
table[3] = 0;
for ( int i = 4; i < 30000000; i++)
{
last = table[i -1];
turn = isfound(table, last, i);
if ( turn != -1) {
table[i] = (i-1) - turn;
}
else {
table[i] = 0;
}
}
cout<< table[29999999] << endl;
delete[] table;
}
int isfound( int table[], int last, int range)
{
for ( int j = range-1; j > 0 ; j--) {
if ( last == table[j -1]) {
return (j - 1);
}
}
return -1;
}
How can I fix this memory overload issue?
You should not build a table of the values, but a table of last rank per value, initialized to 0. That way when you get a value, you have a direct access to next value and you algo become simply linear.
If you are sure that none of the initialization values will be greater than the expected number of iterations, then everything is fine because as other values will be index differences, this will also be less than that number.
Here is a simple code for your 0-3-6 example:
#include <iostream>
int main()
{
int number;
std::cout << "Total number (>=7): ";
std::cin >> number;
if (!std::cin || number < 5) return EXIT_FAILURE;
// 3 initial values are 0, 3, 6, so 4th will be 0
int* data = new int[number];
for (int i = 0; i < number; i++) data[i] = 0;
data[0] = 1;
data[3] = 2;
int val = 6;
for (int index = 3; index <= number; index++) {
int newval = data[val] ? index - data[val] : 0;
data[val] = index;
val = newval;
// uncomment next line to see intermediary values
//printf("%d: %d\n", index + 1, val);
}
delete[] data; // always release dynamic objects...
printf("Final %d: %d\n", number, val);
return 0;
}
BTW, in modern C++ you should rarely directly allocate a raw array with new, precisely because if you do, you will be responsible for its deletion. It is much more common and easy to use standard containers, here a std::vector. (Thanks to #EtiennedeMartel for the remark).
I've tried the (somewhat questionable) convention of deleteing after usage, but that doesn't seem to work. The program is supposed to receive an input of a single integer, sort a randomly created array, and print elapsed time for sorting, yet when I leave the delete in there, the program abnormally ends without even a warning after I do the input. In other words, it crashes. However, when I comment out just the delete line, the program executes perfectly.
The MWE is measuring time for a simple Quick Sort Algorithm, and since this is a school project I cannot change the main() function and using the QuickSort class and its pointers, etc..
The only things I can change are the stuff that goes in the various functions, and although it does seem that set(double*, int) can just be integrated into the constructor, that's not a possible option here for some reason.
The objective is to define a default double* in the constructor, and then delete it and copy input_array into this->arr in set:
EDIT: I use Windows 10 and the GCC C++ Compiler from MinGw-w64. All compilations have been executed in the Windows Command Prompt.
main.cpp
#include <iostream>
#include <cstdlib> // Just for good measure, though this shouldn't be needed
#include "Sort.hpp"
bool check_quick(QuickSort *quick_sort) {
int i = 0;
while(i < (quick_sort->size) - 1) {
if (quick_sort->arr[i] > quick_sort->arr[i + 1]) break;
++i;
} if (i == (quick_sort->size) - 1) return true;
else return false;
}
int main() {
int n; cin >> n;
double *input_array = new double[n];
srand((unsigned int)time(NULL));
for (int k = 0; k < n; k++) input_array[k] = (double)((rand() % n));
QuickSort* quick_sort = new QuickSort();
quick_sort->set(input_array, n);
quick_sort->run();
if (check_quick(quick_sort)) {
cout << "QuickSort is validated" << endl << endl;
} delete quick_sort;
}
Sort.hpp
#define CLOCKS_PER_SECOND 1000
#include <iostream>
#include <ctime>
#include <iomanip> // Use to call setprecision(4)
using namespace std;
class QuickSort {
friend bool check_quick(QuickSort*); // Give access for private variables
public:
void print_time() const {
cout << "QuickSort : " << fixed << setprecision(4) << seconds
<< " sec" << endl;
// << fixed << setprecision(4) always prints to four numbers after point
}
QuickSort() {
this->arr = new double[10];
for (int i = 0; i < 10; ++i) this->arr[i - 1] = i; // Set default array
seconds = clock(); // Set current Millisecond to starting time
}
~QuickSort() {
delete this->arr; // Delete array in object of this class
}
void sorter(double *arr, int begin, int end) { // Sorting Recursive Function
// Size of array without pivot is: end - begin
int pivot = arr[end];
// PIVOT is element at end of subarray "arr[begin...end]"
int i = begin, j = end;
while (i <= j) {
while (arr[i] < pivot) i++; // Increment until arr[i] is larger than
while (arr[j] > pivot) j--; // Decrement until arr[j] is lesser than
if (i <= j) { // If the larger element precedes lesser element
swap(arr[i], arr[j]); // Call Swap function
i++; j--;
} // If i is larger than j now, i was 1 lesser than j before,
// effectively leaving no more elements to scan.
}
if (begin < j) sorter(this->arr, begin, j); // Recursive, larger part
if (end > i) sorter (this->arr, i, end); // Recursive, lesser part
}
void run() {
sorter(this->arr, 0, this->size - 1); // Call Sorter function
seconds = (double)(clock() - seconds) / (double)(CLOCKS_PER_SECOND);
// Calculate Difference of Ticks and divide by Ticks per second.
// Now, `seconds` is passed seconds with millisecond precision.
}
void set(double *arr, int size) {
this->arr = new double[size]; // Make new array of `size` size
for (int i = 0; i < size; i++) this->arr[i] = arr[i]; // Copy input_arr
for (int i = 0; i < size; i++) cout << this->arr[i] << endl; // Copy input_arr
this->size = size; // Save global `size` to object of class
}
void swap(double &p, double &q) { // Swap Function
// Ampersand precedence to change input
double x = p; // Temporary `double` saver
p = q; // p is q
q = x; // q is x, which is p
}
private:
double *arr;
int size;
double seconds;
};
In your QuickSort constructor you are writing outside the bounds of the array that you are allocating:
this->arr = new double[10];
for (int i = 0; i < 10; ++i) this->arr[i - 1] = i; // Set default array
In the first iteration i is 0 so this->arr[i - 1] writes to the element -1. This is only crashing when you call delete as if you don't the runtime doesn't notice this corruption and exits cleanly.
Presumably just changing i-1 to i will produce the desired behaviour.
The first line of QuickSort::set:
this->arr = new double[size]; // Make new array of `size` size
leaks the array allocated in QuickSort's constructor. You need to delete[] that array first, before assigning arr to point to another one:
delete[] arr;
this->arr = new double[size]; // Make new array of `size` size
If this were the real world, and not a shcool assignment, it would be much better not to use a raw pointer in this case. Rather, a std::vector<double> would be much more appropriate.
A quick look reveals that you are using delete instead of delete[]..
this line:
delete this->arr; // Delete array in object of this class
should be:
delete[] this->arr; // Delete array in object of this class
Additionally, as per the convention of delete you should also do this:
delete[] this->arr;
this->arr = nullptr; // This is important, else your are double deleting which is calling for trouble.
I am working on an assignment that requires me to simulate Langton's ant. I have dynamically allocated memory for a 2D array in the constructor of class Ant. The pointer to this array is a member of class Ant. Additionally, I have defined get functions for the rows and columns which I am using to pass these values to my array.
Ant.hpp
#ifndef ANT_HPP
#define ANT_HPP
enum Direction {UP, RIGHT, DOWN, LEFT};
class Ant
{
private:
char** board;
char spaceColor;
Direction facing;
int rows, cols, steps, stepNumber;
int startRow, startCol, tempCol, tempRow;
int lastRow, lastCol;
int thisRow, thisCol;
public:
Ant();
Ant(int, int, int, int, int);
void print();
void makeMove();
};
Ant.cpp
Ant::Ant()
{
rows = 5;
cols = 5;
steps = 5;
startRow = 0;
startCol = 0;
stepNumber = 0;
facing = LEFT;
setThisRow(5);
setThisCol(5);
setLastRow(5);
setLastCol(5);
setSpaceColor(' ');
board = new char*[rows];
for(int i = 0; i < rows; ++i){
board[i] = new char[cols];
}
for(int i = 0; i < rows; ++i){
for(int i = 0; i < rows; ++i){
board[i][j] = ' ';
}
}
board[startRow][startCol] = '*';
}
char Ant::getSpaceColor()
{
return spaceColor;
}
void Ant::makeMove()
{
if(getSpaceColor() == ' '){
board[getLastRow()][getLastCol()] = '#';
}
}
int Ant::getLastRow()
{
return lastRow;
}
int Ant::getLastCol()
{
return lastCol;
}
main.cpp
#include "Ant.hpp"
#include <iostream>
using std::cout;
using std::endl;
int main()
{
Ant myAnt;
myAnt.print();
myAnt.makeMove();
return 0;
}
Gdb has reported a segmentation fault at this line of code:
board[getLastRow()][getLastCol()] = '#';
Gdb is able to print accurate values for getLastRow() & getLastCol(), but cannot access memory for board[getLastRow()][getLastCol()].
I am not sure what I am doing wrong, any help would be greatly appreciated
Assuming board[getLastRow()][getLastCol()] translates to board[5][5], you go beyond the buffer. Your board is 0..4.
You are invoking undefined behavior by accessing array elements out of bounds. Your setLastRow(5); and
setLastCol(5); functions cause both of your getLastRow() and getLastCol() functions to return the value of 5 but since arrays are zero indexed that would imply you are accessing 6th element. So with:
board[getLastRow()][getLastCol()] = '#';
you are effectively calling:
board[5][5] = '#'; // undefined behavior because there are no 6 X 6 elements
whereas you can only have a maximum index of 4:
board[4][4] = '#'; // OK as there are 5 X 5 elements
One solution is to have your functions return lastRow - 1 and lastCol - 1 respectively.
Segmentation fault usually refers that the program is accessing an unallocated address.
board[getLastRow()][getLastCol()]
You might want to check the starting index and ending index of the arrays.
I think you might allocating the 2D array with index starting from 0
getLastRow()/Col might return the size of the row / Col
So when the index starts from 0, your last row index would be getLastRow()-1 and the same thing would apply for the Column
which yields ==> board[getLastRow()-1][getLastCol()-1]
Trying to understand the insertion sort algorithm..
My algorithm looks like this currently:
void insertionSort(int *array, int N) {
int value;
int hole;
int *array2;
for (int i = 1; i < N - 1; i++) {
value = array[i]; //next item to be inserted in array 2
hole = i;
while (hole > 0 && array[hole - 1] > value) {
array[hole] = array[hole - 1];
hole = hole - 1;
}
array[hole] = value;
}
}
My algorithm works for sorting arrays, however I now need to change it so that I build up a new sorted array (array2) one element at a time, rather than just working with the original array.
Is there a simple way to implement this given my completed algorithm?
Thanks.
You can use the following method:
int *array2 = calloc(N, sizeof(int));
for(var index = 0; index < N; index++)
{
array2[index] = array[index];
}
and after that use array2 instead of array
then just change the prototype of your function to int *insertionSort
All remaining is to return array2 at the end of task
But be aware of memory leak: https://en.wikipedia.org/wiki/Memory_leak
I'm attempting to teach myself the basics of algorithms and data structures through a free online course, and as such, I though it'd give it a first shot at merge sort. This isn't really going to be used for anything so it's pretty sloppy, but I seem to be having a problem where main is not calling the MergeSort function.
The output is 00000000, (I assume because array is never assigned anything). When I run the program through gdb the program seems to get to that line, and then completely skip over the function and go directly to the loop that prints the array.
Any thoughts? Am I missing something stupid?
#include <iostream>
using namespace std;
int *MergeSort(int array[], int sizeOf);
int main(){
int numbers[8] = {5, 4, 1, 8, 7, 2, 6, 3};
int *array = MergeSort(numbers, 8);
for (int i = 0; i < 8; i++)
cout << array[i];
return 0;
}
int *MergeSort(int array[], int sizeOf){
int *leftArr = new int[sizeOf/2]; // Build arrays to split in half
int *rightArr = new int[sizeOf/2];
if (sizeOf < 2){ // Base case to end recursion
return array;
}
else{
for (int i = 0; i < (sizeOf/2); i++){ // Left gets first half
leftArr[i] = array[i];
}
int j = (sizeOf/2) - 1; // Set point to start building 2nd
for (int i = sizeOf; i >= (sizeOf/2); i--){
rightArr[j] = array[i]; // Build other half of array
j--;
}
leftArr = MergeSort(leftArr, sizeOf/2); // Call Recursive functions
rightArr = MergeSort(rightArr, sizeOf/2);
}
static int *newArray = new int[sizeOf]; // Sorted array to Build
int k = 0; // Iterators to build sorted func
int m = 0;
int p = 0;
while (p < sizeOf){
if (leftArr[k] < rightArr[m]){ // Left Arr's current value is less
newArray[p] = leftArr[k]; // right arr's current calue
k++;
}
else if (leftArr[k] >= rightArr[m]){
newArray[p] = rightArr[k];
m++;
}
p++;
}
//for (int i = 0; i < 8; i++)
// cout << newArray[i] << endl;
return newArray; // Return address to new array
}
There is a fundamental design issue in your MergeSort():
your algorithm is recursive (that's perfect)
unfortunately it returns newArraywhich is static. This means that all invocations use the same instance of the same static variable (and overwrite the one returned by the recursive call).
You need to solve this by making newArray non static. And at the end of the function, you need to delete[] the arrays returned by recursive calls in order to avoid memory leakage.