Bubble Sort Using Slides instead of swaps - c++

currently I'm being asked to design four sorting algorithms (insertion, shell, selection, and bubble) and I have 3 of the 4 working perfectly; the only one that isn't functioning correctly is the Bubble Sort. Now, I'm well aware of how the normal bubble sort works with using a temp var to swap the two indexes, but the tricky part about this is that it needs to use the array index[0] as a temp instead of a normal temp, which is used in swapping, and slide the lower array variables down to the front of the list and at the end of the pass assign the last index to the temp which is the greatest value.
I've been playing around with this for a while and even tried to look up references but sadly I cannot find anything. I'm hoping that someone else has done this prior and can offer some helpful tips. This is sort of a last resort as I've been modifying and running through the passes with pen and paper to try and find my fatal error. Anyways, my code is as follows...
void BubbleSort(int TheArray[], int size)
{
for (int i = 1; i < size + 1; i++)
{
TheArray[0] = TheArray[i];
for (int j = i + 1; j < size; j++)
{
if (TheArray[j] > TheArray[0])
TheArray[0] = TheArray[j];
else
{
TheArray[j - 1] = TheArray[j];
}
}
TheArray[size- 1] = TheArray[0];
}
}
Thanks for any feedback whatsoever; it's much appreciated.

If I understand the problem statement, I think you're looking for something along these lines :
void BubbleSort(int theArray[], int size)
{
for (int i = 1; i < size + 1; i++)
{
theArray[0] = theArray[1];
for (int j = 1; j <= size + 1 - i; j++)
{
if (theArray[j] > theArray[0])
{
theArray[j-1] = theArray[0];
theArray[0] = theArray[j];
}
else
{
theArray[j - 1] = theArray[j];
}
}
theArray[size-i+1] = theArray[0];
}
}
The piece that you're code was missing, I think, was that once you find a new maximum, you have to put it back in the array before placing the new maximum in theArray[0] storage location (see theArray[j-1] = theArray[0] after the compare). Additionally, the inner loop wants to run one less each time since the last element will be the current max value so you don't want to revisit those array elements. (See for(int j = 1 ; j <= size + 1 - i ; j++))
For completeness, here's the main driver I used to (lightly) test this :
int main()
{
int theArray[] = { 0, 5, 7, 3, 2, 8, 4, 6 };
int size = 7;
BubbleSort(theArray, size);
for (int i = 1; i < size + 1; i++)
cout << theArray[i] << endl;
return 0;
}

Related

Class Function that Inserts values into a sorted array without ruining the order

So I am really confused on the logic here, I get the general Idea of taking my values in 1 by 1 and comparing them to the elements in the array. If the value is larger move on to the next element, if the value is smaller or equal to the element move over all the elements over 1 index and replace the original index with your value. My problem is I cant get that last part into code and I have been sitting here stooped for half an hour. Here is what I have gotten so far.
void SortedArray::insertVal(int val)
{
//check for size == capacity
// if so, use .Expand function to double array capacity, then continue to below.
//if not continue
//here is where I am having my issues because I cant get the logic down.
for (int i = 0; i < capacity; i++)
{
if (val > arr[i])
arr[i] = arr[i + 1];
else if (val <= arr[i])
{
for (int x = 0; x < capacity; x++)
{
int temp = arr[i+1];
arr[i + 1] = arr[i];
//right about here I realized If I just assign temp to arr[1+2] the value of that index is lost.
}
}
}
}
I am just stooped, I wanted to check here and see if anyone can help before I have to contact my professor for help as a last resort.
Thanks in advance for anything :)
If I understood what you want, reading the array backwards should solve the problem.
for (int i = 0; i < capacity; i++)
{
if (val > arr[i])
{
for(int x = capacity - 1; x > i; x--)
{
arr[x] = arr[x - 1];
}
arr[i] = val;
break;
}
}

find the 4 biggest elements of an array by using a simple brute force algorithm

