Bubble sort the total number of comparisons and swaps - c++

I have this code for bubble sort in c++. At first it generates random numbers and puts them inside an array. After that I call my bubbleSort function, which does the sorting. Everything works fine. However I was curious how can I find a number of total comparisons and number swapping that bubble sort makes?
I created a CountBubbleSort integer for comparisons. However I'm not sure in which part of my code should I increment it. I was thinking to add it after second for loop, inside first one. Hope you understand what I mean. Is it right or not? Number of comparisons defines this formula n*(n-1))/2. And with swaps it is 3*(n-1). But how can I implement it to my code? Thanks for the help guys.
void swap(double *xp, double *yp)
{
double temp = *xp;
*xp = *yp;
*yp = temp;
}
double *Data;
double* A;
double n, temp;
void generate(int _n, const char *_file);
void read(const char *_file);
void printArray(double arr[], int n);
void bubbleSort(double arr[], int n);
int main()
{
int m;
int CountBubbleSort = 0;
srand(time(NULL));
cout << "Amount of random numbers you want: ";
cin >> m;
cout << "Generating random data ..." << endl;
generate(m, "duom.txt");
cout << "Reading data" << endl;
read("duom.txt");
A = new double[n];
for (int i = 0; i < n; i++) {
A[i] = Data[i];
}
cout << "Randomly generated array" << endl;
printArray(A, n);
// Bubble Sort
bubbleSort(A, n);
cout << "Array after bubble sort" << endl;
printArray(A, n);
return 0;
}
void bubbleSort(double arr[], int n)
{
bool swapped;
for (int i = 0; i < n - 1; i++)
{
swapped = false;
for (int j = 0; j < n - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
swap(&arr[j], &arr[j + 1]);
swapped = true;
}
}
// Should I add CountBubbleSort += i here or not?
if (swapped == false)
break;
}
}
void printArray(double arr[], int n) {
for (int i = 0; i < n; i++) {
cout << A[i] << endl;
}
}

This is a relatively straightforward change:
Increment comparison count before the if statement
Increment the swap counter inside the if statement
Take two int& parameters for the count, like this:
void bubbleSortCounted(double arr[], int n, int& countComparisons, int& countSwaps);
The code incrementing the counters would look like this:
countComparisons++;
if (arr[j] > arr[j + 1])
{
countSwaps++;
swap(&arr[j], &arr[j + 1]);
swapped = true;
}
The call from the main() would look like this:
int cmp = 0, swp = 0;
bubbleSort(A, n, cmp, swp);
std::cout << cmp << " comparisons, " << swp << " swaps" << std::endl;

However I was curious how can I find a number of total comparisons and number swapping that bubble sort makes? I created a CountBubbleSort integer for comparisons. However I'm not sure in which part of my code should I increment it.
There's exactly one line in your bubbleSort() function where you actually compare two elements in the array, so it stands to reason that if you want to count the number of times you compare elements, you should increment the counter either immediately before or immediately after the comparison happens.

Related

how to use user input array in heap sorting

I'm a beginner so please excuse me if it is a dumb question.
I am trying to code a heap sort that takes input from user in an array and heap sorts it but i can not find a way to implement user input array in my code.
at the end, in the main function, i have to use array arr[]={} but i either have to define the elements or the number of elements so it creates zeros if i define the array as arr[10]={}
here is the code :
// Heap Sort in C++
#include <iostream>
using namespace std;
void heapify(int arr[], int n, int i) {
// Find largest among root, left child and right child
int largest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < n && arr[left] > arr[largest])
largest = left;
if (right < n && arr[right] > arr[largest])
largest = right;
// Swap and continue heapifying if root is not largest
if (largest != i) {
swap(arr[i], arr[largest]);
heapify(arr, n, largest);
}
}
// main function to do heap sort
void heapSort(int arr[], int n) {
// Build max heap
for (int i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i);
// Heap sort
for (int i = n - 1; i >= 0; i--) {
swap(arr[0], arr[i]);
// Heapify root element to get highest element at root again
heapify(arr, i, 0);
}
}
// Print an array
void printArray(int arr[], int n) {
for (int i = 0; i < n; ++i)
cout << arr[i] << " ";
cout << "\n";
}
// Driver code
int main() {
int arr[10] = { };
cout << "Enter the numbers : " << endl;
for (int x = 1; x <= 5; x++)
{
cin >> arr[x];
}
int n = sizeof(arr) / sizeof(arr[0]);
heapSort(arr, n);
cout << "Sorted array is \n";
printArray(arr, n);
}
here is the output :
code output image
You can consider std::vector and pass it by reference to your heapify(...) to save memory.

