If we were "old school" about this:
Given that you said "grid" that implies a simple two dimensional array.
In order to know if each cell has an open passage to its neighbour in some direction only requires 1 bit. (0 closed, 1 open) So only four bits need to be saved in each cell to represent passages, north, south, east, west. Or you might need 8 bits if diagonal passages are allowed.
So, each cell need only hold a u8, the bits of which are used to hold the open/closed passage of each direction out of the cell.
Of course you are likely to want to store some other data in each cell, so better make each element of that array a struct with that "neighbours" byte in it and whatever other fields you need.
That is how I did a maze generation algorithm on a TRS-80 computer back in 1980 something. Worked a treat in the 4 kilo bytes of memory available on that machine.
Moving forward, I recently wanted to generate the mazes of the "Hunt The Wumpus" game in Rust: Hunt the Wumpus - Wikipedia
To that end I put all the caves of the game into elements of a vector of structures and created passages between them simply storing the índices of open passages in those elements.
As discussed here: When is a linked list not a linked list?. With code.