Bubble sort algorithm not working - c++

I am in the process of creating a C++/SFML game engine. Every "entity" in the game has a pointer to it stored in a static vector in the Entity class, called entityRenderList. This vector is sorted by the Bubble Sort algorithm on each iteration of the game loop so that the sprites are drawn in the correct order.
Whenever an entity is deleted, it replaces its pointer in the vector with a NULL pointer. My algorithm should, by default, cause any NULL pointers it finds to be sorted to the back of the vector, where they are subsequently removed.
Here is the code for the sorting algorithm:
bool Entity::depthSortFunction(Entity* a, Entity* b)
{
if (b==NULL) return false; //any NULL values are moved to the back
if (a==NULL) return true;
else return (a->depth_) < (b->depth_);
}
void Entity::sortEntityRenderList()
{
if (entityRenderList.size()>1) {
//Any NULL values are brought to the top to be stripped off.
bool passMade=false;
Entity* temp;
int n=entityRenderList.size()-1;
for(int i=0; i<n; i++)
{
passMade=false;
for(int j=0; j<n-1; j++)
{
if(depthSortFunction(entityRenderList[j],entityRenderList[j+1]))
{
//then swap them
temp = entityRenderList[j+1];
entityRenderList[j+1] = entityRenderList[j];
entityRenderList[j] = temp;
//and then notify the entities of the change
if (entityRenderList[j]!=NULL) {entityRenderList[j]->renderListID=j;}
if (entityRenderList[j+1]!=NULL) {entityRenderList[j+1]->renderListID=j+1;}
passMade=true;
//std::cout<<"Swapping entries "<<j<<" and "<<j+1<<"...\n";
}
}
if (!passMade) {
break; //then it is sorted, as we have not needed to modify the array.
}
}
}
//Now, we strip off any NULL values from the top.
while (!entityRenderList.empty() && entityRenderList.back()==NULL) {
entityRenderList.pop_back(); //strip off last one
}
}
What should be happening is that any NULL pointers are removed from the vector on each run of the algorithm. However, this is not the case, and any NULL pointers stay right where they are, and appear to not be sorted at all.
NB: The passMade boolean is there so that if a pass of the array is made and no swaps were made, the algorithm stops.
Any help would be appreciated. Thanks in advance.
EDIT: The sorting algorithm code is slightly modified from here.

There is a bug in the j loop limit. For example, if the list has 10 elements, n is 9, n-1 is 8, and the largest value of j is 7. The loop can exchange elements 7 and 8 of a 10 element list. It cannot exchange the last pair, elements 8 and 9.
As suggested by a comment, it would be better and simpler to use a library sort that is already tested and working. Rather than adjust the renderListID fields as you go along, you could do them all in a single pass through the list at the end. If you do it after popping the NULL elements, you would not need to test for NULL in that loop.
for(int i=0; i<entityRenderList.size(); i++)
{
entityRenderList[i]->renderListID=i;
}

Related

Removing first three elements of 2d array C++

