#!/bin/bash
# qsort - pure bash qsort implementation

set -e

######
# Settings

core_qsort_config_init() {
	lib_setting_vars qsort_compare_func

	qsort_compare_func=compare_str_asc
}

######
# Internal functions

qsort_stack_push() { qsort_stack+=( "$@" ); }
qsort_stack_pop() { qsort_stack=( "${qsort_stack[@]:2}" ); }


######
# Public interface

# $1 - Array to receive sorted items
# ... - Items to sort
qsort() {
	min_args 1 "$@"
	local result=$1
	shift

	[ $# -gt 0 ] || return 0

	local -a sorted=( "$@" )

	local -a qsort_stack
	local last=$(($# - 1))
	qsort_stack_push 0 $last

	local -a smaller larger
	while (( ${#qsort_stack[@]} )); do
		local a=${qsort_stack[0]}
		local b=${qsort_stack[1]}
		qsort_stack_pop

		local pivot=${sorted[$a]}

		local i
		smaller=()
		larger=()
		for ((i = a + 1; i <= b; i++)); do
			local value="${sorted[i]}"
			local name
			$qsort_compare_func "$value" "$pivot" \
				&& smaller+=( $value ) \
				|| larger+=( $value )
		done

		sorted=( \
			"${sorted[@]:0:a}" \
			"${smaller[@]}" "$pivot" "${larger[@]}" \
			"${sorted[@]:b + 1:last - b}" \
			)

		if ((${#smaller[@]} >= 2)); then
			qsort_stack_push $a $((a + ${#smaller[@]} - 1))
		fi
		if ((${#larger[@]} >= 2)); then
			qsort_stack_push $((b - ${#larger[@]} + 1)) $b
		fi
	done
	eval "$result=( \"\${sorted[@]}\" )"
}

# list_qsort - Sorts the list
qsort_list() {
	has_args 1 "$@"
	eval "qsort $1 \"\${$1[@]}\""
}


######
# Item comparison functions

compare_str_asc() { [[ "$1" < "$2" ]]; }
compare_str_dsc() { [[ "$1" > "$2" ]]; }

compare_int_asc() { (("$1" < "$2")); }
compare_int_dsc() { (("$1" > "$2")); }

compare_mtime() { [[ $1 -nt $2 ]]; }

View the Script Reference Index


Generated on Tue Apr 25 21:20:13 PDT 2017 by mcsh i7 v0.18.0.