Pre-emptive scheduling just means that whatever is running now can be stopped for something else to run. Emphasis on can be stopped. It may never be stopped, as well as it may never end up running at all.
As you asked, I will try to describe a pseudocode for a preemptive scheduling algorithm that can cause starvation:
P = running processes list
q = quantum
while P is not empty:
t_0 <- infinity
for each p in P:
t <- p.totalTime
if t < t_0:
t_0 <- t
p <- process with running time t_0
run p for quantum q
Suppose now that processes can be added to the list P at any time. If you keep adding small processes, they would always be executed before any other big processes, resulting on starvation.
This algorithm is a pre-emptive form of SJF (Shortest Job First). You can extrapolate and make a pre-emptive algorithm that simply never runs a given process; instead, if this is the only process left, the algorithm just waits in a loop until something new appears. It's not a good algorithm, but it is pre-emptive and causes starvation.
Actually, if you stop to think, the only way you can get starvation is on pre-emptive schemes. You can't get starvation in non-preemptive schemes, as they will all run until the end, and you can't add any jobs. Preemptive schemes comes actually not to give all processes a share of CPU, but to make your system more responsive. So, a smart preemptive scheme is one that increases responsiveness by not giving I/O bounded processes too much attention, stopping them while they are waiting for some input, for example.