So here's my problem.. I have a 2d array of 2 char strings.
9D 5C 6S 9D KS 4S 9D
9S
If 3 found I need to delete the first 3 based on the first char.
card
My problem is I segfault almost anything i do...
pool is the 2d vector
selection = "9S";
while(col != GameBoard::pool.size() ){
while(GameBoard::pool[col][0].at(0) == selection.at(0) || cardsRem!=0){
if(GameBoard::pool[col].size() == 1){
GameBoard::pool.erase(GameBoard::pool.begin() + col);
cardsRem--;
}
else{
GameBoard::pool[col].pop_back();
cardsRem--;
}
}
if(GameBoard::pool[col][0].at(0) != selection.at(0)){
col++;
}
}
I've tried a series of for loops etc, and no luck! Any thoughts would save my sanity!
So I've tried to pull out a code segment to replicate it. But I can't...
If I run my whole program in a loop it will eventually throw a segfault. If I run that exact code in the same circumstance it doesn't... I'm trying to figure out what I'm missing. I'll get back in if I figure out exactly where my issue is..
So in the end the issue is not my code itself, i've got memory leaks or something somewhere that are adding up to eventually crash my program... That tends to be in the same method each time I guess.
The safer and most efficient way to erase some elements from a container is to apply the erase-remove idiom.
For instance, your snippet can be rewritten as the following (which is testable here):
using card_t = std::string;
std::vector<std::vector<card_t>> decks = {
{"9D", "5C", "6S", "9D", "KS", "4S", "9D"},
{"9S"}
};
card_t selection{"9S"};
// Predicate specifing which cards should be removed
auto has_same_rank = [rank = selection.at(0)] (card_t const& card) {
return card.at(0) == rank;
};
auto & deck = decks.at(0);
// 'std::remove_if' removes all the elements satisfying the predicate from the range
// by moving the elements that are not to be removed at the beginning of the range
// and returns a past-the-end iterator for the new end of the range.
// 'std::vector::erase' removes from the vector the elements from the iterator
// returned by 'std::remove_if' up to the end iterator. Note that it invalidates
// iterators and references at or after the point of the erase, including the
// end() iterator (it's the most common cause of errors in code like OP's).
deck.erase(std::remove_if(deck.begin(), deck.end(), has_same_rank),
deck.end());
So for anyone else in the future who comes across this...
The problem is I was deleting an element in the array in a loop, with the conditional stop was it's size. The size is set before hand, and while it was accounted for in the code it still left open the possibility for while(array.size() ) which would be locked in at 8 in the loop be treated as 6 in the code.
The solution was to save the location in the vector to delete and then delete them outside of the loop. I imagine there is a better, more technical answer to this, but it works as intended now!
for (double col = 0; col < size; ++col)
{
if(GameBoard::pool[col][0].at(0) == selection.at(0)){
while(GameBoard::pool[col][0].at(0) == selection.at(0) && cardsRem !=0){
if( GameBoard::pool[col].size() > 1 ){
GameBoard::pool[col].pop_back();
cardsRem--;
}
if(GameBoard::pool[col].size() <2){
toDel.insert ( toDel.begin() , col );
//GameBoard::pool.erase(GameBoard::pool.begin() + col);
cardsRem--;
size--;
}
}
}
}
for(int i = 0; i< toDel.size(); i++){
GameBoard::pool.erase(GameBoard::pool.begin() + toDel[i]);
}

Fast algorithm to remove odd elements from vector

Given a vector of integers, I want to wrote a fast (not obvious O(n^2)) algorithm to remove all odd elements from it.
My idea is: iterate through vector till first odd element, then copy everything before it to the end of vector (call push_back method) and so on until we have looked through all original elements (except copied ones), then remove all of them, so that only the vector's tail survive.
I wrote the following code to implement it:
void RemoveOdd(std::vector<int> *data) {
size_t i = 0, j, start, end;
uint l = (*data).size();
start = 0;
for (i = 0; i < l; ++i)
{
if ((*data)[i] % 2 != 0)
{
end = i;
for (j = start, j < end, ++j)
{
(*data).push_back((*data)[j]);
}
start = i + 1;
}
}
(*data).erase((*data).begin(), i);
}
but it gives me lots of errors, which I can't fix. I'm very new to the programming, so expect that all of them are elementary and stupid.
Please help me with error corrections or another algorithm implementation. Any suggestions and explanations will be very appreciative. It is also better not to use algorithm library.
You can use the remove-erase idiom.
data.erase(std::remove_if(data.begin(), data.end(),
[](int item) { return item % 2 != 0; }), data.end());
You don't really need to push_back anything (or erase elements at the front, which requires repositioning all that follows) to remove elements according to a predicate... Try to understand the "classic" inplace removal algorithm (which ultimately is how std::remove_if is generally implemented):
void RemoveOdd(std::vector<int> & data) {
int rp = 0, wp = 0, sz = data.size();
for(; rp<sz; ++rp) {
if(data[rp] % 2 == 0) {
// if the element is a keeper, write it in the "write pointer" position
data[wp] = data[rp];
// increment so that next good element won't overwrite this
wp++;
}
}
// shrink to include only the good elements
data.resize(wp);
}
rp is the "read" pointer - it's the index to the current element; wp is the "write" pointer - it always points to the location where we'll write the next "good" element, which is also the "current length" of the "new" vector. Every time we have a good element we copy it in the write position and increment the write pointer. Given that wp <= rp always (as rp is incremented once at each iteration, and wp at most once per iteration), you are always overwriting either an element with itself (so no harm is done), or an element that has already been examined and either has been moved to its correct final position, or had to be discarded anyway.
This version is done with specific types (vector<int>), a specific predicate, with indexes and with "regular" (non-move) assignment, but can be easily generalized to any container with forward iterators (as its done in std::remove_if) and erase.
Even if the generic standard library algorithm works well in most cases, this is still an important algorithm to keep in mind, there are often cases where the generic library version isn't sufficient and knowing the underlying idea is useful to implement your own version.
Given pure algorithm implementation, you don't need to push back elements. In worst case scenario, you will do more than n^2 copy. (All odd data)
Keep two pointers: one for iterating (i), and one for placing. Iterate on all vector (i++), and if *data[I] is even, write it to *data[placed] and increment placed. At the end, reduce length to placed, all elements after are unecessary
remove_if does this for you ;)
void DeleteOdd(std::vector<int> & m_vec) {
int i= 0;
for(i= 0; i< m_vec.size(); ++i) {
if(m_vec[i] & 0x01)
{
m_vec.erase(m_vec.begin()+i);
i--;
}
}
m_vec.resize(i);
}

