I am writing a program that uses two dynamic arrays to sort the original array: One for the left side, and one for the right side.
However, the dynamic arrays do not receive the original array in lines 23 and 28 (As demonstrated by the cout methods throughout the array). They are either empty, or contain elements that are out of bounds. Thus, the program does not work as a whole. My question is then, is the issue with the initialization itself, or is it with the declaration on lines 18-19? I personally believe it is with the declaration, but I am unsure of what I should do with it, as with a Dynamic Array, I do not want to mess with the size too much. I included all of the methods for proper testing, but I will edit this question if they are deemed unnecessary. Thank you in advance for your help.
#include "stdafx.h"
#include <iostream>
using namespace std;
void Merge(int *array, int left, int middle, int right)
{
int * LArray;
int * RArray;
int counter = left;//This counter is used as a marker for the main array.
int mid = middle;
cout<<"Left " << left << "middle: "<< middle << " right: " << right<<endl;
LArray = new int[middle-left + 1];
RArray = new int[right];
/*Initializes LArray*/
for (int i = left; i < middle - left + 1; i++)
{
LArray[i] = array[i];
}
/*Initializes RArray*/
int temp = 0;
for (int i = middle; i < right; i++)
{
RArray[temp] = array[i];
temp++;
}
/*Prints out LArray*/
cout<<"LARRAY: ";
for (int i = left; i < middle- left + 1; i++)
{
cout<<LArray[i]<< " ";
}
/*Prints out RArray*/
cout<<endl<<"RARRY: ";
temp = 0;
for (int i = middle; i < right; i++)
{
temp = 0;
cout<<RArray[temp]<< " ";
temp++;
}
cout<<endl;
while (left <= middle && mid <= right)
{
/*This if statement checks if the number in the left array is smaller than the number in the right array*/
if (LArray[left] < RArray[right])
{
array[counter] = LArray[left];
left++;
counter++;
cout<<"First if: array[counter]: "<< array[counter]<<" LArray[left]" << LArray[left]<<" left: "<< left<<" counter : "<< counter<<endl;
}
/*This else statement checks if the number in the right array is smaller than the number in the left array*/
else
{
array[counter] = RArray[right];
mid++;
counter++;
cout<<" First else: array[counter]: "<< array[counter] << " RArray[right] "<< RArray[right]<<" mid: "<< mid<<" counter : "<< counter<<endl;
}
}
/*If RArray is completed, check this one for any remaining elements.*/
while (left <= middle)
{
array[counter] = LArray[left];
left++;
counter++;
cout<<" First while: array[counter]: "<< array[counter]<<" LArray[left]" << LArray[left]<<" left: "<< left<<" counter : "<< counter<<endl;
}
/*If LArray is completed, check this one for any remaining elements.*/
while (mid <= right)
{
array[counter] = RArray[right];
mid++;
counter++;
cout<<" Second while: array[counter]: "<< array[counter] << " RArray[right] "<< RArray[right]<<" mid: "<< mid<<" counter : "<< counter<<endl;
}
delete [] LArray;
delete [] RArray;
}
void MergeSort( int *array,int left, int right )
{
if ( left < right )
{
int middle = ( left + right ) / 2;
MergeSort( array, left, middle );
MergeSort( array, middle + 1, right );
Merge( array, left, middle, right );
}
};
/*Checks if the array listed is sorted by looping through and checking if the current number is smaller than the previous.*/
bool IsSorted(int* array, unsigned long long size)
{
for (int i = 0; i < size; i++)
{
cout<<array[i]<< " ";
}
cout<<endl;
for (int i = 1; i < size; i++)
{
if (array[i] < array[i-1])
return false;
}
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
int array[8] = {5, 2, 4, 7, 1, 3, 2, 6};
MergeSort(array, 0, 8);
bool check = IsSorted(array, 8);
if (check)
cout<<"It is sorted!";
else
cout<<"It is not sorted!";
return 0;
}
The idea of merge sort is that you recursively split an array into two halves, sort those two halves and then merge them back together.
Here are the things I see wrong with your code:
Code weirdness that aren't the problem with your algorithm:
Your left array is always larger than necessary, since you're allocating it to have middle elements and initializing it as such.
You initialize right array twice.
The actual problems with your algorithm:
You're not initializing counter correctly, it's always being set as 0 so no matter how deep you are in the callstack, you are always setting elements 0 through middle to be the sorted array instead of the range between left and right.
You're trying to index into the right array with argument right ...which will always be large than the number of elements in right array since you allocated it to have right - middle elements.
You also have an error in your MergeSort function. You are never actually sorting the middle element since in the Merge function array[right] is never added to RArray, so the first recursive call won't sort it, and you're passing in middle + 1 to the second recursive call so it's not sorting it.
Related
c++
When printing to console, if function execution is sequential it would seem logical the ordered array would be printed after calling insertionSort, however order list does not print until next loop. Any help would be appreciated.
#include <stdio.h>
#include <iostream>
#include <array>
using namespace std;
void insertionSort(int* array, int size) {
for (int i = 1; i < size; i++) {
int key = i - 1;
while (i > 0 && array[key] > array[i] ) {
int tmp = array[i];
array[i] = array[key];
array[key] = tmp;
i -= 1;
key -= 1;
}
}
}
const int ARRAY_MAXSIZE = 5;
int main(void) {
int *array = (int*)calloc(ARRAY_MAXSIZE, sizeof(int));
int input;
cout << "Enter 5 digits\n";
for (int size=0; size < ARRAY_MAXSIZE; size++) {
cout << size << " index ";
cin >> input;
array[size] = input;
insertionSort(array, size);
for (int j=0; j <= size; j++) {
cout << array[j];
}
cout << '\n';
}
}
Console Entry
This is a classic off-by-one error. Your insertionSort expects you to pass the number of elements to sort via the parameter size. But your main loop is always holding a value that is one less than the size immediately after adding an element.
I want to say that bugs like this are easily discovered by stepping through your program's execution with a debugger. If you don't know how to use a debugger, start learning now. It is one of the most important tools used by developers.
Anyway, the quick fix is to change your function call to:
insertionSort(array, size + 1);
However, as Paul McKenzie pointed out in comments, it's a bit crazy to do this every time you add a new element because your function sorts an entire unsorted array. Your array is always nearly sorted except for the last element. You only need to call that function once after your input loop is done:
// Read unsorted data
for (int size = 0; size < ARRAY_MAXSIZE; size++) {
cout << size << " index ";
cin >> input;
array[size] = input;
}
// Sort everything
insertionSort(array, ARRAY_MAXSIZE);
// Output
for (int j = 0; j < ARRAY_MAXSIZE; j++) {
cout << array[j];
}
cout << '\n';
But if you want every insertion to result in a sorted array, you can "slide" each new value into place after inserting it. It's similar to a single iteration of your insertion-sort:
// Sort the last element into the correct position
for (int i = size; i >= 1 && array[i] > array[i - 1]; i--)
{
std::swap(array[i], array[i - 1]);
}
Even better, you don't need to swap all those values. You simply read the value, then shuffle the array contents over to make room, then stick it in the right spot:
// Read next value
cin >> input;
// Shuffle elements to make room for new value
int newPos = size;
while (newPos > 0 && array[newPos - 1] > input) {
array[newPos] - array[newPos - 1];
newPos--;
}
// Add the new value
array[newPos] = input;
I'm a Computer Science student. This is some code that I completed for my Data Structures and Algorithms class. It compiles fine, and runs correctly, but there is an error in it that I corrected with a band-aid. I'm hoping to get an answer as to how to fix it the right way, so that in the future, I know how to do this right.
The object of the assignment was to create a binary search. I took a program that I had created that used a heap sort and added a binary search. I used Visual Studio for my compiler.
My problem is that I chose to read in my values from a text file into an array. Each integer in the text file is separated by a tabbed space. In line 98, the file reads in correctly, but when I get to the last item in the file, the counter (n) counts one time too many, and assigns a large negative number (because of the array overflow) to that index in the array, which then causes my heap sort to start with a very large negative number that I don't need. I put a band-aid on this by assigning the last spot in the array the first spot in the array. I have compared the number read out to my file, and every number is there, but the large number is gone, so I know it works. This is not a suitable fix for me, even if the program does run correctly. I would like to know if anyone knows of a correct solution that would iterate through my file, assign each integer to a spot in the array, but not overflow the array.
Here is the entire program:
#include "stdafx.h"
#include <iostream>
#include <fstream>
using std::cout;
using std::cin;
using std::endl;
using std::ifstream;
#define MAXSIZE 100
void heapify(int heapList[], int i, int n) //i shows the index of array and n is the counter
{
int listSize;
listSize=n;
int j, temp;//j is a temporary index for array
temp = heapList[i];//temporary storage for an element of the array
j = 2 * i;//end of list
while (j <= listSize)
{
if (j < listSize && heapList[j + 1] > heapList[j])//if the value in the next spot is greater than the value in the current spot
j = j + 1;//moves value if greater than value beneath it
if (temp > heapList[j])//if the value in i in greater than the value in j
break;
else if (temp <= heapList[j])//if the value in i is less than the value in j
{
heapList[j / 2] = heapList[j];//assigns the value in j/2 to the current value in j--creates parent node
j = 2 * j;//recreates end of list
}
}
heapList[j / 2] = temp;//assigns to value in j/2 to i
return;
}
//This method is simply to iterate through the list of elements to heapify each one
void buildHeap(int heapList[], int n) {//n is the counter--total list size
int listSize;
listSize = n;
for (int i = listSize / 2; i >= 1; i--)//for loop to create heap
{
heapify(heapList, i, n);
}
}
//This sort function will take the values that have been made into a heap and arrange them in order so that they are least to greatest
void sort(int heapList[], int n)//heapsort
{
buildHeap(heapList, n);
for (int i = n; i >= 2; i--)//for loop to sort heap--i is >= 2 because the last two nodes will not have anything less than them
{
int temp = heapList[i];
heapList[i] = heapList[1];
heapList[1] = temp;
heapify(heapList, 1, i - 1);
}
}
//Binary search
void binarySearch(int heapList[], int first, int last) {//first=the beginning of the list, last=end of the list
int mid = first + last / 2;//to find middle for search
int searchKey;//number to search
cout << "Enter a number to search for: ";
cin >> searchKey;
while ((heapList[mid] != searchKey) && (first <= last)) {//while we still have a list to search through
if (searchKey < heapList[mid]) {
last = mid - 1;//shorten list by half
}
else {
first = mid + 1;//shorten list by half
}
mid = (first + last) / 2;//find new middle
}
if (first <= last) {//found number
cout << "Your number is " << mid << "th in line."<< endl;
}
else {//no number in list
cout << "Could not find the number.";
}
}
int main()
{
int j = 0;
int n = 0;//counter
int first = 0;
int key;//to prevent the program from closing
int heapList[MAXSIZE];//initialized heapList to the maximum size, currently 100
ifstream fin;
fin.open("Heapsort.txt");//in the same directory as the program
while (fin >> heapList[n]) {//read in
n++;
}
heapList[n] = heapList[0];
int last = n;
sort(heapList, n);
cout << "Sorted heapList" << endl;
for (int i = 1; i <= n; i++)//for loop for printing sorted heap
{
cout << heapList[i] << endl;
}
binarySearch(heapList, first, last);
cout << "Press Ctrl-N to exit." << endl;
cin >> key;
}
int heapList[MAXSIZE];//initialized heapList to the maximum size, currently 100
This comment is wrong - heapList array is declared not initialized, so when you had read all data from the file, index variable n will point to the uninitialized cell. Any attempt to use it will invoke an undefined behavior. You could either: initialize an array before using it, decrement n value, since it greater than read values number by one, or better use std::vector instead of array.
You populate values for heapsort for indices 0 to n-1 only.
Then you access heaplist from 1 to n which is out of bounds since no value was put in heapsort[n].
Use
for (int i = 0; i < n; i++) //instead of i=1 to n
Hi everyone I need to write merge sort in C++ using a given header for mergeSort();
I have the partitioning correct but at a point where its merging an array that was merged before it has 0's. For example: If I have [34][21] i get [21, 34] but when this is merged with let's say [8] it gives [0, 0, 8]. I am losing values. Please help me debug it.
Note: I have some moveCount to count data moves and compCount to count computations. Please don't get confused with those.
int * merge(int * left ,int szLeft ,int * right,int szRight, int &compCount, int &moveCount){
int * newArr = new int [szLeft+szRight];
cout << "Left: ";
for (int i = 0; i < szLeft; ++i){
cout << left[i] << " ";
}
cout << endl;
cout << "Right: ";
for (int i = 0; i < szRight; ++i){
cout << right[i] << " ";
}
cout << endl;
int bigArrIndex = 0, rightArrIndex = 0,leftArrIndex = 0;
while(leftArrIndex < szLeft && rightArrIndex < szRight){
compCount++;
if(right[rightArrIndex] <= left[leftArrIndex]){
newArr[bigArrIndex] = right[rightArrIndex];
rightArrIndex++;
compCount++;
}
else{
newArr[bigArrIndex] = left[leftArrIndex];
leftArrIndex++;
}
moveCount++;
bigArrIndex++;
}
//1 more computation done even if the loop is not executed
compCount++;
//copy the rest of the stuff if left
while(rightArrIndex < szRight){
moveCount++;
compCount++;
newArr[bigArrIndex] = right[rightArrIndex];
rightArrIndex++;
bigArrIndex++;
}
//1 more computation done even if the loop is not executed
compCount++;
//copy the rest of the stuff if left
while(leftArrIndex < szLeft){
moveCount++;
compCount++;
newArr[bigArrIndex] = left[leftArrIndex];
leftArrIndex++;
bigArrIndex++;
}
//1 more computation done even if the loop is not executed
compCount++;
return newArr;
}
void mergeSort( int * arr, int size, int &compCount, int &moveCount){
//to take the branch or not needs 1 comparison
compCount++;
if(size > 1){
int mid = size/2;
int * left = new int[mid];
int * right = new int[size-mid];
for(int i = 0; i < mid; i++){
compCount++;
left[i] = arr[i];
moveCount++;
}
//1 more computation done even if the loop is not executed
compCount++;
for(int i = mid; i < size; i++){
right[i-mid] = arr[i];
moveCount++;
compCount++;
}
//1 more computation done even if the loop is not executed
compCount++;
mergeSort(left,mid,compCount,moveCount);
mergeSort(right,size-mid,compCount,moveCount);
int * sortedArr = merge(left,mid,right,size-mid,compCount,moveCount);
cout << "Done: ";
for (int i = 0; i < size; ++i)
cout << sortedArr[i] << " ";
cout << endl;
//delete[] left;
//delete[] right;
for(int i = 0; i < size; i++){
arr[i] = sortedArr[size];
moveCount++;
compCount++;
}
//1 more computation done even if the loop is not executed
compCount++;
}
}
Just one line. Fix noted in comment:
//delete[] left;
//delete[] right;
for(int i = 0; i < size; i++){
arr[i] = sortedArr[i]; // fix from [size] to [i]
moveCount++;
compCount++;
}
Comment: in mergeSort, rather than allocate left and right, the code could use arr instead of left, and arr+mid instead of right. Two less allocations. An entry / helper function could do a one time allocation of a temp array the same size as the original array, and pass that as a parameter to mergeSort() which would in turn pass it as a parameter to merge(). In that case, all mergeSort does is create pairs of indices on the stack, and merge does the actual merge and copy back.
Although probably beyond the scope of this class, the copy back can also be eliminated with two mutually recursive versions of mergeSort, one where the merged data ends in in the original array, call this mergeSortO(), one where the merged data ends up in the temp array, call this mergeSortT(). mergeSortO() calls mergeSortT() twice (left and right halves), then calls merge() to merge from temp array to original array. mergeSortT() calls mergeSortO() twice (left and right halves), then calls merge() to merge from original array to temp array, or if size is 1, it copies one element from original to temp array.
Also probably beyond the class, another alternative would be bottom up merge sort, as most libraries such as STL std::stable_sort() use some variation of bottom up merge sort.
Question is: write a function that takes an array A of length n and an index i into A, and rearrange the elments such that all elements less than A[i] appear first, followed by elements equal to A[i], followed by elements greater than A[i].
explanation for my code:
Ask user for n numbers, which is 11. And ask him what the index that he wants to rearrange the elements with. It takes it to function1, and creates a for loop and does an if else statement. if A[i] < A{index} , place it in the begining, else if it's less, place it at the end, or place it in the middle:
Here is my code
#include <iostream>
using namespace std;
void function1(int a[], int ind);
int main()
{
int a[11];
int index;
cout << " enter the numbers: " << endl;
for(int i=0; i < 11; i++)
cin >> a[i];
cout << "what is the index ? " << endl;
cin >> index;
function1(a,index);
}
void function1(int a[], int ind)
{
int x = a[ind];
int newArray[11];
for(int i=0; i < 11; i++)
{
if(a[i] < x)
{
newArray[i] = a[i];
}
else if(a[i] > x)
{
newArray[10-i] = a[i];
}
else
{
newArray[10/2] = a[i];
}
}
for(int i=0; i<11; i++)
cout << newArray[i] << " ";
}
The output that I am expecting to get is the rearrangement of the new array which will probably look similar to this:
a[0....x....n-1], where x is the index that represents a[i]
however I am getting incorrect output with numbers randomly scattered across
what is wrong with my logic ?
The problem is that (like Olaf Dietsche pointed out) you take just one index where two are necessary. Further you can't know if the element that is neither smaller not bigger than a[ind] (means equal to a[ind]) is to be inserted in the middle of the new array. (Imagine 3 2 1 and index 3 results in 2 1 3 but 3 isn't in the middle!)
Updated Version (allows for multiple elements with same value as pivot element)
void rearange(int* data, int size, int pivot)
{
int* temp_data = new int[size];
int start_index = 0, end_index = size - 1;
for (int i = 0; i < size; i++)
{
if (data[i] < data[pivot]) // -> insert 'before' pivot element
{
temp_data[start_index] = data[i];
start_index++;
}
else if (data[i] > data[pivot]) // -> insert 'behind' pivot element
{
temp_data[end_index] = data[i];
endIndex--;
}
// else: skip pivot(s)
}
// insert pivot element(s)
for (int i = start_index; i <= end_index; i++)
{
temp_data[i] = data[pivot];
}
for (int i = 0; i < size; i++)
{
std::cout << temp_data[i] << " ";
}
delete[] temp_data;
}
Input:
11 10 9 8 7 7 7 6 5 4 3
5
Output
6 5 4 3 7 7 7 8 9 10 11
As you see, all elements smaller than element 5 (with value of 7) are before, all elements greater are behind the pivot element. All other elements with same value as pivot are wrapped around position 5, wherever there's free space. However the rearranged elements are not yet sorted (apart from being positioned relative to pivot element)!
You use the same index i for the smaller and larger values. This means, if only the last value a[10] is larger than x, you will write it in the first location newArray[10 - 10], even though you already filled all places up to the 10th. Another problem is, when you have multiple middle values. They will all be stored into newArray[5].
What you want to achieve is called partitioning, as used in the quicksort algorithm.
You need to maintain two indexes (pointers), one for the smaller (left) and one for the larger (right) values.
You have to determine the size of your array at the beginning and pass the fixed size of the array to the function as a parameter.
I was just practising a little bit and tried to sort an array with the bubble sort algorithm.
Compiler didn't give me any warnings nor errors and it worked well! First you type 10 times a number and then the program sorts them + prints them.
Code:
#include <iostream>
using namespace std;
void arr_sort(int* array, const int arr_size){
int temp = 0; //Temporary integer to store (if necessary) the current element
int end = 0; //Run time condition
while(end++ != arr_size){ // Will loop max. 10 times
for(int i = 0; i < arr_size; i++){
if(array[i] > array[i + 1]){ //If the current element
temp = array[i]; //is bigger than the next
array[i] = array[i + 1];//Change the positions
array[i + 1] = temp;
}
}
}
}
int main(){
int arr_input[10];
for(int i = 0; i < 10;i++) //The user has to type 10 numbers
cin >> arr_input[i]; //which will be stored in this array
arr_sort(arr_input, 10); //sorts the array
cout << endl << endl;
for(int i = 0; i < 10; i++) //Print out the array!
cout << arr_input[i] << ", ";
cout << endl;
return 0;
}
My only problem is the while-loop in the arr_sort function. I mean it sorts the array until end has the same value as arr_size. But often it doesn't need that long. My question now... How can I improve this function? How can I test if the array is completely sorted so the while-loop can stop without running another time and another time ...?
Before your for loop, assume it's sorted:
bool sorted = true;
In your if statement`, record that it's not sorted:
sorted = false;
After your for loop`, return if there was no evidence that it's not sorted:
if ( sorted ) return;
Just outside of the for loop, place a bool and set it to false. Inside the swap block, set the bool to true. After the for loop, check the value of the boolean, and if it's still false, no swaps were made so the array is sorted, so break out of the while loop.
while(end++ != arr_size){ // Will loop max. 10 times
bool swapped = false;
for(int i = 0; i < arr_size; i++){
if(array[i] > array[i + 1]){ //If the current element
temp = array[i]; //is bigger than the next
array[i] = array[i + 1];//Change the positions
array[i + 1] = temp;
swapped = true;
}
}
if (!swapped) break;
}