I'm trying to sort a filled linked list with random numbers. The function I have made doesnt work as it should. I can't see what is wrong, its not sorting the numbers properly.
void linked_list::SortList()
{
if(is_empty())
{
return;
}
for(node_t *it =head; it!=tail; it = it->next)
{
int valToIns = it->value;
node_t *holePos = it;
while(holePos->prev && valToIns < it->prev->value)
{
holePos->value = holePos->prev->value;
holePos = holePos->prev;
}
holePos->value = valToIns;
}
}
You're comparing with the wrong element,
while(holePos->prev && valToIns < it->prev->value)
should be
while(holePos->prev && valToIns < holePos->prev->value)
in order to compare valToIns with the value before the one holePos points to.
Related
I'm stumped on my loop. When two lists sizes are equal, I want to compare the contents of it (string and int). I primarily don't understand this part:
The content of all the containers in a BookList is the same - so pick one to walk. If the books are different, you have your answer
Here is my code:
int BookList::compare(const BookList& other) const {
if (!containers_are_consistent() || !other.containers_are_consistent()) {
throw BookList::InvalidInternalStateException(
"Container consistency error in compare");
}
// my implementation starts here
auto begin_this_ = this->books_vector_.begin();
auto begin_other_ = other.books_vector_.begin();
auto end_this_ = this->books_vector_.end();
auto end_other_ = other.books_vector_.end();
if(this->size() == other.size()){
while(begin_this_ != end_this_) {
if(begin_this_ == begin_other_){
++begin_this_;
}
return 0;
if(begin_this_ != begin_other_) {
//what do I do here?
}
}
return 0;
} else if(this->size() < other.size()){
return -1;
} else if(this->size() > other.size()){
return 1;
}
// ends here
}
Firstly, you probably want to compare the contents of the iterators and not the iterators themselves
if (*begin_this_ == *begin_other_) ...
Secondly, you return 0 whenever two iterators compare equal which means you exit the loop.
I suggest you return early only if two elements are NOT equal.
Sadly, you have not described what value is returned if the sizes are equal but the contents are not, so I will assume that the elements are less than comparable.
Then your while loop will look like
while (begin_this_ != end_this_) {
if (*begin_this_ < *begin_other_)
return -1;
else if (*begin_other_ < *begin_this_)
return 1;
++begin_this_;
++begin_other_;
}
// end of loop which means that all elements are equal
return 0;
I need to loop through a vector of linked list and check if a node with the string(s) exists. Obviously this only checks the beginning to see if it exists. I want to know how to go through the entire linked list.
vector <Dlist *> table; //Dlist is the linked list
int DL_Hash::Present(string &s) {
int index = djb_hash(s) % table.size();
for(int i = 0; i < table[index]->Size(); i++) {
if(table[index]->Begin()->s == s) {
return 1;
}
}
return 0;
}
You are not using variable i at all, and you indeed cant do something like table[index][i], as you cant index linked list. You only can get first element in list, and immediate next.
First you get pointer to the beginning (iterator would be more fitting). Then check every item for your condition, until you are at the end of list.
int DL_Hash::Present(string &s) {
int index = djb_hash(s) % table.size();
auto tmp = table[index]->Begin();
while (tmp != nullptr) { // check if you are at end of linked list
if (tmp->s == s)
return 1;
tmp = tmp.Next(); // asuming you have function to get next element in linked list.
}
return 0;
}
If Dlist would have iterators:
int DL_Hash::Present(string &s) {
int index = djb_hash(s) % table.size();
auto tmp = table[index]->begin();
while (tmp != table[index].end()) { // check if you are at end of linked list
if (tmp->s == s)
return 1;
tmp++;
}
return 0;
}
Or even better, using range for
int DL_Hash::Present(string &s) {
int index = djb_hash(s) % table.size();
for (auto &tmp : table[index]) {
if (tmp->s == s)
return 1;
}
return 0;
}
I have used std::vector for making my algorithm. I would like to replace the vectors by linked lists.
In order to do so, I was thinking of using the std::list, but I have no idea how to do this, for example I have tried following example for finding a value within a vector/list:
void find_values_in_vector(const std::vector<int>& input_vector, int value, int &rv1, int &rv2)
{
if (input_vector[0] >= value) { // too small
rv1 = 0; rv2 = 0; return;
}
int index = (int)input_vector.size() - 1;
if (input_vector[index] <= value) { // too big
rv1 = index; rv2 = index; return;
}
// somewhere inside
index = 0;
while (input_vector[index] <= value) {
index++;
}
rv1 = index - 1; rv2 = index; return;
}
void find_values_in_list(const std::list<int>& input_list, int value, int &rv1, int &rv2)
{
if (*input_list.begin() >= value) { // too small
rv1 = 0; rv2 = 0; return;
}
if (*input_list.end() <= value) { // too big
rv1 = (int)input_list.size() - 1; rv2 = (int)input_list.size() - 1; return;
}
// somewhere inside
int index = 0; int temp = *input_list.begin();
while (temp <= value) {
temp = *input_list.next(); index++;
}
rv1 = index - 1; rv2 = index; return;
}
This seems not to work, as the member function next() is not existing. However I remember that browsing through a linked list is done by going to the beginning, and moving further to the next element until the a certain point is reached. I have seen that there is a way to get this done by using an interator in a for-loop, but I wonder what's wrong with my approach? I was under the impression that a std::list was a standard implementation of a double-directional linked list, or am I wrong and in that case, what std class is the implementation of a linked list (it does not need to be a double-directional linked list)?
The standard way to iterate through containers is like this:
for(std::list<int>::iterator it = input_list.begin();
it != input_list.end();
it++)
{
....
}
This also works for vectors,maps,deque,etc. The Iterator concept is consistently implemented throughout the STL so it's best to get used to this concepts.
There are also iterator operations like std::distance and std::advance etc. for the different types of iterators (I suggest you read up on them and their advantages/limitations)
If you have C++ 11 available you can also use this syntax (may not be useful for your problem though.)
for(const auto& value : input_list)
{
...
}
This also works throughout the STL container.
This should work for vector, list, deque, and set (assuming the contents are sorted).
template <class T>
void find_values_in_container(const T& container, int value, int &rv1, int &rv2)
{
rv1 = rv2 = 0; // Initialize
if (container.empty() || container.front() >= value)
{
return;
}
for (const auto& v : container)
{
rv2++;
if (v > value)
{
break;
}
rv1++;
}
return;
}
I am currently programming a little game for the console with an 2D map. 2 Elements of my game are: destroying fields and an enemy, which spreads in a random direction (its getting bigger). These two "entities" are saved in a structure which contains two vectors (X and Y). I am now trying to erase an element of "_Enemy"(<-private instance of the structure in a class, same as "_DestroyedFields") if you destroy the field where the enemy is.
I tried a lot of different variations to do so and whats giving me the error least is this method (I already searched the internet for a while now an couldn't find a answer to my question):
for (std::vector<int>::iterator itEX = _Enemys.X.begin(), itEY = _Enemys.Y.begin();
itEX != _Enemys.X.end() && itEY != _Enemys.Y.end();
++itEX, ++itEY) {
for (std::vector<int>::iterator itX = _DestroyedFields.X.begin(),
itY = _DestroyedFields.Y.begin();
itX != _DestroyedFields.X.end() && itY != _DestroyedFields.Y.end();
++itX, ++itY) {
if (*itY == *itEY && *itX == *itEX){
itEY = _Enemys.Y.erase(itEY);
itEX = _Enemys.X.erase(itEX);
}
}
}
PS: sorry if my english isn't the best, im german ^^
PSS: if you wanna watch over my whole code, you can find it on Github: https://github.com/Aemmel/ConsoleGame1
After erasing using iterator it, you cannot use it further as it is invalidated. You should use a result of a call to erase which is new, valid iterator.
for( it = v.begin(); it != v.end();)
{
//...
if(...)
{
it = v.erase( it);
}
else
{
++it;
}
...
}
I fixed the bug with first: making a "simple structure"(struct Entity{int X; intY} and then std::vector [insert name here]) and then with adding an break; if the condition is true.
for (Uint itE = 0; itE < _Enemys.size(); ++itE){
for (Uint it = 0; it<_DestroyedFields.size(); ++it){
if (_Enemys.at(itE).Y == _DestroyedFields.at(it).Y
&& _Enemys.at(itE).X == _DestroyedFields.at(it).X){
_Enemys.erase(_Enemys.begin()+itE);
break;
}
}
}
With struct Position {int x; int y;}; and some utility operators,
you may do one of the following: (https://ideone.com/0aiih0)
void filter(std::vector<Position>& positions, const std::vector<Position>& destroyedFields)
{
for (std::vector<Position>::iterator it = positions.begin(); it != positions.end(); ) {
if (std::find(destroyedFields.begin(), destroyedFields.end(), *it) != destroyedFields.end()) {
it = positions.erase(it);
} else {
++it;
}
}
}
Or, if input are sorted, you may use a 'difference':
std::vector<Position> filter2(const std::vector<Position>& positions, const std::vector<Position>& destroyedFields)
{
std::vector<Position> res;
std::set_difference(positions.begin(), positions.end(),
destroyedFields.begin(), destroyedFields.end(),
std::back_inserter(res));
return res;
}
I am trying to insert into this Vector (mCards) in alphabetical order. I can't use sort - it must be inserted in alphabetical order! Right now, I'm inserting in reverse. I can't figure out how to get this to insert in correct alphabetical order!
void Rolodex::Add(Card& card)
{
vector<Card>::iterator temp;
if (mCards.size() != 0)
{
for(vector<Card>::iterator it = mCards.begin(); it != mCards.end(); ++it)
{
Card& currentCard = *it;
temp = it;
int compareResult = currentCard.GetLastName().compare(card.GetLastName());
if (compareResult <= 0)
{
mIteratorNumber = it - mCards.begin();
mCards.insert(temp, card);
return;
}
}
}
else
{
mCards.push_back(card);
for(vector<Card>::iterator it = mCards.begin(); it != mCards.end(); ++it)
{
mIteratorNumber = it - mCards.begin();
}
}
}
If you wants a sorted container, you may instead look at std::map and std::set or their multi variant if you may have duplicated values.
To insert into a sorted vector, the right way to do it is to use std::upper_bound
myCards.insert( std::upper_bound( begin(myCards), end(myCards), card), card );
If the card do not have a valid operator<, use a predicate like this
auto it = std::upper_bound( begin(myCards), end(myCards), card,
[] ( Card const & a, Card const & b ) {
return a.GetLastName().compare(b.GetLastName()) < 0;
} );
myCards.insert( it, card );