C++ 尝试删除分配的数组l#u sorted和r#u sorted in c++;
下面是我实现mergesort算法的代码 它很有效。但当我尝试删除分配的数组l_sorted和r_sorted时,会发生错误。 错误为:malloc:*对象0x7fa7b3501330的错误:未分配要释放的指针 我找了很多,但没有找到任何解决办法 我怎样才能解决这个问题C++ 尝试删除分配的数组l#u sorted和r#u sorted in c++;,c++,recursion,C++,Recursion,下面是我实现mergesort算法的代码 它很有效。但当我尝试删除分配的数组l_sorted和r_sorted时,会发生错误。 错误为:malloc:*对象0x7fa7b3501330的错误:未分配要释放的指针 我找了很多,但没有找到任何解决办法 我怎样才能解决这个问题 #include <iostream> #include <stdlib.h> using namespace std; void merge(int L[],int R[],int size,int
#include <iostream>
#include <stdlib.h>
using namespace std;
void merge(int L[],int R[],int size,int *a_sorted, bool even)
{
if (even == 1)
{
int l=0,r=0;
for (int i=0;i<size*2;i++)
{
if ((L[l]<=R[r] && l<size) || (r>=size && l<size))
{
a_sorted[i]=L[l];
l++;
}
else
{
a_sorted[i]=R[r];
r++;
}
}
}
else
{
int l=0,r=0;
for (int i=0;i<size*2+1;i++)
{
if ((L[l]<=R[r] && l<size) || (r>=size+1 && l<size))
{
a_sorted[i]=L[l];
l++;
}
else
{
a_sorted[i]=R[r];
r++;
}
}
}
}
int* merge_sort(int a[],int size,int *a_sorted)
{
if (size == 1)
return a;
if(size%2==0)
{
int mid=size/2;
int *L=(a);
int *R=(a+mid);
int *l_sorted=new int[mid];
int *r_sorted=new int[mid];
l_sorted = merge_sort(L,mid,l_sorted);
r_sorted = merge_sort(R,mid,r_sorted);
merge(l_sorted,r_sorted,mid,a_sorted,1);
delete []l_sorted;
delete []r_sorted;
}
else{
int mid=size/2;
int *L=a;
int *R=a+mid;
int *l_sorted=new int[mid];
int *r_sorted=new int[mid+1];
l_sorted = merge_sort(L,mid,l_sorted);
r_sorted = merge_sort(R,mid+1,r_sorted);
merge(l_sorted,r_sorted,mid,a_sorted,0);
delete []l_sorted;
delete []r_sorted;
}
return a_sorted;
}
int main()
{
const int s=2;
clock_t start1=clock();
int *a=new int[s];
srand(time(0));
for (int i=0;i<s;i++){
a[i]=rand()%(s*2);
}
int *b=new int[s];
clock_t end1=clock();
clock_t start2=clock();
b=merge_sort(a,s,b);
clock_t end2=clock();
for (int i=0;i<s;i++){
cout<<b[i]<<endl;
}
cout<<"Time taken for mergesort: "<< (double)(end2-start2)/(CLOCKS_PER_SEC)<<endl;
cout<<"Time taken for generate: "<< (double)(end1-start1)/(CLOCKS_PER_SEC)<<endl;
}
#包括
#包括
使用名称空间std;
无效合并(整数L[],整数R[],整数大小,整数*a_排序,布尔偶数)
{
如果(偶数==1)
{
int l=0,r=0;
对于(int i=0;i首先,您的代码有什么问题。稍后我将对算法进行简化,但现在……在分而治之的两部分中,您都执行以下操作:
首先,将入站数组划分为左右两个子部分(以“偶数”块为例):
int mid=size/2;
int *L=(a);
int *R=(a+mid);
然后将两个大小相似的数组分配给分区
int *l_sorted=new int[mid];
int *r_sorted=new int[mid];
最后,调用递归。现在仔细查看作为第一个参数传递的内容:
l_sorted = merge_sort(L,mid,l_sorted);
r_sorted = merge_sort(R,mid,r_sorted);
但是L
和R
不能保证在这个函数中分配。事实上,R
根本不能保证在这个函数中分配,R
始终只是L
数组中的一些偏移量。现在看看递归的基中返回了什么n(递归停止并弹出的情况):
这意味着如果长度为1,则返回的结果是L
或R
。但是R
不是分配;它是到另一个数组(可能是分配)的偏移量。因此,执行此操作时:
r_sorted = merge_sort(R,mid,r_sorted);
您刚刚更改了r\u排序
指向的内容。它不再指向您所做的分配。现在它指向l\u排序
数组中某个偏移量,而不是调用堆栈中较高的一步。因此,boom。在l\u排序
分配上也会发生同样的情况,但在这种情况下,当您分配inbou时你实际上做了两件事:
泄漏同一激活范围内的原始分配(同一函数调用)
删除调用者传入的数组(作为a[]传入的数组)
我不应该,瓦尔格兰会抓到很多这样的东西
如果你想做的是自上而下的合并排序,有相当简单的方法。但是传统的自下而上的方法更容易理解,下面将展示
传统的自底向上合并排序
在编写递归算法时,很少有这样的情况:在问题上抛出更多的代码,除了会导致更大的问题外,还会导致其他任何问题,这也不例外。您将这一点变得太复杂了。从merge函数开始
合并应采用三个参数。段底、中点偏移和总长度:
void merge(int ar[], int mid, int len)
有两段正在排序:
a[0] ... a[mid-1]
a[mid] ... a[len-1]
使用非就地合并执行此操作所需的临时空间量是len
(请相信我;此时,您不想尝试编写就地算法)。偶数边界专门化代码是完全没有必要的。尽管很难相信,以下是传统合并排序中最难的部分,这里没有太多:
merge()
:长版本
void merge(int a[], int mid, int len)
{
int *tmp = new int[len];
int i=0, j=mid, k=0;
while (i<mid && j<len)
{
// x will reference the index (i or j) we're bumping
int& x = (a[i] < a[j]) ? i : j;
tmp[k++] = a[x++];
}
// one of the two segments didn't finish. we don't really care which
// one, as we'll be ensuring *both* did.
while (i < mid)
tmp[k++] = a[i++];
while (j < len)
tmp[k++] = a[j++];
// tmp[] is now fully sorted. just dump the content back
// into a[]; *all of it*.
for (i=0; i<len; ++i)
a[i] = tmp[i];
// delete temp space
delete [] tmp;
}
void merge(int a[], int mid, int len)
{
std::vector<int> tmp;
tmp.reserve(len);
std::merge(a, a+mid, a+mid, a+len, std::back_inserter(tmp));
std::copy(tmp.begin(), tmp.end(), a);
}
merge()
:最短版本
void merge(int a[], int mid, int len)
{
int *tmp = new int[len];
int i=0, j=mid, k=0;
while (i<mid && j<len)
{
// x will reference the index (i or j) we're bumping
int& x = (a[i] < a[j]) ? i : j;
tmp[k++] = a[x++];
}
// one of the two segments didn't finish. we don't really care which
// one, as we'll be ensuring *both* did.
while (i < mid)
tmp[k++] = a[i++];
while (j < len)
tmp[k++] = a[j++];
// tmp[] is now fully sorted. just dump the content back
// into a[]; *all of it*.
for (i=0; i<len; ++i)
a[i] = tmp[i];
// delete temp space
delete [] tmp;
}
void merge(int a[], int mid, int len)
{
std::vector<int> tmp;
tmp.reserve(len);
std::merge(a, a+mid, a+mid, a+len, std::back_inserter(tmp));
std::copy(tmp.begin(), tmp.end(), a);
}
根本不编写合并,只需使用:
std::inplace_merge(a, a+len/2, a+len);
无论您使用哪种方法,结果合并排序算法都会变为以下,所有偶数与奇数分区逻辑都会被抑制。请注意,这使用简单的指针算法来指定rhs段的起始位置,该位置始终为a+len/2
void mergesort(int a[], int len)
{
if (len < 2)
return;
mergesort(a, len/2);
mergesort(a+len/2, len-len/2);
merge(a, len/2, len); // or use std::inplace_merge(a, a+len/2, a+len);
}
样本输出(明显不同)
我只能希望这能有所帮助。有一些明显的方法可以使这更有效,有些方法比其他方法更明显。例如,你知道你永远不会需要超过len
的额外空间,因此你可以在算法潜入之前分配整个临时空间,并在以后的每次调用中对其进行参数化。这将消除l只有一个内存分配。您可以通过使用更智能的分配(例如使用std::vector的更短的merge()
算法)进一步使此RAII基于内存分配。值得思考。请正确缩进您的代码。您的问题是{l,r}_已排序
获得不同的值。l\u排序=合并\u排序(…)。你必须记住你原来的LL排序是如何删除它的。因为这是标记C++,也许你不应该使用数组,而不是<代码> STD::向量< /代码>。这会让你的生活更容易。我必须问。为什么你要用特殊的外壳甚至边界分区来让你的生活变得如此的可笑?不仅仅是TH。没有必要这样做,最终没有任何好处。合并的最终结果总是基于“第一个”完成的段(显然,一个总是这样),剩下的列表只是简单地连接在一起。lhs和rhs段长度应该是len/2
和(len-len/2)
如果它们是相同的,就这样吧,如果它们不是,谁在乎呢。谢谢你的建议。我是编程新手,从你的实现中我可以学到很多东西。但是你能帮我指出为什么我的delete[]l_排序/delete[]r_排序不起作用??谢谢你进来advance@Young当然可以。我会更新问题。我需要一分钟:
18 26 38 55 12 38 31 35 46 32 14 26 42 3 10 13 37 21 24 21 11 15 55 10 55 19 47 19 28 53
3 10 10 11 12 13 14 15 18 19 19 21 21 24 26 26 28 31 32 35 37 38 38 42 46 47 53 55 55 55
Time taken for generate: 6.1e-05
Time taken for mergesort: 1e-05