changeset 782:11f3101c1980

farray.sh: Implemented plain Insertionsort. Using the optimized algorithm already used in Shell sort, just without manx gaps and using only the fixed last step 1.
author Franz Glasner <fzglas.hg@dom66.de>
date Sat, 26 Oct 2024 18:35:37 +0200
parents aead7cf1cb9a
children 7d44112dfb81
files share/local-bsdtools/farray.sh tests/farray-array.t tests/sort-perf/sort-perf.sh
diffstat 3 files changed, 96 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/share/local-bsdtools/farray.sh	Sat Oct 26 14:09:47 2024 +0200
+++ b/share/local-bsdtools/farray.sh	Sat Oct 26 18:35:37 2024 +0200
@@ -1628,7 +1628,7 @@
     _farr_array_get_meta "$@"
 
     # XXX TBD: Select a method depenting on `__farr_len`.
-    _farr_array_gnomesort
+    _farr_array_insertionsort
 }
 
 
@@ -1695,6 +1695,66 @@
 
 
 #:
+#: Sort an array using Insertion Sort.
+#:
+#: Args:
+#:   $1: The array to sort to
+#:
+#: See Also:
+#:   `_farr_array_gnomesort`
+#:
+farray_insertionsort() {
+    local __farr_name
+
+    local __farr_token __farr_gvrname __farr_len \
+          __farr_pos __farr_val __farr_val_1
+
+    _farr_array_get_meta "$@"
+
+    _farr_array_insertionsort
+}
+
+
+#:
+#: Internal sort implementation using Insertion Sort.
+#:
+#: Stable: yes
+#:
+#: This is a very simple stable sort (a variant of insertion sort).
+#:
+#: See: https://en.wikipedia.org/wiki/Insertion_sort
+#:
+#: Input (Globals):
+#:   All the "Output (Globals)" from `farr_array_get_meta`:
+#:   __farr_name, __farr_token, __farr_gvrname and __farr_len.
+#:   These variables are declared local in this function but the shell
+#:   initializes them from the same variables in the nearest dynamic scope.
+#:   So they are really input variables and not also output variables.
+#:
+_farr_array_insertionsort() {
+
+    local __farr_name __farr_token __farr_gvrname __farr_len \
+          __farr_i __farr_j __farr_tmpitem __farr_tmpprevitem
+
+    __farr_i=2
+    while [ "${__farr_i}" -le "${__farr_len}" ]; do
+        # Save a[i] in temp and make a hole at position i
+        eval __farr_tmpitem=\"\$\{"${__farr_gvrname}"_"${__farr_i}"\}\"
+        __farr_j="${__farr_i}"
+        while [ "${__farr_j}" -gt 1 ]; do
+            eval __farr_tmpprevitem=\"\$\{"${__farr_gvrname}"_$((__farr_j - 1))\}\"
+            [ "${__farr_tmpprevitem}" = "${__farr_tmpitem}" ] || [ "${__farr_tmpprevitem}" '<' "${__farr_tmpitem}" ] && break
+            setvar "${__farr_gvrname}"_"${__farr_j}" "${__farr_tmpprevitem}"
+            __farr_j=$((__farr_j - 1))
+        done
+        # Put temp (the original a[i]) in its correct location
+        setvar "${__farr_gvrname}"_"${__farr_j}" "${__farr_tmpitem}"
+        __farr_i=$((__farr_i + 1))
+    done
+}
+
+
+#:
 #: Sort an array using Shell Sort.
 #:
 #: Args:
--- a/tests/farray-array.t	Sat Oct 26 14:09:47 2024 +0200
+++ b/tests/farray-array.t	Sat Oct 26 18:35:37 2024 +0200
@@ -1397,6 +1397,19 @@
   $ check_no_array_artifacts
 
   $ farray_create TEST 5 3 2 4
+  $ farray_insertionsort TEST
+  $ check_array_is_sorted "$TEST"
+  $ farray_debug TEST
+  DEBUG: array `TEST' has length 4
+  DEBUG:   the items:
+  DEBUG:     1: `2'
+  DEBUG:     2: `3'
+  DEBUG:     3: `4'
+  DEBUG:     4: `5'
+  $ farray_release TEST
+  $ check_no_array_artifacts
+
+  $ farray_create TEST 5 3 2 4
   $ farray_heapsort TEST
   $ check_array_is_sorted "$TEST"
   $ farray_debug TEST
@@ -1438,6 +1451,14 @@
   $ farray_splice "" TEST 1 "" UNSORTED
   $ check_array_is_sorted "$TEST"
   [1]
+  $ farray_insertionsort TEST
+  $ check_array_is_sorted "$TEST"
+  $ farray_release TEST
+
+  $ farray_create TEST
+  $ farray_splice "" TEST 1 "" UNSORTED
+  $ check_array_is_sorted "$TEST"
+  [1]
   $ farray_shellsort TEST
   $ check_array_is_sorted "$TEST"
   $ farray_release TEST
@@ -1945,5 +1966,3 @@
 =========
 
   $ check_no_local_artifacts
-
-  $ set
--- a/tests/sort-perf/sort-perf.sh	Sat Oct 26 14:09:47 2024 +0200
+++ b/tests/sort-perf/sort-perf.sh	Sat Oct 26 18:35:37 2024 +0200
@@ -50,6 +50,20 @@
 	echo "===> SKIPPED: Gnome Sort with ${1} items"
     fi
 
+
+    if [ "${1}" -le 2000 ]; then
+	farray_create TEST
+	farray_splice "" TEST 1 "" UNSORTED
+	echo "===> Insertion Sort with ${1} items"
+	get_ts
+	farray_insertionsort TEST
+	get_ts
+	check_array_is_sorted "$TEST" || fatal "sort failed"
+	farray_release TEST
+    else
+	echo "===> SKIPPED: Insertion Sort with ${1} items"
+    fi    
+
     if [ "${1}" -le 50000 ]; then
 	farray_create TEST
 	farray_splice "" TEST 1 "" UNSORTED