Here are two alternatives.
First, assuming we have to start with "x" and "y", you can try interleave from the "gdata" package:
library(gdata)
interleave(x, y)
#      ranks names      
# [1,] "1"   "Karl"     
# [2,] ""    "Cape Town"
# [3,] "2"   "Klaus"    
# [4,] ""    "London"   
# [5,] "3"   "Mary"     
# [6,] ""    "Berlin"
Second, assuming we can start with "ranks", "names", and "universities", you can use base R, like this:
cbind(c(t(cbind(ranks, ""))), c(t(cbind(names, universities))))
#      [,1] [,2]       
# [1,] "1"  "Karl"     
# [2,] ""   "Cape Town"
# [3,] "2"  "Klaus"    
# [4,] ""   "London"   
# [5,] "3"  "Mary"     
# [6,] ""   "Berlin"
A better alternative, however, would be to use something like melt (from "reshape2" or "data.table"). This would allow you to add another variable that indicates what type of measurement a value represents.
library(data.table)
melt(data.table(ranks, names, universities), "ranks")
#    ranks     variable     value
# 1:     1        names      Karl
# 2:     2        names     Klaus
# 3:     3        names      Mary
# 4:     1 universities Cape Town
# 5:     2 universities    London
# 6:     3 universities    Berlin
Or, to match your desired ordering:
library(data.table)
setorder(melt(data.table(ranks, names, universities), "ranks"), ranks)[]
#    ranks     variable     value
# 1:     1        names      Karl
# 2:     1 universities Cape Town
# 3:     2        names     Klaus
# 4:     2 universities    London
# 5:     3        names      Mary
# 6:     3 universities    Berlin