我被要求将此伪代码转换为C程序:
rep := 0
while A not empty:
B := []
for x in A, y in A:
if x != y: append absolute_value(x - y) to B
A := B
rep := rep + 1
最后我得到了这个
int iterateIt(int a_count, int* a) {
unsigned long long i, j, k;
unsigned long long count = a_count;
for( i = 1 ; i < a_count ; i++ )
count *= count-1;
int *b = (int *) malloc(count * sizeof(int));
count = 0;
k = 0;
for( i = 0 ; i < a_count ; i++ ){
for( j = i ; j < a_count ; j++ ){
if(a[i] != a[j]){
b[k] = abs(a[i] - a[j]);
k++;
}
}
}
if( k > 0){
return 1 + iterateIt(k, b);
}
free(b);
return 1;
}
我使用了递归来返回算法的迭代次数。实际上,我将A的任意两个不同对象之间的差值放在B上,然后将绝对值放在B上。
对于简单的输入,我会得到正确的结果,但是我不明白为什么输入如下内容:
16
1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768
或4
1 352 9483 50000
(第一个数字是A的元素数)
我遇到了细分错误错误。
谢谢您的帮助
答案 0 :(得分:1)
我认为您的count
是错误的。您的第二次迭代已经非常庞大。
#include <stdio.h>
#include <stdlib.h>
size_t total_allocated = 0;
int iterateIt(int a_count, int* a) {
unsigned long long i, j, k;
unsigned long long count = a_count;
for( i = 1 ; i < a_count ; i++ )
count *= count-1;
size_t size = count * sizeof(int);
printf("Allocating %llu ints: %llu bytes\n", count, (unsigned long long)size);
total_allocated += size;
printf("Total allocated: %llu bytes\n", (unsigned long long)total_allocated);
int *b = (int *) malloc(count * sizeof(int));
count = 0;
k = 0;
for( i = 0 ; i < a_count ; i++ ){
for( j = i ; j < a_count ; j++ ){
if(a[i] != a[j]){
b[k] = abs(a[i] - a[j]);
k++;
}
}
}
if( k > 0){
return 1 + iterateIt(k, b);
}
free(b);
return 1;
}
int main (void)
{
iterateIt(4, (int[4]){1,352,9483,50000});
return 0;
}
结果:
Allocating 17292 ints: 69168 bytes
Total allocated: 69168 bytes
Allocating 12550317587327992670 ints: 13307782201892867448 bytes
Total allocated: 13307782201892936616 bytes
答案 1 :(得分:1)
首先考虑这一行:
return 1 + iterateIt(k, b);
b
数组永远不会在此return
上释放,但是如果k
为零,它会释放。让我们重写此代码以对其进行一些清理:
#include <stdio.h>
#include <stdlib.h>
unsigned iterateIt(size_t a_count, int *a) {
unsigned rep = 1;
int *b = calloc(a_count * a_count, sizeof(int));
size_t k = 0;
for (size_t i = 0; i < a_count; i++) {
for (size_t j = i + 1; j < a_count; j++) {
if (a[i] != a[j]) {
b[k++] = abs(a[i] - a[j]);
}
}
}
if (k > 0) {
rep += iterateIt(k, b);
}
free(b);
return rep;
}
int main() {
int x[] = {1, 324, 54};
printf("%u\n", iterateIt(sizeof(x) / sizeof(int), x));
return 0;
}
看着a_count
的值,程序尝试分配过多的内存,但失败了。
更新
由于矩阵的两半最终相同,因此我修复了上面的代码以执行OP的工作,只需处理矩阵的1/2,即j
从i + 1
开始一半最终相同。我也忽略对角线,因为对角线始终为零。然后,代码完成了示例代码中的三个数字,但是当我将数组增加到四个值时,代码又爆炸了。
我相信OP解决方案的递归性质是优雅的,没有问题,但只是为了确认,这是一个迭代解决方案,其执行失败且并非由于缺少堆栈内存而引起的:
unsigned iterateIt(size_t a_count, int *a) {
unsigned rep = 1;
bool first_time = true;
while (true) {
int *b = calloc((a_count * a_count) / 2, sizeof(int));
if (b == NULL) {
perror("calloc failed!");
exit(1);
}
size_t b_count = 0;
for (size_t i = 0; i < a_count; i++) {
for (size_t j = i + 1; j < a_count; j++) {
if (a[i] != a[j]) {
b[b_count ++] = abs(a[i] - a[j]);
}
}
}
if (b_count == 0) {
free(b);
break;
}
if (first_time) {
first_time = false;
} else {
free(a);
}
a = b;
a_count = b_count;
rep++;
}
return rep;
}