Well you can use a linked list but there are several issues you are going to run into. First you are never guaranteed that the tile number 1 is going to be in the upper left hand corner of the screen. This would require iterating through the list until you reached the correct tile ID which wastes cycles. The absolute best system I could think of is a quad tree but coding that might be beyond where you are. Not to say that you could not do it, but why make it hard.
Here is a scheme I came up with and have also seen used on many tutorial websites.
First of all you know that this array:
012
345
678
does not have to be a two dimensional array. If you take the row*width+column you can get to any location in that array but you can use a 1 dimensional array.
So let's start with 20x20 tiles. Each tile is 400 bytes (in 256 color mode) or unsigned char Tile[400].
But we want several tiles -> Tiles[maxtiles][sizeinbytes]
So for tile 1 element 200 - Tiles[1][200]
The second element in your 2D array is the bitmap data only it is in a linear array. You would do y*20+x to access it correctly.
So in this way you could load all of your tiles into the array and use their tile ID as the index into the array.
So if grass is 1 and tree is 2 -> Tile[grass][y*20+x] and Tile[tree][y*20+x]. We get the first value from the tilemap.
Here is a basic tilemap system - note the tilemap can also be a one dimensional array.
Grass=1
Tree=2
Road=3
Rocks=4
Code:
unsigned int TileMap[]={1,1,1,1,1,1,
1,2,1,2,1,2,
3,3,3,3,3,3,
4,4,4,4,4,4,
1,1,1,1,1,1};
unsigned char Tiles[NumTiles][TileSizeInBytes];
Then all you do is draw
Tiles[(TileMap[playery*mapwidth+playerx])][TileData];
I would not use a linked list, but multiple arrays. Tiles1 would be layer 1 tiles, Tiles2 would be 2nd level, etc. etc.
They are easier and faster to access and easier to code for. However they do not lend themselves well to inserting, deleting, etc.., but most tilemaps are constant so this shouldn't matter.
Not sure why the board mangled my Tiles[] line but it did.