I have an array (myDb) that contains songs and their duration. I need to find the 4 songs with the longest duration by using a brute force algorithm, but I'm kind of too stupid to make it work. First I made a loop to find my longest song like this (works):
CTitle tmp=*myDb.getTitle(0);
for (int i=0; i<=myDb.getNumberofTitles;i++)
{
if (tmp.getDuration()<myDb.getTitle(i+1)->getDuration())
{
tmp=*myDb.getTitle(i+1)
}
}
So this works and I have my longest track saved as my temporary object.
Now I have to search myDb for a title that has this duration and add it into my "playlist" (array of CTitles). Than I have to decrease the duration (integer, represents duration of a track in seconds) by one and search my array for a track that has this duration and add it to my playlist, if there is no one than again decrease duration by one and search again.
It seems to me that i have to do 2 for loops one to go through my array and the other one to decrease my duration, I tried it on every ways I could think of, but it never worked like it had to work. Thats my best attempt for now, but it doesn't stop when my array reached 4 elemtens:
for(int k=tmp.getDuration();k>=0; k--)
{
for (int m=0; m<myDb.getNumberOfTitles();m++)
{
if (myDb.getTitle(m)->getDuration()==k)
{
playlist2.add(myDb.getTitle(m));
}
}
}
playlist2.print();
size_t i;
size_t place;
size_t size = 4;
CTitle tmps[size];
for (i = 0; i < size && i <= myDb.getNumberofTitles; i++) {
tmps[i] = *myDb.getTitle(i);
}
std::sort(tmps, tmps + size, [](const CTitle &a, const CTitle &b) {
return a.getDuration() > b.getDuration();
});
for (i = size; i <= myDb.getNumberofTitles; i++)
{
for (size_t j = 0; j < size; j++) {
if (tmps[j].getDuration() < myDb.getTitle(i + 1)->getDuration()) {
place = j;
for (j = size - 1; j > place; j--) {
tmps[j] = tmps[j - 1];
}
tmps[place] = *myDb.getTitle(i+1);
}
}
}

Selection Sort on an Array of Objects

Looked around online, but haven't been able to find anything concerning this.
I'm in a C++ introductory class and have a project that is dealing with Arrays of Objects. An object (called media) has a name and a rating. I have three different media objects put into an media object array. I need to find a way to sort them by name. I was given code for selection sort for c-strings, but haven't been able to figure out what exactly to do with this to change it over to dealing with the media objects. Here is my selection sort for the c-strings.
void selectsort(char str[][20], int N)
{
int pass, j, min;
char temp[20];
for (pass = 0; pass <= N - 2; pass++) // passes
{
min = pass;
for (j = pass + 1; j < N; j++) // in each pass
if (strcmp(str[min], str[j]) > 0)
min = j;
strcpy(temp, str[min]);
strcpy(str[min], str[pass]);
strcpy(str[pass], temp);
}
}
I have gotten rid of strcmp by overloading < with
int media::operator<(media med)
{
return strcmp(mname, med.mname);
}
and strcpy by overloading = with
void media::operator=(media med)
{
strcpy(mname, med.mname);
}
I believe that this would return the same results, yes?
So here is my code so far (have just been throwing myself at it non-understanding of how to do it).
void selsort(media mry[], int n) // mry[] is the object array, n is the
// number of objects in the array
{
int pass, j, min;
media temp[1];
for (pass = 0; pass <= n - 2; pass++) // passes
{
min = pass;
for (j = pass + 1; j < n; j++) // in each pass
if ((mry[min] < mry[j]) < 0)
min = j;
temp = mry[min];
mry[min] = mry[pass];
temp = mry[min];
}
}
I understand that there are a lot of flaws in this code. The temp comparison doesn't work and when I try to get it to using *temp or temp[0] (trying everything under the sun over here) I get corrupted data errors. I can't seem to figure it out though. I've always struggled with understanding sorts, and this just adds insult to injury.
(Also please note that some notations might not be correct, but this is what I was taught in this class and what this professor asks that we code in)
Thanks for any help!
There are 2 things wrong with your code:
media temp[1]; Why would you want your temporary media storage for swapping be an array of 1?
The swapping: temp = mry[min]; mry[min] = mry[pass]; temp = mry[min]; See anything wrong with it?
Here is the adjusted function, which BTW works fine:
void selsort(media mry[], int n) // mry[] is the object array, n is the
// number of objects in the array
{
int pass, j, min;
media temp;
for (pass = 0; pass <= n - 2; pass++) // passes
{
min = pass;
for (j = pass + 1; j < n; j++) // in each pass
if ((mry[min] < mry[j]) < 0)
min = j;
temp = mry[min];
mry[min] = mry[pass];
mry[pass] = temp;
}
}

Insertion sort using pointer to an array

