如何在递归函数中打印出特定数组并返回其指针

huangapple go评论68阅读模式
英文:

How to print out a specific array and return its pointer from a recursive function

问题

以下是您要翻译的内容:

"我之前在这里提出了一个问题,但答案我自己找到了。但是有一个额外的要求。

练习如下:

我们有一个大小为 N 的浮点数数组。每个浮点数值代表银行账户中的现金流。例如,存款(值为正)或取款(值为负)。账户的初始余额为零。

所以如果现金流是(+10, -5, +7, -8),余额分别为(0+10)=+10(10-5)=+5(5+7)=+12,和(12-8)=+4;因此最大和最小余额分别为+12和+4,差额为+8。

对于相同的现金流集合,但排序为(-5, +10, -8, +7),余额分别为(0-5)=-5(-5+10)=+5(+5-8)=-3,和(-3+7)=+4,最大和最小值分别为+5和-5,差额为+10。

使用递归,我们必须找到最佳排列,以使最大和最小值之间的差异最小。

这是打印出每个排列的代码:

#include <stdio.h>
#include <stdlib.h>

void permutation(float *val, float *sol, float *mark, int n, int pos)
{
    if (pos == n)
    {
        for (int i = 0; i < n; ++i)
        {
            printf("%.0f ", sol[i]);
        }
        printf("\n");
        return;
    }
    for (int i = 0; i < n; ++i)
    {
        if (mark[i] == 0)
        {
            mark[i] = 1;
            sol[pos] = val[i];
            permutation(val, sol, mark, n, pos + 1);
            mark[i] = 0;
        }
    }
}

int main()
{
    float *sol;
    float *val;
    int n = 4;
    float *mark;
    mark = calloc(n, sizeof(float));
    if (mark == NULL)
    {
        exit(1);
    }
    val = malloc(n * sizeof(float));
    if (val == NULL)
    {
        exit(1);
    }
    val = (float[]){+10, -5, +7, -8};

    sol = malloc(n * sizeof(float));
    if (sol == NULL)
    {
        exit(1);
    }

    permutation(val, sol, mark, n, 0);
    return 0;
}

但正如我所说,我如何打印出特定数组,即最大和最小之间差异最小的数组。此外,该练习要求我返回该数组的指针。我应该如何做?

请告诉我,您希望如何处理这些问题。

英文:

I asked a question here before the answer to which i found it myself. But there was an extra requirement.

The exercise goes like this :

We are given an array of float values of size N. Each float value represents a cash flow in a bank account. For example a deposit (when the value is positive) or a withdrawal (when it is negative). The initial balance of the account is equal to zero.

So if the cash flow is (+10, -5, +7, -8) the balances are (0+10)=+10, (10-5)=+5, (5+7)=+12, and (12-8)=+4; thus the maximum and minimum balances
are +12 and +4, with a difference equal to +8

with the same set of cash flows but ordered as (-5, +10, -8, +7) the balances are(0-5)=-5, (-5+10)=+5, (+5-8)=-3, and (-3+7)=+4, with a maximum and a minimum equal to +5 and -5 and a difference is equal to +10.

Using recursion we have to find the best arrangement so that the difference between the maximum and minimum is minimal

This is the code that prints out every permutation

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

void permutation(float *val,float *sol,float *mark,int n,int pos)
{
    if(pos==n)
    {
        for (int i = 0; i &lt; n; ++i) {
            printf(&quot;%.0f &quot;,sol[i]);
        }
        printf(&quot;\n&quot;);
        return;
    }
    for (int i = 0; i &lt; n; ++i) {
        if(mark[i]==0)
        {
            mark[i]=1;
            sol[pos]=val[i];
            permutation(val,sol,mark,n,pos+1);
            mark[i]=0;
        }
    }
}
int main() {
    float *sol;
    float *val;
    int n=4;
    float *mark;
    mark = calloc(n, sizeof(float ));
    if(mark==NULL)
    {
        exit(1);
    }
    val = malloc(n* sizeof(float ));
    if(val==NULL)
    {
        exit(1);
    }
    val=(float []){+10, -5, +7, -8};
    
    sol=malloc(n* sizeof(float));
    if(sol==NULL)
    {
        exit(1);
    }

    permutation(val,sol,mark,n,0);
    return 0;
}

But as i said how do i print out a specific array in my case the one that the difference between max and min is minimal. Also the exercise requires me to return the pointer of this array. How do i do that as well?

答案1

得分: 1

以下是翻译好的部分:

一种方法是,在递归过程中,不要打印输出,而是在每个排列上执行计算。如果它产生了迄今为止的最佳结果,将当前排列复制到输出缓冲区中。

一旦所有排列都耗尽,然后打印最佳结果。

请注意,在两个或更多排列产生最佳结果的情况下,这会选择首次遇到的排列。这意味着数组的起始顺序会影响结果的顺序。

使用您的算法(以及可变长度数组 [VLAs] 1)的一个简单、天真的示例:

#include <float.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>

static void print_array(float *data, size_t length)
{
    for (size_t i = 0; i < length; i++)
        printf("%5.1f ", data[i]);
    putchar('\n');
}

static float flow_minmax_diff(float *data, size_t length)
{
    float min = FLT_MAX;
    float max = FLT_MIN;
    float balance = 0;

    for (size_t i = 0; i < length; i++) {
        balance += data[i];

        if (balance > max)
            max = balance;

        if (balance < min)
            min = balance;
    }

    return max - min;
}

