基础排序(四)

作者: SmallRookie | 来源:发表于2017-08-04 02:20 被阅读26次
希尔排序(Shell Sort)

算法思想:先将待排序表分割成若干个形如L[i, i+d, i+2d, ... , i+kd]的“特殊”子表,分别进行插入排序,当整个表中元素已呈“基本有序”时,再对全体记录进行一次插入排序。

算法图解:

希尔排序

注:图片来自Lyndon的专栏,如若侵权请联系本人删除,谢谢!

基本代码如下:

template<typename T>
void shellSort(T arr[], int n) {

    // Incremnet表示增量
    int i, j, Increment;
    T tmp;
    // 增量变化
    for (Increment = n / 2; Increment > 0; Increment /= 2) {
        // 在增量为某个值时,进行插入排序
        for (i = Increment; i < n; ++i) {
            tmp = arr[i];
            for (j = i; j >= Increment; j -= Increment) {
                if (tmp < arr[j - Increment])
                    arr[j] = arr[j - Increment];
                else
                    break;
            }
            arr[j] = tmp;
        }
    }
}

为了和选择排序、插入排序、冒泡排序比较算法效率,故分别创建SelectionSort.h文件、InsertionSort.h和BubbleSort.h文件,并分别添加如下代码:

// SelectionSort.h

#include <iostream>

using namespace std;

template<typename T>
void selectionSort(T arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        // 寻找[i, n)区间里的最小值
        int minIndex = i;
        for (int j = i + 1; j < n; j++) {
            if (arr[j] < arr[minIndex])
                minIndex = j;
        }
        if (minIndex != i)
            swap(arr[i], arr[minIndex]);
    }
}
// InsertionSort.h

#include <iostream>

using namespace std;

template<typename T>
void insertionSort(T arr[], int n) {

    for (int i = 1; i < n; i++) {
        // 寻找元素arr[i]合适的插入位置

        T e = arr[i];
        // j保存元素e应该插入的位置
        int j;
        for (j = i; j > 0 && arr[j - 1] > e; j--) {
            arr[j] = arr[j - 1];
        }
        arr[j] = e;
    }
}
// BubbleSort.h

#include <iostream>

using namespace std;

template<typename T>
void bubbleSort(T arr[], int n) {

    for (int i = 0; i < n - 1; ++i) {
        // 表示本趟冒泡是否发生交换的标志
        bool flag = false;
        for (int j = n - 1; j > i; --j) {
            if (arr[j - 1] > arr[j]) {
                swap(arr[j - 1], arr[j]);
                flag = true;
            }
        }
        // 本趟遍历后没有发生交换,说明已有序
        if (flag == false) return;
    }
}

好了,我们在main()中调用这几个算法比较一下它们的性能,具体代码如下:

int main(void) {

    int n = 10000;
    int *arr_1 = SortTestHelper::generateRandomArray(n, 0, n);
    int *arr_2 = SortTestHelper::copyIntArray(arr_1, n);
    int *arr_3 = SortTestHelper::copyIntArray(arr_1, n);
    int *arr_4 = SortTestHelper::copyIntArray(arr_1, n);

    SortTestHelper::testSort("Shell Sort", shellSort, arr_1, n);
    SortTestHelper::testSort("Insertion Sort", insertionSort, arr_2, n);
    SortTestHelper::testSort("Selection Sort", selectionSort, arr_3, n);
    SortTestHelper::testSort("Bubble Sort", bubbleSort, arr_4, n);

    delete[] arr_1;
    delete[] arr_2;
    delete[] arr_3;
    delete[] arr_4;
    return 0;
}

其运行结果如下:

Shell Sort : 0.003 s
Insertion Sort : 0.124 s
Selection Sort : 0.187 s
Bubble Sort : 0.866 s

从结果中,我们发现希尔排序在随机数组的情况下,其运行效率比之前我们学习的排序算法的效率都高。那么我们不禁想问希尔排序在处理近乎有序的数据时,其效率也会这么高吗?为此,我们调用generateNearlyOrderdArray()来测试一下,其代码如下:

int main(void) {

    int n = 10000;
    int *arr_1 = SortTestHelper::generateNearlyOrderdArray(n, 100);
    int *arr_2 = SortTestHelper::copyIntArray(arr_1, n);
    int *arr_3 = SortTestHelper::copyIntArray(arr_1, n);
    int *arr_4 = SortTestHelper::copyIntArray(arr_1, n);

    SortTestHelper::testSort("Shell Sort", shellSort, arr_1, n);
    SortTestHelper::testSort("Insertion Sort", insertionSort, arr_2, n);
    SortTestHelper::testSort("Selection Sort", selectionSort, arr_3, n);
    SortTestHelper::testSort("Bubble Sort", bubbleSort, arr_4, n);

    delete[] arr_1;
    delete[] arr_2;
    delete[] arr_3;
    delete[] arr_4;
    return 0;
}

其运行结果如下:

Shell Sort : 0.002 s
Insertion Sort : 0.003 s
Selection Sort : 0.293 s
Bubble Sort : 0.344 s

从结果中,我们发现希尔排序在处理近乎有序的数据时,仍然可以保证高效率。因此,我们在处理近乎有序的数据时,不仅推荐使用插入排序,也推荐希尔排序。

相关文章

  • 基础排序(四)

    希尔排序(Shell Sort) 算法思想:先将待排序表分割成若干个形如L[i, i+d, i+2d, ... ,...

  • Excel 2016 For Mac 数据透视表基础应用四

    Excel 2016 For Mac 数据透视表基础应用四——排序、筛选与切片器一、使用排序筛选1、自定义排序顺序...

  • 开发者应该掌握的几种排序算法

    该篇文章主要介绍了算法基础以及几种常见的排序算法:选择排序、插入排序、冒泡排序、快速排序、堆排序。 一、算法基础 ...

  • 算法-排序算法总结

    排序类型总结 1 排序算法基础实现 2 排序算法应用 2.1 基础排序 2.2 计数排序应用 2.3 快排应用 2...

  • Java常见排序基础 - 中

    在Java常见排序基础 - 上中主要介绍了冒泡排序、选择排序、插入排序三种基础排序,本篇文章主要介绍的是 快速排序...

  • c++day09

    插入排序基础版(后插1) 插入排序基础版(后插2) 改进 插入排序基础版(前插) 字符数组 ASCII 的 A =...

  • 数据结构与算法-排序/二分查找

    算法中基础中的基础,排序/二分查找 排序 1.快排QuickSort 归并排序 堆排序 1. 二分查找

  • 排序算法总结

    基础排序算法 基础排序算法相关接口和实现类 接口: 实现类(后续排序的父类): 1.选择排序 两层循环:内层循环进...

  • C#入门(数组排序,二维数组,锯齿数组,输出蛇形矩阵)

    数组排序 冒泡排序 冒泡排序是数组的基础排序方法 int[] intArray = { 1, 5, 5, 79, ...

  • 排序算法

    概述 一般排序算法(以元素比较为基础) => 快速排序、归并排序、插入排序、冒泡排序、堆排序 特殊排序算法 => ...

网友评论

    本文标题:基础排序(四)

    本文链接:https://www.haomeiwen.com/subject/ykgmlxtx.html