这是我对karatsuba算法的实现,
它在删除部分被注释时运行良好但是当我将其插入代码时,它会导致错误的输出!
(例如,对于测试n = 5,a = b = {1,2,3,4,5})
void conv(int a[], int b[], int c[], int n)
{
if (n == 1)
{
c[0] = a[0]*b[0];
return;
}
int *C0 = new int[n];
int *C1 = new int[n];
int *C2 = new int[n];
conv(a, b, C0, n/2);
conv(a + n/2, b + n/2, C1, n/2);
for (int i = 0; i < n/2; i++)
a[i] += a[i + n/2], b[i] += b[i + n/2];
conv(a, b, C2, n/2);
for (int i = 0; i < n/2; i++)
a[i] -= a[i + n/2], b[i] -= b[i + n/2];
for (int i = 0; i < n; i++)
{
c[i] += C0[i];
c[i + n] += C1[i];
c[i + n/2] += C2[i] - C1[i] - C0[i];
}
/* delete[] C0;
delete[] C1;
delete[] C2;*/
}
删除有什么问题?我是否以错误的方式释放了分配的内存? 提前谢谢!
答案 0 :(得分:0)
您可以将它们声明为向量,而不是将它们声明为指针,然后您不必担心删除。这里删除的问题在你的代码参数中,你实际上是将c作为指针发送,所以当你删除指针时,你仍然指向你删除的地址而不是值。
答案 1 :(得分:0)
在这个循环中:
for (int i = 0; i < n; i++) {
c[i] += C0[i];
c[i + n] += C1[i];
c[i + n/2] += C2[i] - C1[i] - C0[i];
}
您要添加从未初始化的c
元素。 (据推测,你打算将它们初始化为0,不是吗?)
我不知道你正在使用什么平台,但是我们假设它是一个平台,当没有内存被释放时,新的内存分配恰好全部为零,但是一旦释放内存分配,可以接收释放的分配,它将具有随机值。在这种情况下,删除delete
语句使得所有内存分配更有可能是新鲜的,而包含它们使得内存块很可能被回收。
无论如何,使用未初始化的值是未定义的行为。您应该明确地将新分配的C0
,C1
和C2
向量设置为0。
答案 2 :(得分:0)
您可以定义IntArray类,并在堆栈上创建它,而不是直接分配内存。通过这种方式,定义的类管理分配的内存本身。 (当它超出范围时,它释放其成员int数组'data'。)
class IntArray{
public:
int* data;
int n;
IntArray(int n){
this->n = n;
data = new int[n];
for(int i=0; i<n; i++){
data[i] = 0;
}
}
~IntArray(){
if(data != NULL){
delete[] data;
data = NULL;
}
}
};
void conv(int a[], int b[], IntArray &c, int n)
{
if (n == 1)
{
c.data[0] = a[0]*b[0];
return;
}
/*
int *C0 = new int[n];
int *C1 = new int[n];
int *C2 = new int[n];
*/
IntArray C0(n);
IntArray C1(n);
IntArray C2(n);
conv(a, b, C0, n/2);
conv(a + n/2, b + n/2, C1, n/2);
for (int i = 0; i < n/2; i++)
a[i] += a[i + n/2], b[i] += b[i + n/2];
conv(a, b, C2, n/2);
for (int i = 0; i < n/2; i++)
a[i] -= a[i + n/2], b[i] -= b[i + n/2];
for (int i = 0; i < n; i++)
{
c.data[i] += C0.data[i];
c.data[i + n] += C1.data[i];
c.data[i + n/2] += C2.data[i] - C1.data[i] - C0.data[i];
}
}