The list insertion sort algorithm is a variant of direct insertion sorting. Its Improvement aims to reduce the number of moves in the direct insertion sorting (of course, this improvement does not reduce the complexity, but still O (N ^ 2 )), therefore, a static linked list is appended to the original input data. (to reduce space consumption, the static linked list is simulated by using an equal-length subscript array link, instead of establishing an equi-long dynamic link structure ). The disadvantage of this algorithm is that, although the number of moves is reduced, an equal-length link array needs to be added, so space is also used for time.
Set the input array to V []. In the ascending order, set the element value of I at a certain position in link [] of the static linked list to X = V [I]. link [I] stores the position value J of the next element x that is larger than Y = V [J], that is, link [I] = J. Each time you insert a new element z = V [I] to the sorted list on the left, compare it from the head position in the Child sequence in the order on the left (Note: In the following implementation, head does not necessarily point to the first element !), Search for the lower mark value of the link until the value V [curr] of an element is found to be greater than (to ensure the stability of the algorithm, it must be greater than but not greater than or equal to) Z, in this case, the last position pointer of the curr pointer is next. To insert Z to the next and curr, you only need to modify: Next points to Z, and Z points to curr. The pointer value of the rightmost element in the sorted list is always-1, which serves as the tail flag.
Because the obtained static linked list cannot be randomly accessed as an array that directly stores the key value, therefore, at the end of list insertion sort, you need to convert V [] to a static array in ascending order Based on Link [] (the element in the static array here is the key value ). The conversion method adopts the in-place method, so that no extra space is required. The specific method is to find the link's bottom mark value starting from the head, and the found key value is exchanged with the rightmost element of the left-side sub-array (here the sub-array is already a static array in ascending order ), for example, set the rightmost element of the Child array on the left to I = 2, V [I] = 30, link [I] = 5, and the subscript OF THE found key value to curr = 6, V [curr] = 20, link [curr] = 7, then after switching V [I] = 20, link [I] = 6 (note not 7 !), V [curr] = 30, link [curr] = 5, here link [I] = 6 indicates that the subsequent operation "the elements at the first 2nd locations have been moved to the second", remember to write down the next = link [curr] = 7 pointer before switching, that is, as the key position value of the next operation, curr.
Java implementation:
/** * * List Insertion Sort algorithm * (Adapted from http://en.wikipedia.org/wiki/Insertion_sort) * * * Copyright (c) 2011 ljs (http://blog.csdn.net/ljsspace/) * Licensed under GPL (http://www.opensource.org/licenses/gpl-license.php) * * @author ljs * 2011-07-20 * */public class ListInsertionSort { public static void sort(int[] v){ int n = v.length; //step 1: link[] creation int[] link = new int[n]; int head=0; int next=0,curr=0; link[0] = -1; for(int i=1;i<n;i++){ if(v[head]>v[i]){ //case: head is changed to i link[i] = head; head = i; //change head }else{ //two stop cases: //curr == -1: when we reach the tail //v[curr] > v[i]: insert i before curr, next is the predecessor of curr //note: this loop executes at least once so 'next' always have valid value for (curr = head ; curr != -1 && v[curr] <= v[i]; curr = link[curr]) next =curr; //insert i between next and curr (also applicable to tail case when curr=-1) link[next] = i; link[i] = curr; } } //step 2: arrange v[] by link[] information: find curr and swap it with i curr = head; //to scan linked list, always start with head //note the difference: //in this step: between iterations, curr doesn't start with head at the beginning //the link creation step: between iterations, we always scan from curr=head to find the insert position for (int i=0 ;i<n;i++){ while(curr < i) curr = link [curr]; //look only those elements on the right side of current element next = link[curr]; //save for next iteration's start position if (curr != i) { //if curr==i, no need change since position i is done. int swap = v[i]; //swap key v[i] = v[curr]; v[curr] = swap; link[curr] = link[i]; //copy i's link link[i] = curr; //reset pointer link[i] for redirection } curr = next; //next iteration we start from 'next' } //link[] is now useless, let it be garbage collected. } public static void main(String[] args) { int[] v = {49,38,65,97,76,13,27,49}; ListInsertionSort.sort(v); for(int key:v){ System.out.format(" %d",key); }}}
Implementation of C version :( slightly modify the code on Wikipedia: http://en.wikipedia.org/wiki/Insertion_sort)
#include <stdio.h>#include <stdlib.h>void ListinsertSort(int * v, int n) {int * link = (int *)malloc(sizeof(int)*n);int head =0;int next,cur,i;link[0] = -1;//generate sorted static list: after sorting, head may not be the first elementfor (i = 1 ; i < n; i++){ if (v[head] > v[i]){ link[i] = head; head = i;} else { for (cur = head ; cur != -1 && v[cur] <= v[i]; cur = link[cur]) next =cur; link[next] = i; link[i] = cur;}}cur = head; //start with headfor ( i = 0 ;i < n;i++){while(cur < i) cur = link [cur]; //look only those elements on the right side of current elementnext = link[cur]; //save for next iterationif (cur != i) {int swap = v[i]; //swap keyv[i] = v[cur];v[cur] = swap;link[cur] = link[i]; //swap linklink[i] = cur;}cur = next;}free(link); }int main(void) {int i;int* v = (int *)malloc(sizeof(int)*5);v[0]=3;v[1]=2;v[2]=1;v[3]=0;v[4]=5;ListinsertSort(v, 5);for(i=0;i<5;i++){ printf(" %d",v[i]);}free(v); return 0;}