One of the things is looking at the state fresh every time and then deciding what to do.
For example for bubble sort the nested loop algorithm is something like:
| for(int i = 0; i<len; i++){
for(int j = i; j+1<len;j++){
if(arr[j] > arr[j+1])swap(&arr[j], &arr[j+1]);
}
}
|
the broken up algorithm would be something like;
| if(arr[j] > arr[j+1])swap(&arr[j], &arr[j+1]);
j++;
if(j==len){
i++;
j = i;
}
if(i==len) return FINISHED;
else return WORKING
|
with arr, i and j as the persisted state.
As you can see the most central bit (the test and swap) is preserved unchanged. Then the array bounds logic is reshuffled so that the algorithm can start with that central bit and then decide what the next step will be and return/reschedule as needed.
recursive algorithms are a more difficult but you can solve that by adding an explicit stack that you push to on the recursive call and pop at return from that call