It compiles fine, but when it runs, it adds random high numbers to the list, as well as duplicates of existing numbers. I've had a couple of people look over this, and none of them can figure it out.
void mergeSort(int list[], int length) {
recMergeSort(list, 0, length - 1);
}
void recMergeSort(int list[], int first, int last) {
if (first < last) {
int mid = (first + last) / 2;
recMergeSort(list, first, mid);
recMergeSort(list, mid + 1, last);
merge(list, first, last, mid);
}
}
void merge(int list[], int first, int last, int mid) {
int arraySize = last - first + 1;
int* tempList = new int[arraySize];
int beginPart1 = first;
int endPart1 = mid;
int beginPart2 = mid + 1;
int endPart2 = last;
int index = beginPart1;
while (beginPart1 <= endPart1 && beginPart2 <= endPart2) {
if (list[beginPart1] < list[beginPart2]) {
tempList[index] = list[beginPart1];
beginPart1++;
}
else {
tempList[index] = list[beginPart2];
beginPart2++;
}
index++;
}
while (beginPart1 <= endPart1) {
tempList[index] = list[beginPart1];
index++;
beginPart1++;
}
while (beginPart2 <= endPart2) {
tempList[index] = list[beginPart2];
index++;
beginPart2++;
}
for (int i = first; i <= last; i++) {
list[i] = tempList[i - first];
}
delete[] tempList;
}
In function merge(), you're incorrectly calculating the index variable:
Assuming begin = 10, mid = 14, end = 19 (for a total array size of 0 .. 19, and you're recMergeSort()ing the higher half), your index = 10, but the tempList array is indexed 0..9 (because arraySize = last - first + 1 == 10).
So you're overflowing your tempList array, and when you "merge", you get data corruption.
Fix your index variable to be 0-based (rather than beginPart1 based).
I think problem is here:
int index = beginPart1;
It should be
int index = 0;
If I run this in C# I get an IndexOutOfRangeException on the following line:
tempList[index] = list[beginPart1];
I reckon if you trace it through you are probably running off the end of a buffer somewhere hence the random numbers.
Related
Having an issue with my MergeSort() and Merge() in my homework for school. Im new to C++ (I've been out of school for two years, they changed my major with new classes. I was learning java....) Long story short, my Merge() and MergeSort() functions aren't working in VS Code when I debug them. I'm having issues with the function working in general. I don't know if I'm passing the parameters correctly.
I've tried to change up the Merge() function by moving it up above MergeSort().
void Merge(int B[], int &lStart, int &lEnd, int &rStart, int &rEnd) {
int length;
int temp[length];
int theSaved = lStart;
int i = lStart;
while (lStart < lEnd && rStart <= rEnd) {
if (B[lStart] < B[rStart]) {
temp[i++] = B[lStart++];
}
else {
temp[i++] = B[rStart++];
}
}
while (lStart <= lEnd) {
temp[i++] = B[lStart++];
}
while (rStart <= rEnd) {
temp[i++] = B[rStart++];
}
for (int j = theSaved; j < rEnd; j++) {
B[j] = temp[j];
}
}
void MergeSort(int B[], int start, int end) {
int middle;
int theMiddle = middle + 1;
if (start < end) {
middle = (start + end) / 2;
MergeSort(B, start, middle);
MergeSort(B, middle + 1, end);
Merge(B, start, middle, theMiddle, end);
}
}
int main() {
int length = 7;
int begin = 0;
int end = (length - 1);
int B[length] = {10, 50, 90, 60, 5, 20, 40};
for (int i = 0; i < length; i++) {
MergeSort(B, begin, end);
cout << "\n" << B[i];
}
return 0;
}
I just wanted some insight into what's going on. I tried to do it logically but it ended up being too confusing. The output should be 5,10,20,40,50,60,90
merge() should not be taking parameters by reference, use int lStart instead of int &lStart. rStart will always be lEnd + 1, so only 3 parameters are needed for merge. The if in merge should be lStart <= lEnd.
Although not a problem, the code would be a bit simpler if the initial call from main is MergeSort(B, 0, length). Then Merge could be called with (B, start, middle, end). The loop in merge() would have ... lStart < middle ... rStart < end ... for the loops and if statements.
Basic quicksort function that partitions and has myswap. everything works fine except for index 0 in the array.
#include<iostream>
#include<string>
#include<iostream>
#include<vector>
#include <ctime>
using namespace std;
//swap
void myswap(int mya[], int a, int b) {
int temp = mya[a];
mya[a] = mya[b];
mya[b] = temp;
}
//partition, returns pivot index
int mypartition(int mya[], int first, int last)
{
int middle = ((first + last) / 2);
int pivot = mya[middle];
//swap first with middle
myswap(mya, first, middle);
//two pointers
int pivotindex = first;
//loop through the elements
for (int index = first + 1; index <= last; index++) {
if (mya[index] <= pivot)
{
pivotindex++;
myswap(mya, pivotindex, index);
}
}
//swap the pivot in its right place
myswap(mya, first, pivotindex);
return pivotindex;
}
void QuickSort(int mya[], int a, int b)
{
//partition
if (a <= b)
{
int index = mypartition(mya, a, b);
QuickSort(mya, a, index - 1);
QuickSort(mya, index + 1, b);
}
}
int main() {
//vector<int> mya;
int * mya = new int[5000000];
srand(time(0));
int i = 0;
int last = 0;
while(i < 100)
{
int x = (rand() + time(0)) % 5000000;
mya[last] = x;
last++;
i++;
}
clock_t startTime, endTime;
startTime = clock();
QuickSort(mya, 0, last);
endTime = clock();
cout << "Sorted in " << (double)(endTime - startTime) / CLOCKS_PER_SEC << " seconds" << endl;
for (int i = 0; i < 100; i++)
{
cout << mya[i] << endl;
}
delete[] mya;
return 0;
}
The problem im having is that the array gets sorted but when mya[0] is called in the for loop it outputs -842150451. This is just a basic quicksort and for some reason im having trouble with it.
You are calling it wrong.
QuickSort(mya, 0, last-1);
Remember that there are last elements, meaning they are indexed 0..last-1.
You do also have a potential overflow problem with your calculation of middle. Use (last - first + 1)/2 + first.
Hope this helps.
Integer Overflow Causing this problem.
int x = (rand() + time(0)) % 5000000;
this line sometime two 10 digits long numbers whose sum is causing the integer overflow.
Just modify that statement as following and your code starts working:
int x = (rand() % 5000000) + (time(0) % 5000000);
Edit: It was a problem I found executing your code using Ideone. Further noticing I found Your Index 0 problem is actually caused by partition function.
change for (int index = first + 1; index <= last; index++) { this line to
for (int index = first + 1; index < last; index++) { //remove the equal sign
N.B: for me this fixed your issue. But I think in your void QuickSort(int mya[], int a, int b)
if (a <= b) should be changed to if (a < b).
So I've been having a problem with a c++ program that quicksorts an array of integers. When I have more than six elements in my array, the sort infinitely loops for some reason. I think I've isolated the problem to the choosing of mm pivotal value, but I can't work out for the life of me why it's causing it to break.
#include<iostream>
using namespace std;
int getPivot(int begin,int end){//Takes length of array as input and returns the position of the pivot
int len = end-begin;
if(len < 3){
return end;
}else{
return 2;
}
};
void quickSort(int begin, int end, int arr[]){
int pivot = arr[getPivot(begin,end)];//get Pivotal value - If I replace this with just 0 then there are no problems...
int tempLeft = begin, tempRight = end;
int temp;
while(tempLeft <= tempRight){
while(arr[tempLeft] < pivot){//Find a point where there are 2 elements that need to be swapped
tempLeft++;
}
while(arr[tempRight] > pivot){
tempRight--;
}
if(tempLeft <= tempRight){
temp = arr[tempLeft];//Swap the elements
arr[tempLeft] = arr[tempRight];
arr[tempRight] = temp;
tempLeft++;//Skip these swapped elements in the sort
tempRight--;
}
}
if (begin < tempRight){//Only recurse lower if the new sub array has a length greater than 1
quickSort(begin, tempRight, arr);
}
if (tempLeft < end){
quickSort(tempLeft, end, arr);
}
}
main() {
int array[] = {0,1,2,3,4,5,6};
int length = 7;
quickSort(0,length-1,array);
}
You will probably ask why I have such a weird way of choosing my pivotal value, but lets just say that for this instance the pivotal value has to be the third element in each sublist or if the sub list is smaller than 3 it is the last item in the sublist.
The reason I think the problem is associated with the pivotal value is because when I replace my method of choosing a pivot with just using the first element in the sublist I don't have any problems.
If run, as is now the program, will segfault after looping infinitely but if the array being sorted is one element shorter, it will work fine. That has had me baffled for hours now, and I can't work out what the problem is. If anyone has any tips or suggestions, they would be greatly appreciated.
quickSort(3,6,arr) will always call quickSort(3,6,arr).
I think you miss
int getPivot(int begin,int end)
{
//Takes length of array as input and returns the position of the pivot
int len = end-begin;
if(len < 3){
return end;
}else{
return 2+begin; // Here
}
};
EDIT: Clarification
GetPivot(3,6) will return 2, instead should return an index between 3 and 6.
You could also use the median of three approach for your pivot. It is a little more robust.
#include<iostream>
using namespace std;
void myswap(int* arr, int left, int right)
{
int swap = arr[left];
arr[left] = arr[right];
arr[right] = swap;
}
int getPivotIndex(int* arr, int begin, int end){
int middle = (begin + end) / 2;
if (arr[end] < arr[begin])
{
myswap(arr, begin, end);
}
if (arr[middle] < arr[begin])
{
myswap(arr, middle, begin);
}
if (arr[end] < arr[middle])
{
myswap(arr, end, middle);
}
return middle;
};
void quickSort(int begin, int end, int* arr){
int pivot = arr[getPivotIndex(arr, begin, end)];
int tempLeft = begin, tempRight = end;
while (tempLeft <= tempRight){
while (arr[tempLeft] < pivot){
tempLeft++;
}
while (arr[tempRight] > pivot){
tempRight--;
}
if (tempLeft <= tempRight){
myswap(arr, tempLeft, tempRight);
tempLeft++;
tempRight--;
}
}
if (begin < tempRight){
quickSort(begin, tempRight, arr);
}
if (tempLeft < end){
quickSort(tempLeft, end, arr);
}
}
int main() {
int array[] = { 6, 0, 2, 5, 4, 3, 1 }; // Test we are actually sorting
int length = 7;
quickSort(0, length - 1, array);
for (int i = 0; i < length; i++)
{
std::cout << "array[" << i << "]: " << array[i] << endl;
}
return 0;
}
I am creating a small program that is supposed to sort integers in an array in ascending order, but I am extremely stuck on the algorithm that I am supposed to use. I cannot iterate through the array, I must instead use a recursion function. I am allowed to have an auxiliary function that can find the smallest index in the array, which I have done successfully, but I am having the hardest time figuring out how to use that function to sort my array in the recursion function. Here is the code that I have so far, I understand that my sortIntegers function is way off.
int main()
{
int numbers[] = {8, 2, 5, 1, 3};
sortingIntegers(numbers, 5);
return 0;
}
void sortingIntegers(int *list, int size) {
if (size == 1) {
for (int i = 0; i < size; i++) {
cout << list[i] << ", ";
}
} else {
for (int z = 0; z < size; z++) {
if (list[size - 1] == smallestIndex(list)) {
for (int y = 0; y < size; y++) {
swap(list[z], list[y]);
}
}
}
sortingIntegers(list, size - 1);
}
}
int smallestIndex(int *array) {
int smallest = array[0];
for (int i = 1; i < sizeof(array); i++) {
if (array[i] < smallest) {
smallest = array[i];
}
}
return smallest;
}
int main()
{
int numbers[] = {8, 2, 5, 1, 0};
sortingIntegers(numbers, 0, 5);
for (int i=0;i<5;i++)
cout << numbers[i] << ' ';
return 0;
}
void sortingIntegers(int *list, int left, int size) {
if (left == size)
return;
int smallest = smallestIndex(list, left, size);
int c = list[smallest];
list[smallest] = list[left];
list[left] = c;
sortingIntegers(list, left+1 ,size);
}
int smallestIndex(int *array, int left, int size) {
int smallest = array[left];
int smIndex = left;
for (int i = left+1; i < size; i++) {
if (array[i] < smallest) {
smallest = array[i];
smIndex = i;
}
}
return smIndex;
}
That's my solution based on yours. First of all sizeof(array) returns the size of pointer. Second I return the index of the smallest item, not it's value, then I swap it with the first element in list. And then I call the sorting for the list starting with another element (the left parameter), because I know that the list up to left-1 is already sorted.
A fully recursive solution:
To sort an array, find the smallest element and swap it to the first position. Then sort the rest of the array, until there is a single element left.
To find the smallest element in an array, take the smallest of -the first element and -the smallest element in the rest of the array, until there is a single element left.
int SmallestIndex(int Array[], int From, int To)
{
if (From == To-1)
return From; // Single element left
// Index of the smallest in the rest
int Index= SmallestIndex(Array, From + 1, To);
// Index of the smallest
return Array[From] < Array[Index] ? From : Index;
}
void Sort(int Array[], int From, int To)
{
if (From == To-1)
return; // Single element left
// Locate the smallest element
int Index= SmallestIndex(Array, From, To);
// Swap it to the first place
int Swap= Array[Index]; Array[Index]= Array[From]; Array[From]= Swap;
// Sort the rest
Sort(Array, From + 1, To);
}
Call Sort with (Array, 0, N).
You can use this snippet to sort an array using recursion. It's not difficult you need to think like this way if your array length is N recursion sort N - 1 length array and you have to sort only one element that is N or you can say the last element. I give you an example it will help you suppose you have to sort this array = [50, 40, 10, 30, 20] if recursion gives you array = [10,30,40,50,20] this array you just need to place 20 in a correct position to sort the array.
private static void sort(int[] array, int length) {
if (length == 1) return;
sort(array, length - 1);
var lastIndex = length - 1;
for (int index = lastIndex; index > 0; index --){
if (array[index] < array[index - 1]){
int temp = array[index];
array[index] = array[index - 1];
array[index - 1] = temp;
}
}
}
I'm not looking to copy a qsort algorithm. I'm practicing writing qsort and this is what I've come up with and I'm interested in what part of my code is wrong. Please don't tell me that this is homework cause I could just use the code in the link below.
Reference: http://xoax.net/comp/sci/algorithms/Lesson4.php
When this runs I get this in the console:
Program loaded.
run
[Switching to process 10738]
Running…
Current language: auto; currently c++
Program received signal: “EXC_ARITHMETIC”.
void myQSort(int min, int max, int* myArray)
{
// Initially find a random pivot
int pivotIndex = rand() % max;
int pivot = myArray[pivotIndex];
int i = 0 , j = max-1;
// Pointer to begining of array and one to the end
int* begin = myArray;
int* end = &myArray[max-1];
// While begin < end
while( begin < end )
{
// Find the lowest bound number to swap
while( *begin < pivot )
{
begin++;
}
while( *end > pivot )
{
// Find the highest bound number to swap
end--;
}
// Do the swap
swap(begin,end);
}
// Partition left
myQSort(0, pivotIndex-1, myArray);
// Partiion right
myQSort(pivotIndex+1,max, myArray);
}
EDIT--
Code for Swap:
void swap(int* num, int* num2)
{
int temp = *num;
*num = *num2;
*num2 = temp;
}
// sort interval [begin, end)
void myQSort(int* begin, int* end)
{
if(end - begin < 2)
return;
int* l = begin;
int* r = end - 1;
// Initially find a random pivot
int* pivot = l + rand() % (r - l + 1);
while(l != r)
{
// Find the lowest bound number to swap
while(*l < *pivot) ++l;
while(*r >= *pivot && l < r) --r;
// Do the swap
if(pivot == l) { pivot = r; }
std::swap(*l, *r);
}
// Here l == r and numbers in the interval [begin, r) are lower and in the interval [l, end) are greater or equal than the pivot
// Move pivot to the position
std::swap(*pivot, *l);
// Sort left
myQSort(begin, l);
// Sort right
myQSort(l + 1, end);
}
You're not using the min parameter in your code, anywhere. You need to set begin and your pivot value using that.
I tried working out the codes above. But, they don't compile.
#Mihran: Your solution is correct algorithmically but the following line generates an error:
myQSort(min, begin - myArray, myArray);
This is because begin is of type int* and myArray is of type long, following which the compiler shows this error message:
implicit conversion loses integer precision
Here's a working solution in C++:
#include <iostream>
using namespace std;
void mySwap(int& num1, int& num2){
int temp = num1;
num1 = num2;
num2 = temp;
}
void myQsort(int myArray[], int min, int max){
int pivot = myArray[(min + max) / 2];
int left = min, right = max;
while (left < right) {
while (myArray[left] < pivot) {
left++;
}
while (myArray[right] > pivot) {
right--;
}
if (left <= right) {
mySwap(myArray[left], myArray[right]);
left++;
right--;
}
}
if (min < right) {
myQsort(myArray, min, right);
}
if (left < max) {
myQsort(myArray, left, max);
}
}
int main()
{
int myArray[] = {1, 12, -5, 260, 7, 14, 3, 7, 2};
int min = 0;
int max = sizeof(myArray) / sizeof(int);
myQsort(myArray, min, max-1);
for (int i = 0; i < max; i++) {
cout<<myArray[i]<<" ";
}
return 0;
}
Here's a clear C++ implementation, for reference:
#include <iostream>
#include <vector>
using namespace std;
int partition(std::vector<int>& arr, int low, int high) {
// set wall index
int wall_index = low;
int curr_index = low;
int pivot_elem = arr[high]; // taking last element as pivot_element
// loop through the entire received arr
for (int i = curr_index; i < high; ++i) {
// if element is less than or equal to pivot_elem
// swap the element with element on the right of the wall
// i.e swap arr[i] with arr[wall_index]
if (arr[i] <= pivot_elem) {
// swap
int temp = arr[wall_index];
arr[wall_index] = arr[i];
arr[i] = temp;
// move the wall one index to the right
wall_index++;
curr_index++;
} else {
// if the element is greater than the pivot_element
// then keep the wall at the same point and do nothing
curr_index++;
}
}
// need to swap the pivot_elem i.e arr[high] with the element right of the wall
int temp = arr[wall_index];
arr[wall_index] = arr[high];
arr[high] = temp;
return wall_index;
}
void quick_sort(std::vector<int>& arr, int low, int high) {
if (low < high) { // element with single arr always have low >= high
int split = partition(arr, low, high);
quick_sort(arr, low, split-1);
quick_sort(arr, split, high);
}
}
int main() {
std::vector<int> data = {6,13,8,4,2,7,16,3,8};
int N = data.size();
quick_sort(data, 0, N-1);
for (int i : data) {
cout << i << " ";
}
return 0;
}
I don't see a clean implementation of Quicksort on SO, so here is my easy to understand implementation
PLEASE DONT USE IN PRODUCTION CODE
This is only for your understanding
// Swap position a with b in an array of integer numbers
void swap(int *numbers, int a, int b){
int temp = numbers[a];
numbers[a] = numbers[b];
numbers[b] = temp;
}
static int partition(int *data, int low, int high) {
int left = low, right = high, pivot = data[low];
while (left < right) {
// Everthing on the left of pivot is lower than the pivot
while ((left <= right) && data[left] <= pivot) // <= is because left is the pivot initially
left++;
// Everything on the right of the pivot is greater than the pivot
while((left <= right) && data[right] > pivot)
right--;
if (left < right)
swap(data, left, right);
}
// Put the pivot in the 'rigthful' place
swap(data, low, right);
return right;
}
// Quicksort
static void quick_sort(int *numbers, int low, int high)
{
if (high > low) {
int p_index = partition(numbers, low, high);
quick_sort(numbers, low , p_index - 1);
quick_sort(numbers, p_index + 1, high);
}
}