c++ insertion sort error - c++

When I compile, it gives error of read access violation. Other stack overflow posts says this is due to an infinite loop. I also saw that the value goes to a very large negative number. My guess is that it is because list[-1], but I do not know how to change it so it does not go past list[0].
Insertion sort code
void insertion_sort(int list[], int length) {
for (int i = 1; i < length; i++) {
for (int j = i; (j > 0) && (list[j] < list[j - 1]); j--) {
swap(list, list[j - 1], list[j]);
}
}
}
Swap function code
void swap(int list[], int & src, int & dest){
int temp = list[src];
list[src] = list[dest];
list[dest] = temp;
}

You are using the values of your sort as an index in your swap. Keep it simple.
This works.
void insertion_sort(int list[], int length) {
for (int i = 1; i < length; i++) {
for (int j = i; (j > 0) && (list[j] < list[j - 1]); j--) {
std::swap( list[j - 1], list[j] );
}
}
}
int main( )
{
int arr[ 100 ];
for( size_t i= 0; i < 100; ++i )
arr[ i ]= std::rand( );
insertion_sort( arr, 100 );
return 0;
}
Added:
As this looks like a class exercise. What you want to notice is that std::swap has no idea that your list exists. All it wants to know is what values you want to swap. So if you can't use the standard library, write your swap like the standard.

void insertion_sort(int list[], int length) {
for (int i = 1; i < length; i++) {
j = i;
while(j > 0 && list[j - 1] > list[j]){
swap(list, list[j], list[j-1]);
j--;
}
}
This should work for sorting least to greatest. The while loop does the job of checking if it needs to be swapped and checks the already "sorted" positions in the array if it needs to be swapped again.
Happy Coding.

Related

What is wrong with my merge sort code, I can't figure out?

I'm new to programming. I just recently started studying algorithms.
My code should just carry out the merge sort procedure but it has some errors although it builds correctly.
My code takes input then stops working.
It shows this error:
#include<iostream>
using namespace std;
#define size 10
class mergesort {
public:
mergesort(){}
void merge(int a[]) {
int mid = 5;
if (size < 2) return;
int left[size]; int right[size];
for (int i = 0; i < mid; i++) {
left[i] = a[i];
}
for (int j = mid; j < size-1; j++) {
right[j-mid] = a[j];
}
merge(left);
merge(right);
sort(left, right, a, mid, size-mid);
}
void sort(int left[], int right[], int a[], int L, int R) {
int i = 0; int j = 0; int k = 0;
while (i < L && j < R) {
if (left[i] <= right[j])
{
a[k] = left[i];
k++; i++;
}
else if (right[j] < left[i]) {
a[k] = right[j];
k++; j++;
}
}
while (i < L) {
a[k] = left[i];
k++; i++;
}
while (i < R) {
a[k] = right[j];
k++; j++;
}
}
};
void main() {
mergesort m;
int a[size];
cout << "Enter the elements:" << endl;
for (int i = 0; i < size; i++) {
cin >> a[size];
}
m.merge(a);
}
The stack overflow error is due to an infinite recursion "loop".
merge() needs two more parameters. In this example, I allocated from stack using _alloca(), so no free is needed. This will only work for arrays small enough to not overflow the stack. The alternative is to use malloc() and free().
void merge(int a[], int lo, int hi) // hi is end == last + 1
{
if((hi - lo) < 2)
return;
int mid = (lo+hi)/2;
int *left = _alloca((mid - lo)*sizeof(int)); // alloc from stack
int *right = _alloca((hi - mid)*sizeof(int)); // alloc from stack
for (int i = lo; i < mid; i++)
left[i-lo] = a[i];
for (int i = mid; i < hi; i++)
right[i-mid] = a[i];
merge(left, lo, mid);
merge(right, mid, hi);
sort(left, right, a, mid-lo, hi-mid);
}
}
The last while in sort() needs to use j instead of i:
while (j < R) { // use j here
a[k] = right[j];
k++; j++;
}
Alternative approach - use a one time helper function to do a one time allocation of a second array the same size as a[], perhaps calling it b[], and use the same indexing for b[] as a[] when doing the splitting and merging. b[] would be passed as a parameter to both merge() and sort(), and would be used instead of left[] and right[].
The names are confusing, merge() is really a "sort", and sort() is really a "merge".