Intro to C++: Sorting code

I am studying for a final exam that is scheduled today. My question is, what does the do-while(swap) statement do here? Is swap set to "true" by default?
My understanding of this code is that it iterates at least once for each pass of the sort. The inner for loop carries the crucial code and does all the swaps in the pass. For example, array[count] is copied into temp, array[count+1] is copied into array[count] and array[count] is copied into array[count+1]. If the two elements are swapped, the bool swap is set to true. The outer loop keeps iterating until it finds the swap flag false.
void sortArray(int array[], int size)
{
int size;
bool swap;
do
{
swap = false;
for(int count = 0; count < (size -1); count++)
{
if(array[count] > array[count+1])
{
temp = array[count];
array[count] = array[count+1];
array[count+1] = temp;
swap = true;
}
}
}while(swap);
}
Swap is used to check if algorithm is still sorting or not. If swap is false, it means that array is already sorted and algorithm can be finished.
By default (in the beginning of each iteration of do-while loop) swap is set to false and it's change to true only if swap was made (it means that array elements weren't in correct order).
Swap variable is used to determine end of algorithm.If array is sorted, no swap occurs and swap variable will be false, hence end of sorting.
Default value of swap variable is undefined, but it doesnt matter, since you assign it as false in each iteration before processing array from beggining
while-do is used to execute for loop until no elements in the array should be swapped. If no swaps occurred during the for loop, than all elements are sorted. But, if during the execution of the inner loop two elements were swapped, the array is scanned again to check if the result array is sorted.

Copy elements of an old array of pointers into new array of pointers?

I need some assistance with a C++ project. What I have to do is remove the given element from an array of pointers. The technique taught to me is to create a new array with one less element and copy everything from the old array into the new one except for the specified element. After that I have to point the old array towards the new one.
Here's some code of what I have already:
I'm working with custom structs by the way...
Data **values = null; // values is initialized in my insert function so it is
// populated
int count; // this keeps track of values' length
bool remove(Data * x) {
Data **newArray = new Data *[count - 1];
for (int i = 0; i < count; i++) {
while (x != values[i]) {
newArray[i] = values[i];
}
count -= 1;
return true;
}
values = newArray;
return false;
}
So far the insert function works and outputs the populated array, but when I run remove all it does is make the array smaller, but doesn't remove the desired element. I'm using the 0th element every time as a control.
This is the output I've been getting:
count=3 values=[5,6,7] // initial insertion of 5, 6, 7
five is a member of collection? 0
count=3 values=[5,6] // removal of 0th element aka 5, but doesn't work
five is a member of collection? 0
count=4 values=[5,6,5] // re-insertion of 0th element (which is stored in
five is a member of collection? 0 // my v0 variable)
Could anyone nudge me in the right direction towards completing this?
First of all, your code is leaking memory like no good! Next you only copy the first element and not even that if the first element happens to be the one you want to remove. Also, when you return from your function, you haven't changed your internal state at all. You definitely want to do something along the lines of
Data** it = std::find(values, values + count, x);
if (it != values + count) {
std::copy(it + 1, values + count, it);
--count;
return true;
}
return false;
That said, if anybody taught you to implement something like std::vector<T> involving reallocations on every operation, it is time to change schools! Memory allocations are relatively expensive and you want to avoid them. That is, when implementing something like a std::vector<T> you, indeed, want to implement it like a std::vector<T>! That is you keep an internal buffer of potentially more element than there are and remember how many elements you are using. When inserting a new element, you only allocate a new array if there is no space in the current array (not doing so would easily result in quadratic complexity even when always adding elements at the end). When removing an element, you just move all the trailing objects one up and remember that there is one less object in the array.
Try this:
bool remove(Data * x)
{
bool found = false;
// See if x is in the array.
for (int i = 0; i < count; i++) {
if (x != values[i]) {
found = true;
break;
}
}
if (!found)
{
return false;
}
// Only need to create the array if the item to be removed is present
Data **newArray = new Data *[count - 1];
// Copy the content to the new array
int newIndex = 0;
for (int i = 0; i < count; i++)
{
if (x != values[i])
newArray[newIndex++] = values[i];
}
// Now change the pointers.
delete[] values;
count--;
values = newArray;
return true;
}
Note that there's an underlying assumption that if x is present in the array then it's there only once! The code will not work for multiple occurrences, that's left to you, seeing as how this is a school exercise.

