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;i CUT< 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++。