Calling a sort function on an array c++

I am using an insertion sort function to sort a 5000 int ascending array. when i pass the array's address to the function call, i get [Error] name lookup of 'i' changed for ISO 'for' scoping [-fpermissive]. Maybe I should use a vector but I am unfamiliar with them. Maybe I coded something wrong?
#include <iostream>
#define SIZE 5000 //array size
using namespace std;
void insertionSort(int arr[], int length) {
int i, j, tmp;
for (i = 1; i < length; i++) {
j = i;
while (j > 0 && arr[j - 1] > arr[j]) {
tmp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = tmp;
j--;
}
}
}
int main() {
int a[SIZE];
int count = 1;
for(int i=0; i<SIZE; i++) {
a[i] = count;
count++;
}
for(int i = 0; i < SIZE; i++) {
printf("%d\t", a[i]);
}
insertionSort(&a[i], SIZE);
}
You probably want to call
insertionSort(a, SIZE)
// insertionSort(&a[i], SIZE); Here you haven't declared i in funciton main(), only in your for loop. And the call to insertionSort is outside of your loop.
Passing (&a)[0] and a mean the same thing.

C++ Crashing in mergesort Function

For some reason, my program keeps crashing while it's in this mergeSort function which has a purpose just to merge sort an array of data. In this case, I'm using an array of strings.
Here is the merge sort function code:
template <class T>
void Metrics<T>::mergeSort(T *arr, int n)
{
if ( n < 10 )
{
insertionSort(arr,n);
return;
}
int mid = n / 2;
int mid2 = n - mid;
T *Left = new T[mid];
T *Right = new T[mid2];
for ( int i = 0; i < mid; i++ )
{
Left[i] = arr[i];
}
for ( int i = 0; i < mid2; i++ )
{
Right[i] = arr[mid+i];
}
mergeSort(Left, mid);
mergeSort(Right,mid);
merge(Left,mid,Right,mid2,arr);
delete Left;
delete Right;
}
and Here is the merge function used in the mergeSort function:
template <class T>
void Metrics<T>::merge(T *a, int numA, T *b, int numB, T *c)
{
int i, j, k;
i = j = k = 0;
while ( i < numA && j < numB )
{
if (a[i] <= b[j])
{
c[k] = a[i];
i++;
k++;
}
else
{
c[k] = b[j];
j++;
k++;
}
}
while ( i < numA )
{
c[k] = a[i];
i++;
k++;
}
while ( j < numB )
{
c[k] = b[j];
j++;
k++;
}
}
The initial parameters I'm sending into the mergeSort function is just an array of strings, and the int n is 36. Oh and by the way, the insertion sort code is this:
template <class T>
void Metrics<T>::insertionSort(T *arr, int n)
{
for ( int i = 1; i < n; i++ )
{
int j = i;
while ( j > 0 && arr[j] < arr[j-1] )
{
T temp = arr[j];
arr[j] = arr[j-1];
arr[j-1] = temp;
j--;
}
}
}
I'm pretty sure it has to do with the fact that I'm sending in an array of strings into the function. It works when it's just with integers and characters though. Thanks!
EDIT:: After looking into it a little bit, I think it crashes on the "Delete Left" and "Delete Right" code on the bottom of mergeSort. Is there a reason for that? How can I fix it? Is that why it's crashing?
You should be using delete [] Left and delete [] Right to match the new [] calls.
Also you call to mergeSort(Right,mid); should be mergeSort(Right,mid2); but I don't think that would cause a crash, just a non-sorted item when n was odd.

shell sort pseudocode to C++ code

