Single table with multiple NULL columns vs multiple tables
There is no hard-and-fast rule.  Here's the logic I would use in coming to a decision.

In general, it is clumsy to have an array of things (delivery addresses) spread across multiple columns.

I would pull out the entire "delivery" set of columns and make a table for them. There would be one or two rows in this new table.

Then, I would do one of these approaches:

Plan A:  In the main table, have two columns:

delivery INT UNSIGNED NOT NULL,
alt_delivery INT UNSIGNED  NULL, -- note Nullable


Plan B:  The delivery table would have a column with 1 or 2 in it, indicating 1=preferred.  (Or some variant on such).  The include that column in the JOIN.

Plan B is especially good for something like phone numbers, since there can be an arbitrarily large set of such (cell, home, work, fax, etc.)  On the other hand, for delivery you may have a rather strong limit today of exactly 1 or 2 addresses.

In both cases, it is probably not wise to do any kind of de-dupping of locations or phones.  So what if there is an occasional dup; after all, cohabitation is common.

In a slightly different use case, a billing UI might ask the user "Is the shipping address the same as billing address?"  This is giving the user the option to tie the two together.  In this case, the main table has two non-null columns bill_to and send_to, that may or may not link to the same address.

In a "location" table, it is clumsy to 'normalize' city, country, etc.  And it is not justifiable for either reason for normalizing:  It does not save much space, and you aren't likely to need to change the spelling of the city/country in some central location.  (Czechoslovakia notwithstanging)