C++ 在合并排序算法中,在数组合并后释放左、右子数组是否会对空间复杂度产生影响?

C++ 在合并排序算法中,在数组合并后释放左、右子数组是否会对空间复杂度产生影响?,c++,algorithm,sorting,mergesort,space-complexity,C++,Algorithm,Sorting,Mergesort,Space Complexity,在“合并排序”的一个教程视频中提到,一旦左右子数组必须合并到父数组,为了降低空间复杂度,我们需要释放为左右子数组分配的内存。但无论何时我们从函数调用中出来,局部变量都会被销毁。如果我错了,请纠正我。那么,释放记忆的行动会有什么不同吗 以下是我编写的代码: #include <iostream> #include <bits/stdc++.h> using namespace std; void mergeArr(int *rarr, int *larr, int *a

在“合并排序”的一个教程视频中提到,一旦左右子数组必须合并到父数组,为了降低空间复杂度,我们需要释放为左右子数组分配的内存。但无论何时我们从函数调用中出来,局部变量都会被销毁。如果我错了,请纠正我。那么,释放记忆的行动会有什么不同吗

以下是我编写的代码:

#include <iostream>
#include <bits/stdc++.h>

using namespace std;

void mergeArr(int *rarr, int *larr, int *arr, int rsize, int lsize) {
    int i = 0, r = 0, l = 0;

    while (r < rsize && l < lsize) {
        if (rarr[r] < larr[l]) {
            arr[i++] = rarr[r++];
        } else {
            arr[i++] = larr[l++];
        }
    }
    while (r < rsize) {
        arr[i++] = rarr[r++];
    }
    while (l < lsize) {
        arr[i++] = larr[l++];
    }
}

void mergeSort(int *arr, int length) {
    if (length > 1) {
        int l1 = length / 2;
        int l2 = length - l1;
        int rarr[l1], larr[l2];

        for (int i = 0; i < l1; i++) {
            rarr[i] = arr[i];
        }
        for (int i = l1; i < length; i++) {
            larr[i - l1] = arr[i];
        }

        mergeSort(rarr, l1);
        mergeSort(larr, l2);
        mergeArr(rarr, larr, arr, l1, l2);
        // will free(rarr); free(larr); make any difference in space complexity
    }
}

int main() {
    int arr[5] = { 1, 10, 2, 7, 5 };
    mergeSort(arr, 5);
    for (int i = 0; i < 5; i++)
        cout << arr[i] << " ";
}
#包括
#包括
使用名称空间std;
无效合并arr(int*rarr,int*larr,int*arr,int rsize,int lsize){
int i=0,r=0,l=0;
而(r1){
int l1=长度/2;
int l2=长度-l1;
int-rarr[l1],larr[l2];
对于(int i=0;iCUT< P>释放临时数组不影响空间复杂度,因为我们必须考虑最大内存消耗-它是关于初始数组的大小。< /P>

从性能的角度来看,在排序开始时临时分配一次存储似乎是合理的,在每个阶段重用它,并在完成所有工作之后释放它。

释放临时数组不会影响空间复杂度,因为我们必须考虑最大内存消耗-它是关于初始数组的大小。>

从性能的角度来看,在排序开始时临时分配一次存储似乎是合理的,在每个阶段重用它,并在完成所有工作之后释放它。

< P>我有很多事情要说。更多的是从C++ POV:

<>代码> int rARR [L1],LRR[L2];< /C> >这是一个C++提供的扩展,在其他编译器中是无效的。你应该做<代码> int *rARR = new int [L1];< /Cord>,或者更好地使用<代码>:ST::vector < /C> >:<代码> STD::向量RARR(L1)< /C> >
  • 如果您正在执行前者(使用
    new
    动态分配,即
    int*rarr=new int[l1]
    ),则必须自己管理内存。因此,当您使用完内存后,必须将其删除:
    delete[]RARR < /代码>注意,代码> Malc C < /C> >代码>免费< /COD>不是C++,它们是C.<代码>新< /COD>和 Dele> <代码>是分配/释放内存的C++方式。
    
  • 如果使用向量,C++将处理内存的删除/分配,因此不必担心。 现在回到你最初的问题:这样的想法是否会改善你的空间复杂性:答案是,不会


    为什么?想想你正在使用的最大临时存储空间。检查递归的第一种情况。你正在使用的空间不是
    O(N)
    ?因为larr和rarr的大小都是
    N/2
    。此外,空间复杂度是
    O(N)
    假设临时存储正在被释放。如果以某种方式未释放空间,则空间复杂性将增加到
    O(N)+2*(N/2)+4*O(N/4)…
    O(Nlog2N)因为递归的每一步都在分配一些不可冻结的空间。

    < P>我有很多事情要说。更多的是从C++ POV:

    <>代码> int rARR [L1],LRR[L2];< /C> >这是一个C++提供的扩展,在其他编译器中是无效的。你应该做<代码> int *rARR = new int [L1];< /Cord>,或者更好地使用<代码>:ST::vector < /C> >:<代码> STD::向量RARR(L1)< /C> >
  • 如果您正在执行前者(使用
    new
    动态分配,即
    int*rarr=new int[l1]
    ),则必须自己管理内存。因此,当您使用完内存后,必须将其删除:
    delete[]RARR < /代码>注意,代码> Malc C < /C> >代码>免费< /COD>不是C++,它们是C.<代码>新< /COD>和 Dele> <代码>是分配/释放内存的C++方式。
    
  • 如果使用向量,C++将处理内存的删除/分配,因此不必担心。 现在回到你最初的问题:这样的想法是否会改善你的空间复杂性:答案是,不会


    为什么?想想你正在使用的最大临时存储空间。检查递归的第一种情况。你正在使用的空间不是
    O(N)
    ?因为larr和rarr的大小都是
    N/2
    。此外,空间复杂度是
    O(N)
    假设临时存储正在被释放。如果以某种方式未释放空间,则空间复杂性将增加到
    O(N)+2*(N/2)+4*O(N/4)…
    O(Nlog2N)
    因为递归的每一步都在分配一些空间,而不是释放空间。

    在您的实现中,左数组和右数组是用自动存储定义的,因此当函数返回时,释放是自动的,但它会带来两个问题:

    • 足够大的数组将调用未定义的行为,因为使用自动存储分配太多空间将导致堆栈溢出
    • 可变大小的数组不是标准C++。