# Sort an array a[0...n-1].
gaps = [701, 301, 132, 57, 23, 10, 4, 1]
foreach (gap in gaps)
# Do an insertion sort for each gap size.
for (i = gap; i < n; i += 1)
temp = a[i]
for (j = i; j >= gap and a[j - gap] > temp; j -= gap)
a[j] = a[j - gap]
a[j] = temp
this is the pseudocode in Wikipedia page.
I'm not sure about that if my c++ code is correct according to it. Here is my code:
void shellSort(int *array, int array_size)
{
int e, i, j, temp;
for(e = 0; e < array_size; e++)
{
for( i = e; i < array_size; i++)
{
temp = array[i];
for( j = i; j >= e && array[j - e] > temp; j -= e)
{
array[j] = array[j-e];
}
array[j] = array[temp];
}
}
}
And here is my test code:
int main()
{
int sizes[9] = {9,3,5,7,1,0,6,2,4};
int size = 0;
shellSort(sizes,size);
for(int i=0;i<size;i++)
{
cout << sizes[i] << endl;
}
return 0;
}
but it shows nothing on the screen.
Okay, let's take this from the top
void shellSort(int *array, int array_size)
{
Your code completely omitted the needed gaps array
const int gaps[] = {701, 301, 132, 57, 23, 10, 4, 1};
int e, i, j, temp;
The outer loop needs to be across gaps rather than 0 to array_size
for(e = 0; e < sizeof(gaps)/sizeof(int); ++e)
{
int gap = gaps[e];
You need to use the gap from the gaps array in the inner loop
for( i = gap; i < array_size; ++i)
{
temp = array[i];
for( j = i; j >= gap && array[j - gap] > temp; j -= gap)
{
array[j] = array[j-gap];
}
You need to store temp back into the array
array[j] = temp;
}
}
}
NB: I don't have a compiler to hand right now, so I haven't checked that, but I think it's right.
Also, a few minor points, this:
int e, i, j, temp;
is bad practice, instead declare each variable as you use it, i.e. do this instead:
for( int i = gap; i < array_size; ++i)
{
int temp = array[i];
For some reason (no comments were given), my first answer was deleted (typo - you set size to 0, not 9). The question wondered why "it shows nothing on the screen". If you set size to 0, what do you expect a for loop to do when it iterates from 0 to < size???
Before looking at the algorithm, your parameters must be correct. Start there. If SOMETHING now gets dumped to the screen, NOW you can start debugging the algorithm (if the output was wrong). If the output is right, then your algorithm is probably okay.
If I am wrong about this, PLEASE POST A COMMENT TO MY ANSWER. Don't just "delete" it!?!

How to get BucketSort algorithm working?

I am trying to create a bucketsort algorithm in C++, but it is not working at all. Every run, it adds many new numbers, often very large, such as in the billions, into the array. Does anyone know why this is? Here is the code - (Note that I am passing in an array of size 100, with random numbers from 0 to ~37000, and that the insertion sort function is fully functional and tested multiple times)
It would be greatly appreciated if someone could point out what's wrong.
void bucketSort(int* n, int k)
{
int c = int(floor(k/10)), s = *n, l = *n;
for(int i = 0; i < k; i++) {
if(s > *(n + i)) s = *(n + i);
else if(l < *(n + i)) l = *(n + i);
}
int bucket[c][k + 1];
for(int i = 0; i < c; i++) {
bucket[i][k] = 0;
}
for(int i = 0; i < k; i++) {
for(int j = 0; j < c; j++) {
if(*(n + i) >= (l - s)*j/c) {
continue;
} else {
bucket[j][bucket[j][k]++] = *(n + i);
break;
}
}
}
for(int i = 0; i < c; i++) {
insertionSort(&bucket[i][0], k);
}
}
This line does not compile. int bucket[c][k + 1];
I think the problem is with you bucket indices. This part here
for(int j = 0; j < c; j++) {
if(*(n + i) >= (l - s)*j/c) {
continue;
} else {
bucket[j][bucket[j][k]++] = *(n + i);
break;
}
}
does not do the equivalent of:
insert n[i] into bucket[ bucketIndexFor( n[i]) ]
First it gets the index off by one. Because of that it also misses the break for the numbers for the last bucket. There is also a small error introduced because the index calculation uses the range [0,l-s] instead of [s,l], which are only the same if s equals 0.
When I write bucketIndex as:
int bucketIndex( int n, int c, int s, int l )
{
for(int j = 1; j <= c; j++) {
if(n > s + (l-s)*j/c) {
continue;
} else {
return j-1;
}
}
return c-1;
}
and rewrite the main part of your algorithm as:
std::vector< std::vector<int> > bucket( c );
for(int i = 0; i < k; i++) {
bucket[ bucketIndex( n[i], c, s, l ) ].push_back( n[i] );
}
I get the items properly inserted into their buckets.