Doublelist

By only storing a pointer to the head of your list, you make your shift and append methods operate in O(n) time complexity, because you have to walk across the entire list every time you want to find the end.  You could trade this for O(1) additional space complexity by also storing and maintaining a pointer to the tail of your list.