It would be inappropriate for me to post the actual code I've written to solve this problem, but I'll post pseudocode instead. I believe this accomplishes the task in linear time, but I have not proven it; I lack either the mathematical sophistication or the motivation to do so. If it is correct and linear-time, it might be formally equivalent to the "rotating calipers" method referred to by MBo.
Note: This might go into a loop if the polygons fail to satisfy my hypotheses. You can detect this by (1) checking at the "find horizon" loop if it's looping too many times, and (2) counting the vertices produced and checking at each produced vertex whether more vertices have been produced than ought to be possible.
Note (2): All indices wrap around; pa + 1 is by definition another name for p1, and p0 is by definition another name for pa.
Note (3): We may assume without loss of generality that p1 is either due west, or anywhere north of q1 (or they are the same point).
let start_point be p[1]
let current_index be 1
let horizon_index be 1
while true:
let c = p[current_index]
let c' = p[current_index + 1]
let h = q[horizon_index]
yield c
-- Update the horizon on the other polygon.
while true:
let T1 = triangle(c, h, q[horizon_index - 1])
let T2 = triangle(c, h, q[horizon_index + 1])
let cond1 = "T1 is clockwise or degenerate"
let cond2 = "T2 is clockwise"
if cond1 and cond2:
-- Found the correct horizon.
break
increment horizon_index
let T = triangle(c, h, c')
let horizon_further be "from c, the horizon is further away than c'"
let should_bridge = case
when T is anticlockwise then false
when T is clockwise then true
when T is degenerate then horizon_further
end case
increment current_index
if should_bridge:
swap p and q
swap current_index and horizon_index
if p[current_index] is equal to start_point:
break