【问题标题】:Implementation of Bottom Up Merge Sort自底向上归并排序的实现
【发布时间】:2021-09-26 06:02:36
【问题描述】:

我了解到归并排序是一种遵循分治原则的排序算法,平均时间复杂度为 n(log n)。

在这里,我将大小为 n 的数组划分为子数组(以长度 2 初始化),并通过对子数组进行排序来征服它。然后我们以 2 的倍数继续该范围,直到它小于数组的长度(即 2,4,8,....i 其中 i

当超过数组长度时,函数返回排序后的数组。

我使用了两个函数来实现归并排序:

  1. 归并排序(产生子数组)
  • 如果数组长度小于范围返回数组。
  • 递归并以指数方式增加范围。
  1. 插入排序(对子数组进行排序)
  • 使用插入排序对范围内的元素进行排序。我选择了插入排序,因为它比冒泡排序和选择排序更有效。

程序运行良好,我想知道我是否理解归并排序的概念并正确实现它?

//C++ Code
#include<iostream>

// Print
void print(int *arr, int length);

// To Sort the sub array
void insertion_sort(int *arr, int low, int high)
{
    for(int i = high; (i-1)>=low; i--)
    {
        if (arr[i] < arr [i-1])
        {
            int temp = arr[i];
            arr[i] = arr[i-1];
            arr[i-1] = temp;
        }
    }
}

int *merge_sort(int* arr, int length, int index = 2)
{
    if (length <= index) // Terminating Condition
    {
        return arr;
    }

    // The range is defined by index.

        /*
            If array has 8 elements:  ********
            It will sort array until it's range within the length of array.
            1st call  2*1 elements max: ** ** ** ** // 2 set as default argument
            2nd call  2*2 elements max: **** ****
            3rd call  2*3 elements max: ********
            Returns Array
        */

    // The range is defined by index.

    for(int i=0; (i+index)<length; i+=index)
    {
        // Divide and Sort
        insertion_sort(arr, i, i+index);
    }

    // The range will increase in multiple of 2 (i.e. 2,4,8,....i where i<length of array)
    return merge_sort(arr, length, index*2);
}

int main()
{
    int length;    
    std::cout<<"Length of Array: ";
    std::cin>>length;

    int arr[length];

    for(int i=0; i<length; i++)
    {
        std::cout<<"Enter element "<<i+1<<" : ";
        std::cin>>arr[i];
    }

    int *result = merge_sort(arr, length);
    
    print(result, length);
    
    return 0;
}

void print(int *arr, int length)
{
    std::cout<<"Sorted Array: ";

    for(int i=0; i<length; i++)
    {
        std::cout<<arr[i]<<" ";
    }

    std::cout<<"\n";
}

【问题讨论】:

  • int arr[length]; 不是标准 C++。不要使用变长数组,更喜欢std::vector
  • @Zoso 我更喜欢std::vector 以供将来实施。
  • 您的merge_sort 不会合并,也不会真正排序任何东西。它只是不必要地一遍又一遍地调用insertion_sort,而它本可以在整个阵列上调用它一次。归并排序算法的核心是归并操作,在线性时间内取两个排序数组并将它们组合成一个排序数组。相反,当你的实现对 8 元素数组进行排序时,它并没有利用 4 元素数组已经排序这一事实。以前的所有工作都浪费了。
  • 另外,您的代码对于输入 10 5 失败
  • @Zoso 您输入了 10 作为数组长度并且您只提供了第一个元素。我使用 for 循环来获取输入,因此它将一直循环,直到输入所有元素,尝试使用终端执行代码而不是在线 IDE。

标签: c++ arrays algorithm mergesort


【解决方案1】:

纯自底向上合并排序将一个包含 n 个元素的数组划分为 n 个大小为 1 的运行,然后每次遍历合并偶数和奇数运行。链接到 wiki 示例:

https://en.wikipedia.org/wiki/Merge_sort#Bottom-up_implementation

正如 Wiki 示例 cmets 中所建议的,每次通过时都可以更改合并的方向。以原始数组中的排序数据结束,计算所需的通过次数,如果通过次数为奇数,则比较并交换(如果需要)元素对以创建大小为 2 的运行,然后进行合并排序通过。

对于混合插入+归并排序,同样计算遍历次数,如果遍历次数为奇数,则将初始运行大小设置为 32 个元素,否则将初始运行大小设置为 64 个元素。使用插入排序对初始运行进行单遍排序,然后切换到合并排序。

获取通过次数的简单示例代码(对于 32 位构建,假设 n

size_t GetPassCount(size_t n)               // return # passes
{
    size_t i = 0;
    for(size_t s = 1; s < n; s <<= 1)
        i += 1;
    return(i);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-11
    • 1970-01-01
    • 2016-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多