Arrays instead of vectors

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
User avatar
Bullet Pulse
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 89
Joined: Sun Feb 21, 2010 6:25 pm

Arrays instead of vectors

Post by Bullet Pulse »

I've usually used vectors in the past to store pointers to objects, but I want to know how to do this with an array.

So, say that I wanted an array of Battleships for a game, and they are destroyed in a random order.

Code: Select all

const int MAX_BATTLESHIPS = 100;
Battleship *battleships[MAX_BATTLESHIPS];

//Sample function to add a ship to the array
void AddShip()
{
   battleships[FindEmptyIndex()] = new Battleship;
}

void RemoveShip(int index)
{
   delete battleships[index];
   battleships[index] = 0;
}

int FindEmptyIndex()
{
   for (int i = 0; i < MAX_BATTLESHIPS; i++)
      if (!battleships[i]) return i;
}
Is this the way to do it?
Image
X Abstract X
Chaos Rift Regular
Chaos Rift Regular
Posts: 173
Joined: Thu Feb 11, 2010 9:46 pm

Re: Arrays instead of vectors

Post by X Abstract X »

I haven't had to do this but just by looking at it, it looks like the way I would go about doing it. Not that it's necessary but I would use unsigned ints where appropriate and add a bounds check inside the RemoveShip() function.
User avatar
Amarant
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 34
Joined: Wed Nov 05, 2008 9:52 am

Re: Arrays instead of vectors

Post by Amarant »

There is no 'THE' way to do it.
Here's something else you could do if the order of the BattleShips in the array is not important:

Code: Select all

const int MAX_AMT_OF_BATTLESHIPS = 100;
Battleship *battleships[MAX_AMT_OF_BATTLESHIPS];

int battleship_count = 0;

//Sample function to add a ship to the array
void AddShip()
{
    if(battleship_count == MAX_AMT_OF_BATTLESHIPS)
        handleError();
    battleships[battleship_count] = new Battleship;
    battleship_count++;
}

void RemoveShip(int index)
{
    delete battleships[index];
    battleship_count--;
    battleships[index] = battleships[battleship_count];
}
So when you remove a battleship the last battleship in the array will take it's place and the array will be 'shortened'.
177
User avatar
Bullet Pulse
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 89
Joined: Sun Feb 21, 2010 6:25 pm

Re: Arrays instead of vectors

Post by Bullet Pulse »

Amarant wrote:There is no 'THE' way to do it.
I just mean an efficient way to do it ;)
Image
User avatar
Amarant
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 34
Joined: Wed Nov 05, 2008 9:52 am

Re: Arrays instead of vectors

Post by Amarant »

I guessed correctly then ;)

The example I've given will be more efficient especially for large full arrays. Since the add and remove functions don't change in performance with the size of the array. Your example will increasingly get slower if you use larger and fuller arrays.

For this particular example however, it probably will not be noticeable.
177
XianForce
Chaos Rift Devotee
Chaos Rift Devotee
Posts: 767
Joined: Wed Oct 29, 2008 8:36 pm

Re: Arrays instead of vectors

Post by XianForce »

That looks fine, but here are a few suggestions:

Code: Select all

const int MAX_BATTLESHIPS = 100;
Battleship *battleships[MAX_BATTLESHIPS];

//Sample function to add a ship to the array
void AddShip()
{
   //You need to check if there actually IS an empty index!
   unsigned int emptyIndex = FindEmptyIndex();

   if(emptyIndex > 0)
   {
      battleships[FindEmptyIndex()] = new Battleship;
   }
}

void RemoveShip(int index)
{
   //check to make sure you don't go outside of the bounds!
   if(index > 0 && index < MAX_BATTLESHIPS)
   {
      //Also, check to make sure the battleship is not already NULL!
      if(battleships[index])
      {
         delete battleships[index];
         battleships[index] = 0;
      }
   }
}

int FindEmptyIndex()
{
   //The only problem with this, is when it DOESN'T find an empty index, no value is returned...
   for (int i = 0; i < MAX_BATTLESHIPS; i++)
      if (!battleships[i]) return i;

   return -1;
}
So I think that should probably work.
XianForce
Chaos Rift Devotee
Chaos Rift Devotee
Posts: 767
Joined: Wed Oct 29, 2008 8:36 pm

Re: Arrays instead of vectors

Post by XianForce »

Amarant wrote:There is no 'THE' way to do it.
Here's something else you could do if the order of the BattleShips in the array is not important:

Code: Select all

const int MAX_AMT_OF_BATTLESHIPS = 100;
Battleship *battleships[MAX_AMT_OF_BATTLESHIPS];

int battleship_count = 0;

//Sample function to add a ship to the array
void AddShip()
{
    if(battleship_count == MAX_AMT_OF_BATTLESHIPS)
        handleError();
    battleships[battleship_count] = new Battleship;
    battleship_count++;
}

void RemoveShip(int index)
{
    delete battleships[index];
    battleship_count--;
    battleships[index] = battleships[battleship_count];
}
So when you remove a battleship the last battleship in the array will take it's place and the array will be 'shortened'.
One thing... Won't this just make it so TWO elements in the array have the same value?, I think you need to do something like:

Code: Select all