How to combine insertion sort and merge sort to make it more efficient in c++ [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
#include<iostream>
#include<stdio.h>
#include<time.h>
using namespace std;
#define ARRAYLENGTH 40
void InsertionSort(int * nums, int arrayLength);
void MergeSort(int * numlist1, int p, int r);
void Merge(int * numsl, int p, int q,int r);
void main(int argc, char* argv[])
{
int nums1[ARRAYLENGTH],numsl[ARRAYLENGTH];
for (int i = 0; i < ARRAYLENGTH; i++)
{
nums1[i] = rand() % 10000;
}
cout << "arraylength = " << ARRAYLENGTH << endl;
cout << "Before Sorting" << endl;
for (int i = 0; i < ARRAYLENGTH; i++)
{
cout << nums1[i] << "\t";
}
cout << endl;
clock_t startTime1 = clock();
InsertionSort(nums1, ARRAYLENGTH);
clock_t endTime1 = clock();
cout << "Running Time for Insertion Sort is " << (endTime1 - startTime1) / 1000 << endl;
for (int i = 0; i < ARRAYLENGTH; i++)
{
cout << nums1[i] << "\t";
}
cout << endl;
cout << "After Insertion Sorting" << endl;
for (int i = 0; i < ARRAYLENGTH; i++)
{
numsl[i] = rand() % 10000;
}
clock_t startTime2 = clock();
MergeSort(numsl, 0, ARRAYLENGTH-1);
clock_t endTime2 = clock();
cout << "Running Time for Merge Sort is " << (endTime2 - startTime2) / 1000 << endl;
for (int i = 0; i < ARRAYLENGTH; i++)
{
cout << numsl[i] << "\t";
}
cout << endl;
cout << "After Merge Sorting" << endl;
getchar();
}
this's the code for main function
void InsertionSort(int * numList, int arrayLength)
{
// your code here
int i,j,key;
for (j=1;j<arrayLength;j++)
{
key=numList[j];
i=j-1;
while(i>=0 && numList[i]>key)
{numList[i+1]=numList[i];
i=i-1;
}
numList[i+1]=key;
}
}
//this is the code of insertion sort
void MergeSort(int * numList, int p, int r)
{
if(p<r)
{
int q=(p+r)/2;
MergeSort(numList,p,q);
MergeSort(numList,q+1,r);
Merge(numList,p,q,r);
}
}
void Merge(int * numsl, int p, int q,int r)
{
int n1 = q - p + 1;
int n2 = r - q;
int * nums1 = (int *)malloc(sizeof(int) * (n1+1));
int * nums2 = (int *)malloc(sizeof(int) * (n2+1));
// your code here
int i,j,k;
for(i=0;i<n1;i++)
nums1[i]=numsl[p+i];
for(j=0;j<n2;j++)
nums2[j]=numsl[q+j+1];
nums1[n1]=10000;
nums2[n2]=10000;
i=0;
j=0;
for(k=p;k<=r;k++)
{
if (nums1[i]<=nums2[j])
{numsl[k]=nums1[i];
i=i+1;}
else
{numsl[k] = nums2[j];
j=j+1;}
}
How to make the new combined algorithm using merge sort firstly then when have been divided in some degree using insertion sort, and how to find the array length N?as is known to all, in small numbers, insertion sort is faster than merge sort, when it comes to large numbers, merge sort is much faster, I am thinking to make a combination of those two to make it more efficient? Specifically, to merge sort can be break down into divide and merge, I am considering when dividing in some level, using insertion sort , but I have trouble to how to find the level in which switch to insertion sort and how to implement it.
Example code. I changed r to be the ending index (last + 1).
void MergeSort(int * numList, int p, int r)
{
int n = r-p;
if(n < 2)
return;
if(n <= 32){ // 16 to 128 are reasonable values
InsertionSort(numList, n)
return;
}
int q=(p+r)/2;
MergeSort(numList,p,q);
MergeSort(numList,q,r);
Merge(numList,p,q,r);
}
With the change to r, the calling code would be:
MergeSort(array, 0, sizeof(array)/sizeof(array[0]));
If performance is the goal, a bottom up merge sort is slightly faster. Most libraries use some variation of a hybrid insertion + bottom up merge sort. Top down merge sort is mostly used for educational purposes.

Obtaining Large Signed Value in my QuickSort/InsertionSort Algorithm

so my code is essentially working; however, I need clarification as to why when I implement insertion sort when I get to less than 20 elements in a subarray it adds a large signed value at the end when I print them out.
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
void swap(int* a, int* b)
{
int t = *a;
*a = *b;
*b = t;
}
int partitionMiddle (int arr[], int low, int high) {
int pivot = arr[high];
int i = (low - 1);
for (int j = low; j <= high- 1; j++)
{
if (arr[j] <= pivot)
{
i++; // increment index of smaller element
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
return (i + 1);
}
void chooseMiddle....
void chooseMedian{code here...}
void insertionSort(int arr[], int low, int high){
int j;
for(int i = low+1; i <= high; i++){
j = i;
while(j>low && arr[j-1]> arr[j]){
swap(arr[j], arr[j-1]);
j= j-1;
}
}
}
void quickSortMiddle(int arr[], int low, int high)
{
int pi = partitionMiddle(arr, low, high);
if (high-low > 20)
{
quickSortMiddle(arr, low, pi - 1);
quickSortMiddle(arr, pi + 1, high);
}
else {
insertionSort(arr, low, pi);
insertionSort(arr, pi+1, high);
}
}
void printArray(int arr[], int size)
{
int i;
for (i=0; i < size; i++)
printf("%d ", arr[i]);
}
int main()
{
clock_t x, k;
x = clock();
int arr[10000];
srand((unsigned)time(0));
for(int i =0; i<10000; i++) {
arr[i] = (rand()%100)+1;
}
int n = sizeof(arr)/sizeof(arr[0]);
cout << "Original array: " ;
printArray(arr, n);
cout << endl;
cout << "With Insertion Sort & Middle Element";
chooseMiddle(arr, 0, n-1);
quickSortMiddle(arr, 0, n-1);
cout << endl;
k = clock();
// can comment this one vvvv or the previous one out to try them both
cout << "With Insertion Sort & Median Element";
chooseMedian(arr, 0, arr[((n-1)/2)], n-1);
quickSortMiddle(arr, 0, n-1);
cout << endl;
k = clock();
printf("Sorted array: ");
printArray(arr, n);
cout << endl;
cout << "CPU Time : ";
cout << k-x;
cout << endl << endl;
return 0;
}
My expected results were to not just have -272632368 at the very end of my sorted array when I print it out. I think I went out of bounds in my insertion sort algorithm but I'm not sure as to where. Maybe someone with a better eye can catch it.
**** EDIT...So I went to debug the code on my own and it the number was appearing there somehow having to do with the n-1 parameter when I was calling the chooseMedian/chooseMiddle or quickSortMiddle functions. I changed it to simply being 'n'. I don't get why, but it's working now. If someone can explain why, that'd be helpful, but if not, that's okay too.
****EDIT2...So now that I have your attention, can you please explain to me why using pointers in the swap function is better than not? I found this example of a swap function online and don't know why they used pointers.

Getting a weird negative number in my output when using an array I modified in one function, in another function

I am writing a program that takes a user-inputted list of up to 25 integers, then prints the sorted list using bubble sorting, the sorted list in descending order, and some other info about the list like the median, minimum and maximum, and mode.
I have tested all of my functions within the program individually on an array I created using initializer lists (not from user input/cin) and they work fine, but when I run the program something is off. For example, when I input 1,2,3,4, the function that prints the sorted list in descending order prints 3,2,1, -858993460. It always leaves out the greatest integer and adds on -858993460 at the end no matter what values I put into the input array. Here's the relevant part of my code:
#include <iostream>
using namespace std;
void input(int ulist[26], int& n);
void Bubblesort(int ulist[26], int slist[26], int n);
void print(int list[26], int n);
int n;
void reversesort(int slist[26], int n);
void main()
{
int ulist[26], slist[26];
input(ulist, n);
cout << "Unsorted";
print(ulist, n);
cout << "Sorted";
Bubblesort(ulist, slist, n);
print(slist, n);
reversesort(slist, n);
cin >> n;
}
void input(int ulist[26], int& n)
{
int i(0), value;
cout << "enter value : \n";
cin >> value;
while (i < 25 && value != -999)
{
ulist[i] = value;
i++;
if (i < 25)
{
cin >> value;
}
}
n = i;
}
void Bubblesort(int ulist[26], int slist[26], int n)
{
int i, j, temp;
for (i = 0; i < n; i++)
slist[i] = ulist[i];
for (j = 25 - 1; j > 0; j--) //25 is Length of the array
for (i = 0; i < j; i++)
if (slist[i] > slist[i + 1])
{
temp = slist[i];
slist[i] = slist[i + 1];
slist[i + 1] = temp;
}
}
void print(int list[26], int n)
{
int i;
cout << " list of numbers are : \n";
for (i = 0; i < n; ++i)
{
cout << list[i] << '\n';
}
cout << "\n\n";
}
void reversesort(int slist[26], int n) //checked w online compiler, works
{
cout << "List of numbers in descending order is: \n";
for (int i = n - 1; i >= 0; --i)
cout << slist[i] << ", ";
cout << "\n";
}
I'm assuming this is some sort of memory problem and that the source of this has to do with passing slist, which was modified in the bubblesort function, through the functions I wrote. I'm pretty new to C++ (coming from python) so I'm assuming I'm missing something as far as passing arrays to functions is concerned.
EDIT: I guess to sum everything up - how can I take the data inputted in the input function and use that array in another function? And how can I take the array that has been sorted by the bubblesort function and use that array in another function?
The first instance of undefined behavior in your code is
if (slist[i] > slist[i + 1])
in Bubblesort.
Due to
for (j = 25 - 1; j > 0; j--)
for (i = 0; i < j; i++)
the maximum index accessed by this loop is slist[24] (24 from i + 1 where i < j and j = 25 - 1 = 24, so i = 23).
Your input is only 4 numbers, so only slist[0] through slist[3] are initialized. The remaining elements (slist[4] through slist[25]) are uninitialized. Reading from an uninitialized variable has undefined behavior.

FirstChance Exception StackOverFlow Merge Sort Shell Sort Bubble Sort

Hey guys I'm working on some sorts and am trying to implement a bubble sort, a merge sort, and a shell sort. I use an outdated technique but I was wondering if you guys could let me know why I keep getting the following error:
First-chance exception at 0x01135EF7 in sortApplication2.exe: 0xC00000FD: Stack overflow (parameters: 0x00000000, 0x00542000).
Unhandled exception at 0x01135EF7 in sortApplication2.exe: 0xC00000FD: Stack overflow (parameters: 0x00000000, 0x00542000).
I am using Visual Studio 2012 if that plays any part. My code is in three different files so I'll post each separately.
My header file:
#pragma once
class sort
{
public:
sort();
void random1(int array[]);
void random2(int array[]);
void random3(int array[]);
void bubbleSort(int array[], int length);
/*void merge(int *input, int p, int r);
void merge_sort(int *input, int p, int r);*/
void shellSort(int array[], int length);
};
My class implementation file:
#include "sort.h"
#include <time.h>
#include <iostream>
using namespace std;
sort::sort()
{}
void sort::random1(int array[])
{
// Seed the random-number generator with current time so that
// the numbers will be different every time the program runs.
for(int i = 0; i < 25; i++)
{
srand ((unsigned) time(NULL));
int n = rand(); //generates a random number
array[i] = n; //places it into the array
}
}
void sort::random2(int array[])
{
// Seed the random-number generator with current time so that
// the numbers will be different every time the program runs.
for(int i = 0; i < 10000; i++)
{
srand ((unsigned) time(NULL));
int n = rand(); //generates a random number
array[i] = n; //places it into the array
}
}
void sort::random3(int array[])
{
// Seed the random-number generator with current time so that
// the numbers will be different every time the program runs.
for(int i = 0; i < 100000; i++)
{
srand ((unsigned) time(NULL));
int n = rand(); //generates a random number
array[i] = n; //places it into the array
}
}
void sort::bubbleSort(int array[], int length)
{
//Bubble sort function
int i,j;
for(i = 0; i < 10; i++)
{
for(j = 0; j < i; j++)
{
if(array[i] > array[j])
{
int temp = array[i]; //swap
array[i] = array[j];
array[j] = temp;
}
}
}
}
/*void sort::merge(int* input, int p, int r) //the merge algorithm of the merge sort
{
int mid = (p + r) / 2;
int i1 = 0;
int i2 = p;
int i3 = mid + 1;
// Temp array
int x = r -p + 1;
int *temp;
temp = new int [x];
// Merge in sorted form the 2 arrays
while ( i2 <= mid && i3 <= r )
if ( input[i2] < input[i3] )
temp[i1++] = input[i2++];
else
temp[i1++] = input[i3++];
// Merge the remaining elements in left array
while ( i2 <= mid )
temp[i1++] = input[i2++];
// Merge the remaining elements in right array
while ( i3 <= r )
temp[i1++] = input[i3++];
// Move from temp array to master array
for ( int i = p; i <= r; i++ )
input[i] = temp[i-p];
}
void sort::merge_sort(int *input, int p, int r) //the merge sort algorithm
{
if ( p < r ) //When p and r are equal the recursion stops and the arrays are then passed to the merge function.
{
int mid = (p + r) / 2;
merge_sort(input, p, mid); //recursively calling the sort function in order to break the arrays down as far as possible
merge_sort(input, mid + 1, r);//recursively calling the sort function in order to break the arrays down as far as possible
merge(input, p, r); //merge function realigns the smaller arrays into bigger arrays until they are all one array again
}
}*/
void sort::shellSort(int array[], int length) //Shell sort algorithm
{
int gap, i, j, temp;
for( gap = length / 2; gap > 0; gap /= 2) //gap is the number of variables to skip when doing the comparisons
{
for( i = gap; i < length; i++) //This for loop sets the variable to use as the gap for the comparisons
{
for (j = i - gap; j >= 0 && array[j] > array[j + gap]; j -= gap)
{
temp = array[j]; //the array variables are swapped
array[j] = array[j + gap];
array[j + gap] = temp;
}
}
}
}
And my driver file:
#include "sort.h"
#include <iostream>
using namespace std;
int main()
{
int bubbleArray1[25]; //these are the arrays to be sorted. three for each sort. each has a length of 25, 10000, or 100000.
int bubbleArray2[10000];
int bubbleArray3[100000];
int mergeArray1[25];
int mergeArray2[10000];
int mergeArray3[100000];
int shellArray1[25];
int shellArray2[10000];
int shellArray3[100000];
sort Sorts;
Sorts.random1(bubbleArray1);
Sorts.random1(mergeArray1);
Sorts.random1(shellArray1);
Sorts.random2(bubbleArray2);
Sorts.random2(mergeArray2);
Sorts.random2(shellArray2);
Sorts.random3(bubbleArray3);
Sorts.random3(mergeArray3);
Sorts.random3(shellArray3);
cout << "BubbleSort1 is now being sorted.\n";
Sorts.bubbleSort(bubbleArray1, 25);
cout << "BubbleSort2 is now being sorted.\n";
Sorts.bubbleSort(bubbleArray2, 10000);
cout << "BubbleSort3 is now being sorted.\n";
Sorts.bubbleSort(bubbleArray3, 100000);
cout << "End bubble sorts.\n";
/*cout << "MergeSort1 is now being sorted.\n";
Sorts.merge_sort(mergeArray1, 0, 25);
cout << "MergeSort2 is now being sorted.\n";
Sorts.merge_sort(mergeArray2, 0, 10000);
cout << "MergeSort3 is now being sorted.\n";
Sorts.merge_sort(mergeArray3, 0, 100000);
cout << "End merge sorts.\n";*/
cout << "ShellSort1 is now being sorted.\n";
Sorts.shellSort(shellArray1, 25);
cout << "ShellSort1 is now being sorted.\n";
Sorts.shellSort(shellArray2, 10000);
cout << "ShellSort1 is now being sorted.\n";
Sorts.shellSort(shellArray3, 100000);
cout << "End shell sorts.\n";
cout << "Array\tElements\n";
cout << "BubbleSort1\t";
for(int i = 0; i < 25; i++)
{
cout << bubbleArray1[i] << " ";
}
cout << "\nMergeArray1\t";
for(int i = 0; i < 25; i++)
{
cout << mergeArray1[i] << " ";
}
cout << "\nShellArray1\t";
for(int i = 0; i < 25; i++)
{
cout << shellArray1[i] << " ";
}
return 0;
}
I know it's a lot of code. And there are probably many ways I could make the code better.
I would just like to know what's causing the error up above since I can't find it using my compiler.
You are allocating too much memory on the stack. Variables with 'automatic' storage class go on the stack. Allocate heap instead.
So, instead of:
int shellArray3[100000];
Do:
int* shellArray3 = new int[100000];
Or better yet, use std::vector.
If you don't want to use heap memory, you could also use the static storage class for something like this. To do that:
static int shellArray3[100000];
That will allocate one instance of the variable for the whole program rather than allocating a copy for each function entry on the stack.