My code is:
#include <iostream>
using namespace std;
void insertion(int*, int);
int main() {
int a[6] = {9, 5, 3, 7, 5, 6};
for (int i = 0; i < 6; i++)
cout << a[i] << " ";
insertion(&a[0], 6);
cout << "now insertion sort \n";
for (int x = 0; x < 6; x++)
cout << a[x] << "\n";
return 0;
}
void insertion(int* l, int m) {
int temp;
for (int i = 0; i < m; i++) {
while (*(l + i) > *(l + 1 + i) && (i > 0)) {
temp = *(l + i);
*(l + i + 1) = *(l + i);
*(l + i) = temp;
i--;
}
}
}
What is wrong with the function sorting?
The output that I'm getting is: 9 5 5 7 7 7
What other details should I add (this is my first doubt in stackoverflow)?
Your logic isn't really correct for an insertion sort. In fact, what you have right now is much closer to a bubble sort (though it's obviously not quite right for that either).
For an insertion sort, the logic goes something like this (assuming 0-based indexing):
for i = 1 to array_length
if array[i] < array[i-1]
temp = array[i]
for j = i downto 1 && temp < array[j-1]
array[j] = array[j-1]
array[j-1] = temp
endif
So the basic idea here is that for each element, we search backwards through the array to find the right place to put that element. As we do so, we shift elements upwards by one spot, so when we got to the right spot, we have a place to put it.
Note, in particular, that this doesn't contain any swap-like code anywhere. We don't normally plan on swapping adjacent elements as you've done. It can/will happen when/if an element happens to be out of place by exactly one position, but it's pretty much incidental when it does.

c++ array can't get the right array

I have Array A[9]= {1,2,3,4,5,6,7,8,9} and I need to delete the numbers which are not dividing by 2. The code I tried to do:
int main()
{
int n;
ifstream fd(Cdf);
fd>>n; // read how many numbers are in the file.
int A[n];
for(int i = 0; i < n; i++)
{
fd >> A[i]; //read the numbers from file
}
for(int i = 0; i < n; i ++) // moving the numbers.
{
if(A[i] % 2 !=0)
{
for(int j = i; j < n; j++)
{
A[i] = A[i+1];
}
}
}
fd.close();
return 0;
}
But I get numbers like 224466888. what I need to do to get 2,4,6,8?
I need to delete numbers in the same array.
First you should use std::vector for dynamic size arrays.
Second, for removing numbers that are even in a vector, you can do :
std::vector<int> inf = {12,0,5,6,8};
auto func = [](int i){return i % 2 != 0;};
inf.erase(std::remove_if(inf.begin(),inf.end(),func), inf.end());
EDIT :
Ok, so you can still do this without std::vectors, but it will be uglier :
#include <algorithm>
int res[] = {2,5,9,8,6,7};
int size = 6;
auto func = [](int i){return i % 2 != 0;};
int new_size = std::remove_if(res,res + size, func) - res;
All the data you want is in [0, new_size[ range, the other part of your array is now garbage.
Your removal loop is indexing with the wrong variable:
for(int j = i; j < n; j++)
{
A[i] = A[i+1];
}
You're using i, which doesn't change in the loop.
Change it to j. You also need to subtract one from the upper limit, as you'd step outside of the array otherwise when accessing A[j + 1].
for(int j = i; j < n - 1; j++)
{
A[j] = A[j + 1];
}
An array can't be used for your purpose. It is allocated on stack and its size can't be changed dynamically (you can't change the size of an array in general, not only when it is allocated on stack).
You could allocate a second array and keep reallocating it with realloc everytime you add a new element but that's not the good way to do it. You are working with C++ so just use a std::vector<int> and your problems will be solved:
std::vector<int> evenArray;
evenArray.reserve(sizeof(A)/sizeof(A[0])/2);
if (number is even) {
evenArray.pushBack(number);
}
Mind that vector stores elements contiguously so this is legal:
int *evenA = &evenArray[0];
For your inner for loop you should be referencing j, not i.
for(int j = i; j < n - 1; j++)
{
A[j] = A[j+1];
}
Otherwise, what's the point of creating j?
Of course, this also means if you read the whole array back you will display all the characters that were shifted (which will just be equal to the last number). So, you should probably keep track of the new length of the array and just iterate to that instead of the end of the array.
EDIT:
In the inner for loop you need to loop to n - 1 otherwise when you have A[j + 1] it will go off the end of the array when you to change it, which may or may not give you a runtime error.