Pancake Sort

Pancake Sort is an $$O(n^2)$$ sort where the only allowed data-movement operation are "flips" which are reversals from the start to any point in the list much like flipping a stack of pancakes. Pancake Sort is not a stable sort.

The algorithm is as follows:


 * 1) Linear search for max in $$O(n)$$ comparisons
 * 2) Flip max so that it's at the top of the stack
 * 3) Flip the top of the stack to the bottom to move the max into place
 * 4) Repeat steps 1-3 excluding the max until we've sorted the list

Pancake Sort makes $$O(n)$$ flips which is the optimal bound to sort $$n$$ elements (2 flips per element in the worst case). Each flip in practice in $$O(m)$$ where $$m$$ is the amount of elements flipped which is $$O(n)$$ on average in the case of Pancake Sort therefore the total amount of data moves is $$O(n^2)$$. We also have to linear search for each element so Pancake Sort also makes $$O(n^2)$$ comparisons. procedure pancake_sort(array arr) do for j from length(arr)-1 to 1 int i = index of max(arr) flip range 0 to i      flip range 0 to j    end for end

Burnt Pancake Sort
Pancake Sort however doesn't ensure that all pancakes are right side up upon sorting which is what Burnt Pancake Sort seeks to achieve. It's easy to see that we can do a Burnt Pancake Sort by simply flipping each pancake that's upside down before flipping it to the bottom. However, in practice, this requires $$O(n)$$ bits to keep track of whether a pancake is upside down or not.

A simple in-place solution is to perform an extra reversal per element to flip pancakes that were upside down ensuring that all pancakes will be right side up: procedure burnt_pancake_sort(array arr) do for j from length(arr)-1 to 1 do int i = index of max(arr) flip range 0 to i      flip range 0 to j       flip range 0 to j-i-1 # extra reversal to ensure all pancakes are right side up    end for end Both the out-of-place and in-place variations of Burnt Pancake Sort are also not stable. Both variants also make 3 flips per item in the worst case which is 1 more compared to vanilla Pancake Sort's 2 flips per item.

Stable Pancake Sort
Stable Pancake Sort is the stable variant of Pancake Sort but makes twice as many reversals per item. Consequently, it also sorts the pancakes right side up therefore Stable Pancake is a Burnt Pancake Sort variant. Pancake Insertion Sort is the improved version of Stable Pancake Sort.

The algorithm is as follows:

procedure stable_pancake_sort(array arr) do for j = length(arr)-1 to 1 do int i = index of max(arr) flip range 0 to i      flip range 0 to j       flip range 0 to j-1 # B'Ae -> A'Be       flip range 0 to i-1 # A'Be -> ABe end for end
 * 1) Let the array be $$AeB$$ where $$A$$ and $$B$$ are ranges and $$e$$ is the max element we want to move to the end
 * 2) Flip $$Ae$$ to get $$e'A'B$$ (where prime represents a flipped range)
 * 3) Flip the entire list to move the max to the bottom: $$B'Ae$$
 * 4) Perform two flips to restore the order of $$A$$ and $$B$$: $$B'Ae \rightarrow A'Be \rightarrow ABe$$
 * 5) Repeat steps 2-4 until we moved all elements into place

Pancake Insertion Sort
Pancake Insertion Sort is a Binary Insertion Sort where all the moves are legal for pancakes. It's an improvement over Stable Pancake as it makes 3 reversals per item instead of 4 and has a worst case of $$O(n\log n)$$ comparisons instead of $$O(n^2)$$ (but is still $$O(n^2)$$ overall because of the data movements). Pancake Insertion, however, is not a Burnt Pancake Sort unless we add an extra 0.5 flips per item.

The algorithm is as follows:


 * 1) Let the array be $$ABe$$ where $$AB$$ is a sorted range and $$e$$ is the element we want to insert between $$A$$ and $$B$$
 * 2) Perform three flips to insert $$e$$ into $$AB$$: $$ABe \rightarrow e'B'A' \rightarrow BeA' \rightarrow B'eA'$$ (to maintain the burnt pancake property we flip $$e$$ before the second flip: $$e'B'A' \rightarrow eB'A'$$)
 * 3) $$e$$ is now inserted into $$AB$$ except the range is now backwards ($$B'A'$$)
 * 4) For the next item $$f$$ we simply insert to the backwards range $$D'C'$$ the same way
 * 5) Perform the same three flips to insert $$f$$: $$D'C'f \rightarrow f'CD \rightarrow C'fD \rightarrow CfD$$ (we don't need to flip $$f$$ here to maintain the burnt pancake property)
 * 6) $$f$$ is now inserted into $$D'C'$$ except the range is now forwards ($$CD$$)
 * 7) Repeat steps 2-6 until sorted.  If the final range is backwards, flip the entire array

procedure pancake_insertion_sort(array arr) do bool backwards = false for j = 1 to length(arr)-1 do int i = if backwards do backwards binary search from 0 to j-1 for arr[j] # binary search returns the index else do forwards binary search from 0 to j-1 for arr[j] flip range 0 to j      flip range 0 to j-i flip range 0 to j-i-1 backwards = not backwards end for if backwards do flip range 0 to length(arr)-1 end if end

Optimized Pancake Sort

 * Main page: Optimized Pancake sort

Optimized Pancake Sort seeks to break the $$O(n^2)$$ bound while also being a valid Pancake Sort. The result is a modification of Rotate Merge Sort where all the moves are legal for pancakes yet retains all of the time bounds of Rotate Merge. Therefore it makes $$O(n\log n)$$ comparisons and $$O(n\log^2 n)$$ moves worst case but $$O(\log n)$$ space due to recursion. Unlike the typical Pancake Sort variant, Optimized Pancake makes $$O(n\log n)$$ flips instead of $$O(n)$$ which is suboptimal, but each flip is $$O(\log n)$$ moves amortized. It can also be made stable (and, consequently, a Burnt Pancake variant).

The algorithm is best described recursively:# Divide array $$A$$ into $$BC$$ and sort $$B$$ recursively procedure opti_pancake_sort(array arr, int n) do if n > 1 do int m = floor(n/2) opti_pancake_sort(arr, m)      rotate(arr, 0, m, n-m) opti_pancake_sort(arr, n-m) merge(arr, m, n-m) end if end
 * 1) Rotate $$BC \rightarrow CB$$ and sort $$C$$ recursively
 * 2) Merge $$C$$ and $$B$$ using an in-place recursive pancake merge

Rotation
procedure rotate(array arr, int pos, int len1, int len2) do flip range 0 to pos+len1-1 flip range 0 to pos+len1+len2-1 flip range 0 to pos+len2-1 flip range 0 to pos-1 end

Merge routine
procedure merge(array arr, int len1, int len2) do if len1 > 0 and len2 > 0 do int midLen1 = length of len1 larger than median int midLen2 = length of len2 smaller than median # both can be found using a single binary search rotate(arr, len1-midLen1, midLen1, midLen2) merge(arr, len1-midLen1, midLen1) rotate(arr, 0, len1, len2) merge(arr, midLen2, len2-midLen2) rotate(arr, 0, len2, len1) end if end