How I would describe quicksort in an imperative way:
def sort(list):
pivot is midpoint(list)
left_part is an empty list
right_part is an empty list
for every item in the list
if the item is smaller than the pivot
add(item) to left_part
else
add(item) to right_part
sort(left_part)
sort(right_part)
In a functional way:
sort of an empty list [] is []
sort of a non-empty list pivot:list is
sorted(list items smaller than l) + sorted(list items larger than l)
For me, the core difference is the order of thought. The top example unpacks the data, step by step, and then manipulates it or constructs new data from it. The algorithm steps are the starting point. The functional example takes the data first and describes how to manipulate it in a single go. The steps are often large-scale transformations. The variable names and low-level steps are kind of secondary. Not sure if I'm expressing myself good enough here.
More importantly, the imperative example has nothing to do with machine code. The machine would translate it to a series of GOTOs and one-letter variables. The description of the algorithm is simply different in both cases.
Caveats: I'm not that good with functional programming. Obviously, I may be missing something. This is just my current mental model of it.