static void permutation_actual(
        float *difference,
        float *result,
        float *values,
        float *swap,
        bool *marked,
        size_t length,
        size_t depth)
{
    if (depth == length) {
        float d = flow_minmax_diff(swap, length);

        if (d < *difference) {
            *difference = d;
            memcpy(result, swap, sizeof *swap * length);
        }

        return;
    }

    for (size_t i = 0; i < length; i++) {
        if (marked[i])
            continue;

        marked[i] = true;
        swap[depth] = values[i];
        permutation_actual(difference, result, values, swap, marked, length, depth + 1);
        marked[i] = false;
    }
}

static float best_permutation(float *res, float *values, size_t length)
{
    float temp[length];
    bool markers[length];
    memset(markers, 0, sizeof markers);

    float diff = FLT_MAX;
    permutation_actual(&diff, res, values, temp, markers, length, 0);
    return diff;
}

int main(void)
{
    float values[] = { -8.f, -5.f, 7.f, 10.f };
    size_t length = sizeof values / sizeof *values;
    float best[length];
    float difference = best_permutation(best, values, length);

    printf("Difference: %5.1f\n", difference);
    print_array(best, length);
}

结果:

Difference:   8.0
10.0  -8.0   7.0  -5.0

至于如何“返回此数组的指针”,根据这个示例,您可以在best_permutation中简单地分配(malloc)结果数组,并返回它,而不是将其作为参数传递。

flow_minmax_diff始终可以在结果上调用。)

作为一个副注意事项,这个:

val = malloc(n * sizeof(float));
val = (float []){ +10, -5, +7, -8 };

是对变量valfloat *值的两个非常独立的赋值。这不会执行在malloc返回的地址上的任何种类的“初始化”。

其结果是val是指向具有自动存储期数组的第一个元素的指针,而由malloc分配的内存被泄漏。

例如:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    float *val = malloc(4 * sizeof(float));
    printf("%p\n", (void *) val);
    val = (float []){ +10, -5, +7, -8 };
    printf("%p\n", (void *) val);
}
0x55bd9c5092a0
0x7ffd138ea010
英文:

One approach is that, instead of printing during the recursion, perform your calculations on each permutation. If it yields the best result yet, copy the current permutation to an output buffer.

Once all permutations are exhausted, then you print the best one.

Note that in the event where two or more permutations produce the best result, this chooses the first encountered. This means the starting order of the array influences the order of the result.

A cursory, naive example using your algorithm (and VLAs):

#include &lt;float.h&gt;
#include &lt;stdbool.h&gt;
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;

static void print_array(float *data, size_t length)
{
	for (size_t i = 0; i &lt; length; i++)
		printf(&quot;%5.1f &quot;, data[i]);
	putchar(&#39;\n&#39;);
}

static float flow_minmax_diff(float *data, size_t length)
{
	float min = FLT_MAX;
	float max = FLT_MIN;
	float balance = 0;

	for (size_t i = 0; i &lt; length; i++) {
		balance += data[i];

		if (balance &gt; max)
			max = balance;

		if (balance &lt; min)
			min = balance;
	}

	return max - min;
}

static void permutation_actual(
		float *difference,
		float *result,
		float *values,
		float *swap,
		bool *marked,
		size_t length,
		size_t depth)
{
	if (depth == length) {
		float d = flow_minmax_diff(swap, length);

		if (d &lt; *difference) {
			*difference = d;
			memcpy(result, swap, sizeof *swap * length);
		}

		return;
	}

	for (size_t i = 0; i &lt; length; i++) {
		if (marked[i])
			continue;

		marked[i] = true;
		swap[depth] = values[i];
		permutation_actual(difference, result, values, swap, marked, length, depth + 1);
		marked[i] = false;
	}
}

static float best_permutation(float *res, float *values, size_t length)
{
	float temp[length];
	bool markers[length];
	memset(markers, 0, sizeof markers);

	float diff = FLT_MAX;
	permutation_actual(&amp;diff, res, values, temp, markers, length, 0);
	return diff;
}

int main(void)
{
	float values[] = { -8.f, -5.f, 7.f, 10.f };
	size_t length = sizeof values / sizeof *values;
	float best[length];
	float difference = best_permutation(best, values, length);

	printf(&quot;Difference: %5.1f\n&quot;, difference);
	print_array(best, length);
}

Result:

Difference:   8.0
10.0  -8.0   7.0  -5.0

As for how to "return the pointer of this array", with the example in mind, you could simply allocate (malloc) the resulting array in best_permutation, and return it, instead of feeding it as an argument.

(flow_minmax_diff could always be called on the result.)


As a side note, this

val = malloc(n * sizeof(float));
val = (float []){ +10, -5, +7, -8 };

is two very separate assignments of a float * value to the variable val. This does not perform any kind of "initialization" of the memory located at the address returned by malloc.

The result being that val is a pointer to the first element of an array of automatic storage duration, and the memory allocated by malloc is leaked.

For example:

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

int main(void)
{
    float *val = malloc(4 * sizeof(float));
    printf(&quot;%p\n&quot;, (void *) val);
    val = (float []){ +10, -5, +7, -8 };
    printf(&quot;%p\n&quot;, (void *) val);
}
0x55bd9c5092a0
0x7ffd138ea010

huangapple
  • 本文由 发表于 2023年5月26日 12:11:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76337621.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定