void RemoveShip(int index)
{
delete battleships[index];
battleship_count--;
battleships[index] = battleships[battleship_count];
battleships[battleship_count = NULL;
}
Right?

Oh and because your incrementing battleship_count for each ship you add, you'll have an 'off by one error' won't you? Because battleship_count is how many battleships you have, but the last battleship in the array would be battleship_count - 1, wouldn't it?
User avatar
Bullet Pulse
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 89
Joined: Sun Feb 21, 2010 6:25 pm

Re: Arrays instead of vectors

Post by Bullet Pulse »

XianForce wrote:That looks fine, but here are a few suggestions:
...
So I think that should probably work.
Thanks! :)

EDIT: Shouldn't it be:

Code: Select all

if (emptyIndex >= 0)
{
      battleships[FindEmptyIndex()] = new Battleship;
}
Last edited by Bullet Pulse on Sat May 22, 2010 5:23 pm, edited 2 times in total.
Image
User avatar
Amarant
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 34
Joined: Wed Nov 05, 2008 9:52 am

Re: Arrays instead of vectors

Post by Amarant »

XianForce wrote:
Amarant wrote:...
One thing... Won't this just make it so TWO elements in the array have the same value?, I think you need to do something like:

Code: Select all

void RemoveShip(int index)
{
delete battleships[index];
battleship_count--;
battleships[index] = battleships[battleship_count];
battleships[battleship_count = NULL;
}
Right?

Oh and because your incrementing battleship_count for each ship you add, you'll have an 'off by one error' won't you? Because battleship_count is how many battleships you have, but the last battleship in the array would be battleship_count - 1, wouldn't it?

Hmmm, I do think my version was correct. Let me think it through.

When you call RemoveShip battleship_count will equal the amount of elements in the array.
So if you use that count as an index, it will point to exactly one position after the last element.
If you then decrement that count, it will point exactly to the last element.
Using it now as an index will get you the last element.
Then assign that last element to the position in the array you've just emptied.
This will indeed result in there being two identical pointers in the array.
But remember that the battleship_count was decremented.
So the next time you will use the add function it will simply be overwritten.

I intentionally named the variable battleship_count, indicating that it is the count of battleships in the array.
If I would have wanted to store the highest index in the array I would have chosen another name for the variable.
Last edited by Amarant on Sat May 22, 2010 5:25 pm, edited 1 time in total.
177
XianForce
Chaos Rift Devotee
Chaos Rift Devotee
Posts: 767
Joined: Wed Oct 29, 2008 8:36 pm

Re: Arrays instead of vectors

Post by XianForce »

Bullet Pulse wrote:
XianForce wrote:That looks fine, but here are a few suggestions:
...
So I think that should probably work.
Thanks! :)

EDIT: Shouldn't it be:

Code: Select all

if (emptyIndex >= 0)
{
      battleships[FindEmptyIndex()] = new Battleship;
}
Ooops, actually I meant to do:

Code: Select all

battleships[emptyIndex] = new Battleship();
Just a safety thing in case FindEmptyIndex() returns something different.
User avatar
Bullet Pulse
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 89
Joined: Sun Feb 21, 2010 6:25 pm

Re: Arrays instead of vectors

Post by Bullet Pulse »

XianForce wrote:That looks fine, but here are a few suggestions:
Ooops, actually I meant to do:

Code: Select all

battleships[emptyIndex] = new Battleship();
Just a safety thing in case FindEmptyIndex() returns something different.
I know that's what you meant ;)
Image
XianForce
Chaos Rift Devotee
Chaos Rift Devotee
Posts: 767
Joined: Wed Oct 29, 2008 8:36 pm

Re: Arrays instead of vectors

Post by XianForce »

Amarant wrote:
Hmmm, I do think my version was correct. Let me think it through.

When you call RemoveShip battleship_count will equal the amount of elements in the array.
So if you use that count as an index, it will point to exactly one position after the last element.
If you then decrement that count, it will point exactly to the last element.
Using it now as an index will get you the last element.
Then assign that last element to the position in the array you've just emptied.
This will indeed result in there being two identical pointers in the array.
But remember that the battleship_count was decremented.
So the next time you will use the add function it will simply be overwritten.

I intentionally named the variable battleship_count, indicating that it is the count of battleships in the array.
If I would have wanted to store the highest index in the array I would have chosen another name for the variable.
Yeah I didn't even think about the decrement haha.
User avatar
avansc
Respected Programmer
Respected Programmer
Posts: 1708
Joined: Sun Nov 02, 2008 6:29 pm

Re: Arrays instead of vectors

Post by avansc »

hey, kinda just read half assed, so sorry if this is a duplicate answer.

you are spending a lot of time finding an open slot, another way would be to always have your ships ordered.
in other words have a count of how many objects you have resident, then if you add one you just add it to the back of the array and increment the residency counter.

when you delete something, from position x, you know you have to move all the aft memory one object size up, in this case just the 4 or 8 bytes of the pointer, and also remember to decrement the counter.this way your adding is O(1), you'll occur some over head in the memmove, but it should be a lot cheaper than trying to find open locations.
Some person, "I have a black belt in karate"
Dad, "Yea well I have a fan belt in street fighting"
Post Reply