Insertion sort: Difference between revisions
Jump to navigation
Jump to search
→Variants: clarification about linked list weakness |
→Implmentation: fix a typo |
||
| Line 17: | Line 17: | ||
* Simple implementation: [[Jon Bentley (computer scientist)|Jon Bentley]] shows a version that is three lines in [[C (programming language)|C]]-like pseudo-code, and five lines when [[Program optimization|optimized]].<ref name="pearls"/> | * Simple implementation: [[Jon Bentley (computer scientist)|Jon Bentley]] shows a version that is three lines in [[C (programming language)|C]]-like pseudo-code, and five lines when [[Program optimization|optimized]].<ref name="pearls"/> | ||
* Efficient for (quite) small data sets, much like other quadratic (i.e., [[big O notation|O]](''n''<sup>2</sup>)) sorting algorithms | * Efficient for (quite) small data sets, much like other quadratic (i.e., [[big O notation|O]](''n''<sup>2</sup>)) sorting algorithms | ||
* | * May be more efficient in practice than most other simple quadratic algorithms such as [[selection sort]] or [[bubble sort]] {{ndash}} but relative incoming data order and read/write costs matter {{ndash}} with high exchange costs and randomly ordered data, [[selection sort]] is faster<ref>{{cite book |last=Sedgewick |first=Robert |author-link=Robert Sedgewick (computer scientist) |year=2011 |title=Algorithms |publisher=Addison-Wesley |isbn=978-0-321-57351-3 |page=248,250}}</ref> | ||
* [[Adaptive sort|Adaptive]], i.e., efficient for data sets that are already substantially sorted: the [[time complexity]] is [[big O notation|O]](''kn'') when each element in the input is no more than {{mvar|k}} places away from its sorted position | * [[Adaptive sort|Adaptive]], i.e., efficient for data sets that are already substantially sorted: the [[time complexity]] is [[big O notation|O]](''kn'') when each element in the input is no more than {{mvar|k}} places away from its sorted position | ||
* [[Stable sort|Stable]]; i.e., does not change the relative order of elements with equal keys | * [[Stable sort|Stable]]; i.e., does not change the relative order of elements with equal keys | ||
| Line 100: | Line 100: | ||
It does not make the code any shorter, it also does not reduce the execution time, but it increases the additional memory consumption from {{math|O(1)}} to {{math|O(N)}} (at the deepest level of recursion the stack contains {{math|N}} references to the {{code|A}} array, each with accompanying value of variable {{code|n}} from {{math|N}} down to 1). | It does not make the code any shorter, it also does not reduce the execution time, but it increases the additional memory consumption from {{math|O(1)}} to {{math|O(N)}} (at the deepest level of recursion the stack contains {{math|N}} references to the {{code|A}} array, each with accompanying value of variable {{code|n}} from {{math|N}} down to 1). | ||
==Implementation== | |||
Below is an implementation in [[C (programming language)|C]]. | |||
<syntaxhighlight lang="c"> | |||
// Sorts the array in ascending order using insertion sort. | |||
void insertionSort(int a[], int n) { | |||
// We treat a[0..i-1] as the sorted part, and a[i..end] as unsorted. | |||
for (int i = 1; i < n; i++) { | |||
int key = a[i]; // The value we want to insert into the sorted prefix. | |||
int j = i - 1; | |||
// Shift larger elements one position to the right | |||
// until we find where 'key' belongs. | |||
while (j >= 0 && a[j] > key) { | |||
a[j + 1] = a[j]; | |||
j--; | |||
} | |||
// Place 'key' into the gap created by shifting. | |||
a[j + 1] = key; | |||
} | |||
} | |||
</syntaxhighlight> | |||
==Best, worst, and average cases== | ==Best, worst, and average cases== | ||
| Line 187: | Line 210: | ||
If the items are stored in a linked list, then the list can be sorted with O(1) additional space. The algorithm starts with an initially empty (and therefore trivially sorted) list. The input items are taken off the list one at a time, and then inserted in the proper place in the sorted list. When the input list is empty, the sorted list has the desired result. | If the items are stored in a linked list, then the list can be sorted with O(1) additional space. The algorithm starts with an initially empty (and therefore trivially sorted) list. The input items are taken off the list one at a time, and then inserted in the proper place in the sorted list. When the input list is empty, the sorted list has the desired result. | ||
<syntaxhighlight lang="c | <syntaxhighlight lang="c"> | ||
struct | struct LinkedList { | ||
{ | int value; | ||
struct LinkedList* next; | |||
}; | |||
struct LinkedList* sortList(struct LinkedList* list) { | |||
// zero or one element in list | // zero or one element in list | ||
if ( | if (list == NULL || list->next == NULL) { | ||
return | return list; | ||
} | |||
// head is the first element of resulting sorted list | // head is the first element of resulting sorted list | ||
struct | struct LinkedList* head = NULL; | ||
while ( | while (list != NULL) { | ||
struct | struct LinkedList* current = list; | ||
list = list->next; | |||
if (head == NULL || current-> | if (head == NULL || current->value < head->value) { | ||
// insert into the head of the sorted list | // insert into the head of the sorted list | ||
// or as the first element into an empty sorted list | // or as the first element into an empty sorted list | ||
current-> | current->next = head; | ||
head = current; | head = current; | ||
} else { | } else { | ||
// insert current element into proper position in non-empty sorted list | // insert current element into proper position in non-empty sorted list | ||
struct | struct LinkedList* p = head; | ||
while (p != NULL) { | while (p != NULL) { | ||
if (p-> | // check last element of the sorted list and middle of the list | ||
if (p->next == NULL || current->value < p->next->value) { | |||
// insert into middle of the sorted list or as the last element | // insert into middle of the sorted list or as the last element | ||
current-> | current->next = p->next; | ||
p-> | p->next = current; | ||
break; // done | break; // done | ||
} | } | ||
p = p-> | p = p->next; | ||
} | } | ||
} | } | ||
| Line 226: | Line 253: | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
struct | struct LinkedList* sortList(struct LinkedList* list) { | ||
{ | // zero or one element in list | ||
if (list == NULL || list->next == NULL) { | |||
return list; | |||
} | } | ||
// build up the sorted array from the empty list | |||
struct LinkedList* sorted = NULL; | |||
// take items off the input list one by one until empty | |||
while (list != NULL) { | |||
// remember the head | |||
struct LinkedList* head = list; | |||
// trailing pointer for efficient splice | |||
struct LinkedList** trail = &sorted; | |||
// pop head off list | |||
list = list->next; | |||
// splice head into sorted list at proper place | |||
// does 'head' belong here? | |||
while (!(*trail == NULL || head->value < (*trail)->value)) { | |||
// no - continue down the list | |||
trail = &(*trail)->next; | |||
} | |||
head->next = *trail; | |||
*trail = head; | |||
} | |||
return sorted; | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||