So I have a C++ lab that requires me to print out an array, remove some digits, and then insert some digits. I've managed to remove the correct digits and then insert the digits at the end but I need to sort the array into ascending order, Ex:1,2,3,4. I thought this would be the easy part but it is giving me more trouble than I thought. I tried using a for loop with nested if loops that would work for a normal array but I guess involving pointers in the mix has stumped me. The current code runs and does everything but sort. Any hints or help is appreciated. Code and output is posted below. This is an image of the assignment description
#include <iostream>
using namespace std;
class Array //The array class
{
private:
//Data members capacity, size, arr (a pointer that points to the first element of the array in the heap)v and two functions to move integers in the array.
int capacity{};
int size{};
int* arr{};
void moveTowardFront(int index);
void moveTowardEnd(int index);
public:
Array(int capacity);//parameter
~Array();//destructor
//two member function declarations
void insert(int num);
void print() const;
void remove(int num);
};
//insert method
void Array::insert(int num)
{
{
//if size is 0, then move number taken from insert call into the first element of the array and increment size before returning
if (size == 0)
{
arr[0] = num;
size++;
return;
}
int index = 0;
while (&num < &arr[index] && index < size) //while the address of the number taken from insert function call is less than the address of the element [index] in the arr array
//and the index is less than the size of the array
{
index++; //then we increment the index
}
moveTowardEnd(index); //move value of element toward the end
//after the while loop we move the value of the number taken from main insert call into the arr element [index] after it has been incremented so we don't overwrite values
arr[index] = num;
size++;
//then we increment the size of the array because a new value has been inserted
}
}
// Delete member function
void Array::remove(int num)
{
int index = 0; //start index at 0
//while number from main is not equal to the array element of index and the index is smaller than the size, we increment the index
while (num != arr[index] && index < size)
{
index++;
}
//if index is equal to the size then output the number from main and say it isn't on the list so no removal
if (index == size)
{
cout << num << " is not in the list. ";
cout << "No removal." << endl;
return;
}
//move toward front function call on index value and post-increment. Then post-decrement size
moveTowardFront(index++);
size--;
}
//print method
void Array::print() const
{
//rearrange the digits in ascending order
for (int i = 0; i < size; i++)
{
//print out values based on value of size taken from insert method
cout << *(arr+i) << " "; //arr points to first element in heap and then moves over by i to the next element for each iteration
}
}
// Helper function to move the elements of array towards end
void Array::moveTowardEnd(int index)
{
int* temp = &arr[index];
int* temp2 = &arr[size-1];
arr[index] = *temp2;
arr[size] = *temp;
return;
}
// Helper function to move the elements of array towards front
void Array::moveTowardFront(int index)
{
int* temp = &arr[index];
int* temp2 = &arr[size-1];
arr[index] = *temp2;
arr[size] = *temp;
return;
}
//Destructor to clean up by deleting the space allocated
Array::~Array()
{
delete[]arr;
}
//Parameter constructor to allocate space
Array::Array(int cap)
:capacity(cap)
{
//move space allocated by array with capacity being taken from main into the arr pointer so pointer can point to first element in heap
arr = { new int[capacity] {} };//allocating memory with the new operator
size = 0;//initialize size to 0
}
int main()
{
// Declaration of any array of capacity 20
Array array(20);
// Inserting some elements and printing array
array.insert(15);
array.insert(13);
array.insert(10);
array.insert(14);
array.insert(11);
array.insert(17);
array.insert(14);
cout << "Printing array after insertions: " << endl;
array.print();
cout << endl;
// Removing two elements and printing array
array.remove(13);
array.remove(11);
cout << "Printing array after removals: " << endl;
array.print();
cout << endl;
// Inserting two more elements and printing array
array.insert(8);
array.insert(22);
cout << "Printing array after more insertion" << endl;
array.print();
cout << endl;
// Try to remove an element, which is not in the array
array.remove(31);
return 0;
}
There are many ways to sort an array. Commonly used is the algorithm known as quicksort: https://en.wikipedia.org/wiki/Quicksort
Psuedo-code taken from the wikipedia page:
algorithm quicksort(A, lo, hi) is
// first we check if the lo and hi
// are natural numbers (without this check, you
// will get an overflow error because, at some point
// the program will access something like A[-1]
// which does not exists !
if lo >= 0 && hi >= 0 then
// if the indexes are in correct order, continue
if lo < hi then
// we find the index of the pivot and...
p := partition(A, lo, hi)
// ...apply quicksort for the left side and the
// right side of the array
quicksort(A, lo, p - 1)
quicksort(A, p + 1, hi)
algorithm partition(A, lo, hi) is
// we set the pivot value to the
// final value of the array
pivot := A[hi]
// we set the pivotIndex (i) to
// the start of the array
// ! NOTICE that A[i] != pivot
// aka. A[pivotIndex] != pivotValue
i := lo - 1
// we traverse the array from the start
// to the end (inclusive) aka. we traverse
// the array in this interval: [lo, hi]
for j := lo to hi do
// if the current element is
// less than the value of the pivot
// (or equal to it), then increment the i
// and swap it with the element at i (pivotIndex)
// ! NOTICE that j is automatically incremented
if A[j] <= pivot then
i := i + 1
swap A[i] with A[j]
return i
You would have to translate the pseudo-code to C++ yourself. They appear to be using the name algorithm to denote a function definition, and the := operator to do assignment, but otherwise it's not terribly different from C++ syntax. They have written in one place swap A[i] with A[j], which would for you probably look more like:
int temp = A[i];
A[i] = A[j];
A[j] = temp;
Related
I intend to create a recursive merge sort function that returns a pointer to the sorted array. Below is my implementation of the program.
The output produced by the code mostly consists of garbage memory locations. Since it is a recursive function, I'm having trouble debugging it. What scares me is whether I have understood pointers, arrays and their interconversion incorrectly. It would be really helpful if someone could take a look at the code and tell me my mistake.
Function that prints an array given a pointer to its first element
void printArr(int *arr, int n){
int *ptr = arr;
for(int i = 0; i < n; i++){
cout << *ptr << " ";
ptr++;
}
cout << endl;
}
Merge Sort function
Here p is the pointer to the given array, n is the length of the array. l and r are the indices of the first and last element of the array respectively.
// returns pointer to the sorted array
int* mergeSort(int *p, int n, int l, int r){
if(l >= r){
return &p[l];
}
int mid = l + (r-l)/2;
int *leftArray = mergeSort(p, n, l, mid);
int *rightArray = mergeSort(p, n, mid+1, r);
int n1 = mid - l + 1;
int n2 = r - mid;
int sortedArray[n1+n2];
int *ptr = sortedArray; // pointer to the sorted array
int p1 = 0; // left array index pointer
int p2 = 0; // right array index pointer
int idx = 0; // sorted array index pointer
int flag = 0; /* flag = 1 => all elements of left array have been placed into the sorted array ; flag = 2 => all elements of right array have been placed into the sorted array */
// putting elements into the sorted array
for(int i = 0; i < n1+n2; i++){
if(p1 == n1){
flag = 1;
break;
}
if(p2 == n2){
flag = 2;
break;
}
if(*(leftArray+i) > *(rightArray+i)){
sortedArray[i] = *(leftArray+p1);
p1++;
idx++;
}
else{
sortedArray[i] = *(rightArray+p2);
p2++;
idx++;
}
}
if(flag == 1){
// put remaining elements of right array into the sorted array
for(int i = idx; i < n1+n2; i++){
sortedArray[i] = *(rightArray+p2);
p2++;
}
}
if(flag == 2){
// put remaining elements of left array into the sorted array
for(int i = idx; i < n1+n2; i++){
sortedArray[i] = *(leftArray+p1);
p1++;
}
}
// return the sorted array
return ptr;
}
Main function
int main(){
int arr[] = {7,2,1,5};
int n = sizeof(arr)/sizeof(int);
int *p = arr;
cout << "Original array: ";
printArr(arr, n);
int *f = mergeSort(arr, n, 0, 3);
cout << "New array: ";
printArr(f, n);
}
Your code have returned the local array's address, which is invalidated after function returned. Then gabarage data is printed:
int sortedArray[n1+n2];
int *ptr = sortedArray; // pointer to the sorted array
Change into
int *ptr = new int[n1 + n2];
auto sortedArray = ptr;
Then we get a non-garbage value, but we hit memory leak and it's hard to deal with memory deallocation since the retuned pointer may point to the array p under certain boundary conditions.
So return pointer is not a good design, and it just wastes the API call to allocate memory and deallocate memory. It's better to split the function into two: the first one allocates a temporary buffer, and the second one handles sorting with the buffer as a parameter and calls itself with a recursive. Or just sort in place, totally avoid the temporary buffer.
I'm trying out "code golf" type problems to prepare for interviews. At the moment I'm trying to do the one where you move the odd elements of an array to the back (without necessarily preserving the order). I've looked over my logic many times and can't think of any case that could cause an infinite loop. However, I'm getting a Timeout when I try to run it. I've commented out my thought process for you to see.
#include <iostream>
void int_swap (int *pi1, int *pi2)
{
int temp = *pi1;
*pi1 = *pi2;
*pi2 = temp;
}
void odds_to_back (int *arr, size_t n)
{
int * end = arr + n; // get pointer to 1 off the end of the array
if (arr == end) return; // handle case of empty array
--end; // move pointer to last element of the array
while (arr != end)
{
if (*arr % 2) // if first pointer is odd
{
if (!(*end % 2)) // if second pointer is even
{
int_swap(arr, end); // swap first and second
++arr; // increment first
}
else // second pointer is odd
{
while ((*end % 2) && arr != end) --end; // move second pointer towards first until second pointer is even or hits the first
}
}
else // if first is even
{
++arr; // increment first
}
}
}
int main ( )
{
int myArray [] = {1, 3, 5, 6, 19, 1, 2, 2};
size_t N = sizeof(myArray)/sizeof(int);
odds_to_back(myArray, N);
for (size_t i = 0; i < N; ++i) std::cout << myArray[i] << " ";
return 0;
}
Oh, that is a hard one. You are calling swap (arr, end) and not your own int_swap. So, at least with my test code the function std::swap which is changing the pointers (and not the values pointed to) is called.
Changing the call to your int_swap looks promising.
[EDIT 1] I'll preface by saying that for this project, I am required to "Create a container class" where I can push, pop, and retrieve elements from a list. I am supposed to use pointers, and must write the functions for pushing, popping, etc. [/EDIT 1]
I am having difficulty pushing an element to a dynamically allocated pointer array. I am able to initially create an array just fine. You can see from my comments my thought process for how I think I should be able to add to the array:
1) create new array with room for the one new element;
2) add the new element to index 0;
3) copy the old array into the rest of the new array;
4) delete old array;
5) set the new array as the value of the pointer
I have the following three files:
IntegerList.h:
/**
*IntegerList.h
*/
#ifndef IntegerList_H
#define IntegerList_H
class IntegerList
{
private:
int * pArray;
int length;
public:
IntegerList(); // default constructor
void createArray(int howlong);
int getValue(int index);
void deleteArray();
void pushFront(int element);
};
#endif
IntegerList.cpp:
/**
* IntegerList.cpp
*/
#include "IntegerList.h"
#include <iostream>
using namespace std;
// IntegerList constructor:
IntegerList::IntegerList()
{
pArray = 0;
length = 0;
}
// creates an array of length howlong (determined by main.cpp); sets the values
// to equal ten times the index number. For example, if an array of size 4 is
// to be created, then an array with the following values will be created by
// this method: 0, 10, 20, 30. Sets length equal to howlong.
void IntegerList::createArray(int howlong)
{
length = howlong;
pArray = new int[length];
for (int i = 0; i < length; i ++)
pArray[i] = (i*10);
}
int IntegerList::getValue(int index)
{
return pArray[index];
}
void IntegerList::deleteArray()
{
delete[] pArray;
}
// places element at front of array
void IntegerList::pushFront(int element)
{
// create new array with room for the one new element
int newArray[length+1]; // nope
// start by adding the new element
newArray[0] = element;
// copy the old array, put it into the new array starting at index 1 (since
// index 0 is the new element)
for(int i = 0; i < length; i ++)
{
newArray[i+1] = pArray[i];
}
// delete old array
deleteArray();
// set pArray equal to the new array;
pArray = newArray;
// update the value of length
length += 1;
}
And my main file, main.cpp:
#include "IntegerList.h"
#include <iostream>
using namespace std;
int main()
{
// create object
IntegerList myArray;
// create array of length 5
myArray.createArray(5);
// print array
for (int i = 0; i < 5; i ++)
cout << "Element " << i << ". " << myArray.getValue(i) << endl;
// everything works ok so far
// push the number 99 to front
myArray.pushFront(99);
// print array
for (int i = 0; i < 6; i ++)
cout << "Element " << i << ". " << myArray.getValue(i) << endl;
myArray.deleteArray();
}
The first printArray() shows that everything is going as planned. However, after I try to push 99 to the front, things get screwed up :(
Here is the output I'm getting:
Element 0. 0
Element 1. 10
Element 2. 20
Element 3. 30
Element 4. 40
Element 0. 99
Element 1. 0
Element 2. 2130567168
Element 3. 4486648
Element 4. 2686508
Element 5. 4201772
Note that in the second printout, the first two elements appear to have the value that I intended for them to have.
Any suggestions?
I'm not sure if you can force your way to make static arrays of variable length, but it's in violation of standard.
int newArray[length+1];
will not work. Make it
int * newArray = new int[length+1];
instead.
As others in comments said, reallocating an array after every single insert is extremely inefficient and tedious work. Consider using some of these:
std::vector
std::stack (as you're inserting on the beginning of your container)
std::list
your very own linked list
I rewrote the code for pushing and got it to work properly. Revised code is below. Notice I had to assign the values form the tempArray back into the "original" array (pArray), not the address of tempArray.
void IntegerList::push(int value){
// when this method is called to push a value onto an empty array, that is,
// when length = 0, it first creates an array of length 1
if(length == 0)
pArray = new int[1];
// create temp array
int * tempArray = new int[length+1];
// add new value to index 0
tempArray[0] = value;
// add old elements
for(int i = 0; i < length; i++)
tempArray[i+1] = pArray[i];
delete[] pArray;
// initialize pArray with proper size
pArray = new int[length+1];
// copy elements of tempArray into pArray
for(int i = 0; i < length+1; i++)
pArray[i] = tempArray[i];
delete[] tempArray;
length += 1;
} // end push
I got an assignment to reverse an dynamic array in C++. So far, from my logic, I thinking of loop thru the array to reverse it. And here comes my code :
int main ()
{
const int size = 10;
int num_array[size];
srand (time(NULL));
for (int count = 0; count< sizeof(num_array)/sizeof(num_array[0]) ; count++){
/* generate secret number between 1 and 100: */
num_array[count] = rand() % 100 + 1;
cout << num_array[count] << " " ;
}
reverse(num_array[size],size);
cout << endl;
system("PAUSE");
return 0;
}
void reverse(int num_array[], int size)
{
for (int count =0; count< sizeof(num_array)/sizeof(num_array[0]); count++){
cout << num_array[sizeof(num_array)/sizeof(num_array[0])-1-count] << " " ;
}
return;
}
Somehow I think my logic was there but this code doesn't works, there's some error. However, my teacher told me that this isn't the way what the question wants. And here is the question :
Write a function reverse that reverses the sequence of elements in an array. For example, if reverse is called with an array containing 1 4 9 16 9 7 4 9 11,
then the array is changed to 11 9 4 7 9 16 9 4 1.
So far, she told us in the reverse method, you need to swap for the array element. So here's my question how to swap array element so that the array entered would be reversed?
Thanks in advance.
Updated portion
int main ()
{
const int size = 10;
int num_array[size];
srand (time(NULL));
for (int count = 0; count< size ; count++){
/* generate secret number between 1 and 100: */
num_array[count] = rand() % 100 + 1;
cout << num_array[count] << " " ;
}
reverse(num_array,size);
cout << endl;
system("PAUSE");
return 0;
}
void reverse(int num_array[], const int& size)
{
for (int count =0; count< size/2; count++){
int first = num_array[0];
int last = num_array[count-1];
int temp = first;
first = last;
last = temp;
}
}
You reverse function should look like this:
void reverse(int* array, const size_t size)
{
for (size_t i = 0; i < size / 2; i++)
{
// Do stuff...
}
}
And call it like:
reverse(num_array, size);
I am no C++ programmer, however I do see an easy solution to this problem. By simply using a for loop and an extra array (of the same size) you should be able to reverse the array with ease.
By using a for loop, starting at the last element of the array, and adding them in sequence to the new array, it should be fairly simple to end up with a reversed array. It would be something like this:
Declare two arrays of the same size (10 it seems)
Array1 contains your random numbers
Array2 is empty, but can consist of 10 elements
Also declare an integer, which will keep track of the progression of the for loop, but in the opposite direction. i.e not from the end but from the start.
Counter = 0
Next you will need to create a for loop to start from the end of the first array, and add the values to the start of the second array. Thus we will create a for loop to do so. The for loop will be something like this:
for(int i = lengthOfArray1; i > 0; i--){
Array2[Counter] = Array1[i]
Counter++
}
If you only wish to print it out, you would not need the counter, or the second array, you will simply use the Array1 elements and print them out with that style of for loop.
That's it. You could set Array1 = Array2 afterward if you wished to keep Array1 the original for some reason. Hope this helps a bit, changing it to C++ is your job on this one unfortunately.
You're not actually swapping the elements in the array, you're just printing them out. I assume she wants you to actually change what is stored in the array.
As a hint, go through the array swapping the first and last element, then the 2nd and 2nd last element, etc. You only need to loop for size/2 too. As you have the size variable, just use that instead of all the sizeof stuff you're doing.
I would implement the function like following
void reverse(int A[], int N)
{
for (int i=0, j=N-1; i<j; i++, j--){
int t = A[i];
A[i] = A[j];
A[j] = t;
}
}
i am making an ordered array. Where the elements are in order. Example 1,2,3,4,5,6,77,89,100,201. I ask the user to enter in the size of the array. This is fine and the push function will put the elements in ordered. But when the arrayList is resized,The elements are no longer being allocated in an ordered fashion.
Here is my code:
//-------------------------------------------------------
// Name: Array::Resize
// Description: Resize the array to a new size.
// Arguments: p_size. The new size of the Array.
//-------------------------------------------------------
void Resize(int p_size)//resizes the array to the size of p_size
{
cout << "Did i get this far ";
if(p_size < 0)//checks if new size is less than 0
{
cout << "ERROR! Size of an array can not be less than 0!" << endl;
}
else//else its ok to continue
{
Datatype* newArray = new Datatype[p_size];//creates a pointer newArray that points at a new array
if(newArray == 0)
{
return;
}
cout << "Did i get this far ";
int min;
if(p_size < size)//checks the if the new array is smaller than the old one
min = p_size;
else//else its going to be bigger
min = size;
cout << "Did i get this far ";
int index;
int temp = num_elements;//puts num_elements into a temporary variable called temp
num_elements = 0;//num_elements is set to 0
for(index = 0; index < min; index++)
{
newArray[index] = m_array[index];//places everything from the old array into the new array that will fit.
if(num_elements < temp)//if the num_elements is less than temp(the original num_elements)
{
num_elements++;//increment num_elements. This will keep incrementing to create the new num_elements based the number of elements cut off in the resize
}
}
size = p_size;//sets the old size to be equal to the new size
cout << "Did i get this far ";
if(m_array != 0)
cout << "\nI am just about to delete ";
//delete[] m_array;//deletes the old array
m_array = newArray;//makes m_array point at the new array
newArray = 0;//makes newArray a null pointer
}
}
//---------------------------------------------------------------------------------------
// Name: Push
// Description:
//---------------------------------------------------------------------------------------
void push(Datatype p_item)
{
if(num_elements == size)//checks if the array is full and needs to be resized
{
Resize(size + g_size);//calls the resize function
}
int pos = num_elements;
for(int x=0;x<num_elements;x++)
{
if(p_item < m_array[x])
{
pos=x;
}
}
//loops through the array from high to low moving all values to the right
//to make space for the passed in value until it gets to the right place
for(int index = num_elements; index >= pos; index--)
{
m_array[index] = m_array[index-1];//moves the values to the right
}
m_array[pos] = p_item;//the passed in value is positioned into its ordered position
num_elements++;
cout<< "Num Elements " << num_elements;
cout<< "Size " <<size;
}
//--------------------------------------------------------------------------------------------
// Name: template <class Datatype>
// Description:
//--------------------------------
template <class Datatype>
//--------------------------------------------------------------------------------------------
// Class: OrderedArray.
//--------------------------------------------------------------------------------------------
class OrderedArray
{
//--------------------------------------------------------------------------------------------
// Member Variables.
//--------------------------------------------------------------------------------------------
private:
Datatype* m_array;
int size;
int g_size;
int num_elements; //Counter for the number of elements in the Array.
//--------------------------------------------------------------------------------------------
// Name: Constructor.
// Description: Constructs the Array.
//--------------------------------------------------------------------------------------------
OrderedArray(int p_size)
{
//Sets the Array size.
m_array = new Datatype[p_size];
size = p_size;
grow_size = 1;
//How many elements are in the Array.
num_elements = 0;
}
Any help would be much appreciated.
I suggest using copies of last element of your m as new elements instead of default-constructed instances. So the last elements will be grater or equal to all preceding elements of the array.