GoLang Program to Implement Shell Sort

GoLang Program to Implement Shell Sort

Sorting plays a big role in programming and computer science. Whether you’re organizing a list of numbers, arranging names alphabetically, or optimizing search operations, sorting makes data much easier to use. Among the many sorting algorithms available, Shell Sort stands out for its simplicity and efficiency. It’s like a smarter version of Insertion Sort, designed to move items over larger gaps to reach their correct positions faster.

Pluralsight Logo
Accelerate your tech career
with hands-on learning.
Whether you're a tech newbie or a total pro,
get the skills and confidence to land your next move.
Start 10-Day Free Trial

Shell Sort was developed by Donald Shell in 1959 and is considered one of the first algorithms to break the barrier between simple sorts like Bubble or Insertion Sort and more advanced ones like Merge or Quick Sort. It improves on Insertion Sort by comparing elements that are far apart, gradually reducing the gap between compared elements. This approach makes it faster for larger datasets while keeping the logic easy to understand and implement.

This algorithm is particularly useful when you need a sorting method that’s quicker than the basic ones but still easy to code. It’s often used in embedded systems, teaching, and scenarios where memory use needs to be minimal. Let’s explore how to implement Shell Sort in GoLang through different approaches that help you understand its working in depth.

Program 1: Basic Shell Sort in GoLang

This is the simplest form of Shell Sort. It uses a fixed gap reduction sequence where the gap starts as half of the array size and keeps reducing by half in each iteration until it reaches one.

package main

import "fmt"

func shellSort(arr []int) {

    n := len(arr)

    for gap := n / 2; gap > 0; gap /= 2 {

        for i := gap; i < n; i++ {

            temp := arr[i]
            j := i

            for ; j >= gap && arr[j-gap] > temp; j -= gap {
                arr[j] = arr[j-gap]
            }

            arr[j] = temp

        }

    }

}

func main() {

    numbers := []int{23, 12, 1, 8, 34, 54, 2, 3}

    fmt.Println("Original array:", numbers)

    shellSort(numbers)

    fmt.Println("Sorted array:", numbers)

}

This program starts by taking a gap equal to half of the array’s length. It then compares elements that are separated by this gap. If an element is smaller than its gap-based partner, they’re swapped. The gap keeps getting smaller, and by the time it becomes one, the array is nearly sorted, making the final pass very efficient. This basic approach helps beginners easily grasp the core logic of Shell Sort.

Program 2: Shell Sort Using Custom Gap Sequence

In this version, we use a custom gap sequence. Instead of simply dividing the gap by two, we use the Knuth sequence, which gives slightly better performance in practice. The sequence is generated using the formula gap = 3*gap + 1.

package main

import "fmt"

func shellSortCustom(arr []int) {

    n := len(arr)
    gap := 1

    for gap < n/3 {
        gap = 3*gap + 1
    }

    for gap > 0 {

        for i := gap; i < n; i++ {

            temp := arr[i]
            j := i

            for ; j >= gap && arr[j-gap] > temp; j -= gap {
                arr[j] = arr[j-gap]
            }

            arr[j] = temp

        }

        gap = (gap - 1) / 3

    }

}

func main() {

    numbers := []int{45, 12, 89, 33, 10, 72, 56, 8, 29}

    fmt.Println("Original array:", numbers)

    shellSortCustom(numbers)

    fmt.Println("Sorted array (custom gaps):", numbers)

}

This version of Shell Sort creates a smarter gap pattern that helps the algorithm perform fewer comparisons and movements overall. Beginners will find this approach interesting because it shows how tweaking one part of the algorithm — the gap sequence — can improve speed and efficiency. It’s a great example of practical algorithm optimization.

Program 3: Shell Sort Using Floating-Point Numbers

Here we apply Shell Sort to an array of floating-point numbers. The logic remains the same, but the data type changes. This example shows that the algorithm is flexible enough to handle different kinds of data.

package main

import "fmt"

func shellSortFloat(arr []float64) {

    n := len(arr)

    for gap := n / 2; gap > 0; gap /= 2 {

        for i := gap; i < n; i++ {

            temp := arr[i]
            j := i

            for ; j >= gap && arr[j-gap] > temp; j -= gap {
                arr[j] = arr[j-gap]
            }

            arr[j] = temp

        }

    }

}

func main() {

    numbers := []float64{3.4, 1.2, 5.6, 2.8, 0.9, 4.3}

    fmt.Println("Original array:", numbers)

    shellSortFloat(numbers)

    fmt.Println("Sorted array (floats):", numbers)

}

This program sorts floating-point numbers using the same logic as the integer version. It demonstrates the versatility of Shell Sort and helps beginners understand that the same algorithmic concept can be applied to different data types with minimal changes.

Program 4: Recursive Shell Sort

This version introduces recursion into the Shell Sort algorithm. While Shell Sort is typically written iteratively, this example shows how it can also be implemented recursively for better conceptual understanding.

package main

import "fmt"

func recursiveShellSort(arr []int, gap int) {

    n := len(arr)

    if gap == 0 {
        return
    }

    for i := gap; i < n; i++ {

        temp := arr[i]
        j := i

        for ; j >= gap && arr[j-gap] > temp; j -= gap {
            arr[j] = arr[j-gap]
        }

        arr[j] = temp

    }

    recursiveShellSort(arr, gap/2)

}

func main() {

    numbers := []int{78, 23, 45, 12, 9, 67, 34, 56}

    fmt.Println("Original array:", numbers)

    recursiveShellSort(numbers, len(numbers)/2)

    fmt.Println("Sorted array (recursive):", numbers)

}

In this program, the sorting logic remains the same, but instead of using loops to reduce the gap, recursion is used to call the function repeatedly with smaller gaps. It’s a neat twist that helps learners think differently about control flow and recursion in GoLang.

Frequently Asked Questions (FAQ)

Below are some common questions beginners often ask when learning Shell Sort.

Q1: What is Shell Sort used for?
Shell Sort is used for sorting medium-sized datasets where performance is needed without the complexity of advanced algorithms like Quick Sort or Merge Sort.

Q2: How does Shell Sort differ from Insertion Sort?
Shell Sort improves upon Insertion Sort by allowing the exchange of elements that are far apart, reducing the number of total shifts required.

Q3: Is Shell Sort stable?
No, Shell Sort is not stable because it can move equal elements past one another when large gaps are used.

Q4: What is the time complexity of Shell Sort?
The time complexity varies depending on the gap sequence used. It ranges between O(n log² n) and O(n²) for most cases.

Q5: Does Shell Sort work for all data types?
Yes, Shell Sort can be applied to integers, floats, or even strings — as long as comparisons between elements are defined.

Conclusion

Shell Sort is a wonderful blend of simplicity and performance. It’s much faster than basic sorting algorithms like Bubble Sort or Insertion Sort, yet still easy enough for beginners to understand. The idea of reducing the gap between compared elements makes it efficient and a great stepping stone toward learning more advanced sorting techniques.

By practicing Shell Sort in GoLang using loops, recursion, and custom gap sequences, you’ll gain a deeper understanding of how sorting algorithms evolve and why optimization matters. Keep exploring, try modifying the gap patterns, and observe how performance changes — that’s the best way to learn and grow as a programmer.

Scroll to Top