Array PopFront Method C++

Trying not to lose it here. As you can see below I have assigned intFrontPtr to point to the first cell in the array. And intBackPtr to point to the last cell in the array...:
bool quack::popFront(int& nPopFront)
{
nPopFront = items[top+1].n;
if ( count >= maxSize ) return false;
else
{
items[0].n = nPopFront;
intFrontPtr = &items[0].n;
intBackPtr = &items[count-1].n;
}
for (int temp; intFrontPtr < intBackPtr ;)
{
++intFrontPtr;
temp = *intFrontPtr;
*intFrontPtr = temp;
}
return true;
}
In the else statement I'm simply reassigning to ensure that my ptrs are where I want them. For some reason I'm popping off the back instead of off the front.
Anyone care to explain?
I'm not entirely sure I understand what you're trying to do, but if I;m guessing right you're trying to 'pop' the 1st element of the array (items[0]) into the nPopFront int reference, then move all the subsequent elements of the array over by one so that the 1st element is replaced by the 2nd, the 2nd by the 3rd, and so on. After this operation, the array will contain one less total number of elements.
Not having the full declaration of the quack class makes most of the following guesswork, but here goes:
I'm assuming that item[0] represents the 'front' of your array (so it's the element you want 'popped').
I'm also assuming that 'count` is the number of valid elements (so item[count-1] is the last valid element, or the 'back' of the array).
Given these assumptions, I'm honestly not sure what top is supposed to represent (so I might be entirely wrong on these guesses).
Problem #1: your nPopFront assignment is reversed, it should be:
nPopFront = items[0].n;
Problem #2; your for loop is a big no-op. It walks through the array assigning elements back to their original location. I think you want it to look more like:
for (int i = 1; i < count; ++i)
{
items[i-1].n = items[i].n; // move elements from back to front
}
Finally, you'll want to adjust count (and probably top - if you need it at all) before you return to adjust the new number of elements in the data structure. The whole thing might look like:
bool quack::popFront(int& nPopFront)
{
if ( count >= maxSize ) return false;
if ( count == 0 ) return false; // nothing to pop
nPopFront = items[0].n;
intFrontPtr = &items[0].n; // do we really need to maintain these pointers?
intBackPtr = &items[count-1].n;
for (int i = 1; i < count; ++i)
{
items[i-1].n = items[i].n; // move elements from back to front
}
count -= 1; // one less item in the array
return true;
}
The original question seems to be that you don't understand why the function popFront returns 3 times when there are 3 elements?
If that's the case, I think you are missing the point of recursion.
When you make a recursive call, you are calling the same function again, basically creating a new stack frame and jumping back to the same function. So if there are 3 elements, it will recurse by encountering the first element, encountering the second element, encountering the third element, returning from the third encounter, returning from the second encounter, and returning from the first encounter (assuming you are properly consuming your array, which you don't appear to be).
The current function cannot return until the recursive call has iterated, thus it may appear to return from the last element before the second, and the second before the first.
That is how recursion works.
I wasn't able to make sense of your example, so I whipped one up real fast:
#include <iostream>
using namespace std;
bool popfront(int* ptr_, int* back_) {
cerr << ptr_[0] << endl;
if(ptr_ != back_) {
popfront(++ptr_, back_);
}
return true;
}
int main() {
int ar[4] = {4,3,2,1};
popfront(ar, ar + 3);
return 0;
}
That's not great, but it should get the point across.
Can't you just use a std::list?
That makes it really to pop from either end using pop_front or pop_back. You can also add to the front and the back. It also has the advantage that after popping from the front (or even removing from the middle of the list) you don't have to shift anything around (The link is simply removed) which makes it much more efficient than what you are, seemingly, proposing.
I'm assuming you're trying to assign the popped value to nPopFront?
bool stack::popFront(int& nPopFront)
{
//items[4] = {4,3,2,1}
if ( intFrontPtr < intBackPtr )
{
nPopFront = *intFrontPtr;
++intFrontPtr;
}
return true;
}
bool quack::popFront(int& nPopFront)
{
if(items.n==0) throw WhateverYouUseToSignalError;
nPopFront = items[0];
for (int =0;i<items.n-1,++i){
items[i]=items[i+1]
}
//update size of items array
}