递归地创建和显示一个人的金字塔-C
问题:我试图获取两个数组,并将它们传递给一个函数,在这个函数中,我应该递归地显示字母“people”的列表,并将它们放置在一个金字塔中,在金字塔中,我将底部人员膝盖上的重量显示为将其上方人员的一半重量加上他们自己的一半重量。因此,站在顶端的人依靠自己的体重支撑,而站在金字塔一侧的人只支撑1人体重的一半,其他人则支撑2人体重的一半。我正在经历一场噩梦,我必须理解并弄清楚如何创建一个递归调用来处理这个问题 我创建了两个函数,一个是在用户输入到底行有多少人后,生成列表中有多少人;下一个函数只是根据总金字塔中的人数给每个人一个字母 我已经将两个数组(权重和字母字符)以及总人数传递给了函数 我如何创建一种基于他们膝盖上的重量递归生成金字塔的方法 示例:递归地创建和显示一个人的金字塔-C,c,recursion,C,Recursion,问题:我试图获取两个数组,并将它们传递给一个函数,在这个函数中,我应该递归地显示字母“people”的列表,并将它们放置在一个金字塔中,在金字塔中,我将底部人员膝盖上的重量显示为将其上方人员的一半重量加上他们自己的一半重量。因此,站在顶端的人依靠自己的体重支撑,而站在金字塔一侧的人只支撑1人体重的一半,其他人则支撑2人体重的一半。我正在经历一场噩梦,我必须理解并弄清楚如何创建一个递归调用来处理这个问题 我创建了两个函数,一个是在用户输入到底行有多少人后,生成列表中有多少人;下一个函数只是根据总金
How many people are on the bottom row? 4
Each person's own weight:
51.18
55.90 131.25
69.05 133.66 132.82
53.43 139.61 134.06 121.63
Weight on each person's knees:
51.18
81.49 156.84
109.80 252.82 211.24
108.32 320.92 366.09 227.25
理想情况下,我希望将它们各自的字母附加到值上,但这不是必需的
我甚至不确定我的函数是否有足够的值,或者我是否应该创建二维数组而不是单个数组。总的来说,我对这个问题的理解有困难
代码:
最后一个函数有错误,无法确定发送什么以递归方式调用正确的输出
intbottomrow(intusernum);
浮动加权宽度(浮动arr[],整数totalpeople,字符[]);
int main(){
int bottomrow,总人数,k=1,j=1;
人物;
printf(“底层有多少人?\n”);
//如果输入7,字母分配将超出字母表的范围
scanf(“%d”和底行);
//递归查找金字塔中的总人数
//printf(“金字塔中的总人数为:%d\n”,底部行(底部行));
total_people=bottomRow(bottomRow);//total_people是所有人的整数
//填充数组
流动人口[总人口];
对于(;j递归函数,需要(1)停止递归的递归测试条件,以及(2)函数内的递归调用
注意…避免在简单的过程性方法可以工作的地方使用递归。每个递归调用本身就是一个单独的函数调用,需要单独的函数堆栈、局部变量等。如果递归需要太多的递归调用,您可以很容易地耗尽可用内存。请确保您了解自己的乐趣有多少次可以在选择递归解决方案之前调用Action
也就是说,在一些问题中,递归提供了一个非常优雅的解决方案,而不存在内存耗尽的可能性。置换、阶乘等都是很好的例子。递归函数也是一个很好的家庭作业问题,因为它是编程的一个必要领域,需要您仔细考虑接下来会发生什么您正在进行递归调用——以及在满足递归测试条件后发生的事情(并且您必须在每个递归调用返回时从递归中“放松”)
在您的例子中,您将获得包含每个人的权重的数组,并将其与相同大小的单独数组一起传递,以计算金字塔中每个点的人的金字塔权重。您必须同时输出人的数组和金字塔中每个点的权重数组
您的递归测试条件相当简单,您将进行递归调用以覆盖人员
数组中的每一行,以便计算权重。您将以函数参数的形式传递当前行,因此您的递归测试仅限于行数达到金字塔的大小(数组的大小)
在初始和每次递归调用中,您需要(1)打印人员数组和(2)在函数中进行递归调用之前,根据上面的人员计算权重。然后在进行递归调用后,您需要打印已计算的权重——但在每次递归调用和“放松”返回时要小心在递归中,您使用的行计数器将从其极限开始,然后返回到零。这将需要在递归调用后处理数组索引时进行一些规划
例如,在设置递归函数时,您可以考虑:
#include <stdio.h>
#define SIZEP 4 /* constant for rows/cols - otherwise VLA or allocate */
void pyramid (double (*people)[SIZEP], double (*weight)[SIZEP], int row)
{
if (row < SIZEP) { /* recursive test condition */
/* handle all computations/print people here */
pyramid (people, weight, row + 1); /* recursive call */
/* print your weights here (but reverse the indexes) */
}
}
现在,当row==SIZEP
时会发生什么?递归函数开始从递归调用返回。因此,如果您在传递row+1
和row==SIZEP
的位置进行最后一次递归调用,那么在递归调用之后立即开始返回和展开。row
的值是多少re?(如果递归调用通过row+1
并在测试条件下返回,则row
未更改,它仍将是最后一行(例如,在您的情况下,3
)
在最后一次递归调用中发生的一切是:
void pyramid (double (*people)[SIZEP], double (*weight)[SIZEP], int row)
{
if (row < SIZEP) { /* recursive test condition -- FAILED */
}
}
您不必担心传递任何内容,当递归调用展开时,每次返回后的行
的值将是递归调用之前该函数中的值
在一个简短的示例中,您将看到如下内容:
#include <stdio.h>
#define SIZEP 4 /* constant for rows/cols - otherwise VLA or allocate */
void pyramid (double (*people)[SIZEP], double (*weight)[SIZEP], int row)
{
if (row < SIZEP) { /* recursive test condition */
/* recursion */
if (row == 0) { /* print people, set weight */
printf ("%6.2lf\n", people[row][0]);
weight[row][0] = people[row][0];
}
else {
/* print 1st person, set 1st weight */
printf ("%6.2lf", people[row][0]);
weight[row][0] = people[row][0] + weight[row-1][0] / 2.0;
/* print inner people, set innter weights */
for (int i = 1; i < row; i++) {
printf (" %6.2lf", people[row][i]);
weight[row][i] = people[row][i] +
(weight[row-1][i-1] + weight[row-1][i]) / 2.0;
}
/* print last person, set last weight */
printf (" %6.2lf\n", people[row][row]);
weight[row][row] = people[row][row] + weight[row-1][row-1] / 2.0;
}
pyramid (people, weight, row + 1); /* recursive call */
/* return from recursion */
int revrow = SIZEP - (row + 1); /* print weights in reverse order */
if (revrow == 0) /* same logic as computing weights applies */
printf ("\n%6.2lf\n", weight[revrow][0]);
else {
printf ("%6.2lf", weight[revrow][0]);
for (int i = 1; i < revrow; i++)
printf (" %6.2lf", weight[revrow][i]);
printf (" %6.2lf\n", weight[revrow][revrow]);
}
}
}
int main (void) {
double people[SIZEP][SIZEP] = {{ 51.18 },
{ 55.90, 131.25 },
{ 69.05, 133.66, 132.82 },
{ 53.43, 139.61, 134.06, 121.63 }},
weight[SIZEP][SIZEP] = {{ 0 }};
pyramid (people, weight, 0);
return 0;
}
想一想。递归函数需要一种稍微不同的思维方式来让它们有意义。但是,当你意识到你只是在进入的过程中重复调用同一个函数,然后在递归展开时处理每个调用的返回——它将开始下沉
使用带有C99+的VLA
而不是声明一个整数常量SIZEP
,将people
和weight
都声明为arr
void pyramid (double (*people)[SIZEP], double (*weight)[SIZEP], int row)
{
if (row < SIZEP) { /* recursive test condition -- FAILED */
}
}
...
pyramid (people, weight, row + 1); /* recursive call */
/* return from recursion */
int revrow = SIZEP - (row + 1); /* print weights in reverse order */
if (revrow == 0) /* same logic as computing weights applies */
printf ("\n%6.2lf\n", weight[revrow][0]);
else {
printf ("%6.2lf", weight[revrow][0]);
for (int i = 1; i < revrow; i++)
printf (" %6.2lf", weight[revrow][i]);
printf (" %6.2lf\n", weight[revrow][revrow]);
}
}
}
#include <stdio.h>
#define SIZEP 4 /* constant for rows/cols - otherwise VLA or allocate */
void pyramid (double (*people)[SIZEP], double (*weight)[SIZEP], int row)
{
if (row < SIZEP) { /* recursive test condition */
/* recursion */
if (row == 0) { /* print people, set weight */
printf ("%6.2lf\n", people[row][0]);
weight[row][0] = people[row][0];
}
else {
/* print 1st person, set 1st weight */
printf ("%6.2lf", people[row][0]);
weight[row][0] = people[row][0] + weight[row-1][0] / 2.0;
/* print inner people, set innter weights */
for (int i = 1; i < row; i++) {
printf (" %6.2lf", people[row][i]);
weight[row][i] = people[row][i] +
(weight[row-1][i-1] + weight[row-1][i]) / 2.0;
}
/* print last person, set last weight */
printf (" %6.2lf\n", people[row][row]);
weight[row][row] = people[row][row] + weight[row-1][row-1] / 2.0;
}
pyramid (people, weight, row + 1); /* recursive call */
/* return from recursion */
int revrow = SIZEP - (row + 1); /* print weights in reverse order */
if (revrow == 0) /* same logic as computing weights applies */
printf ("\n%6.2lf\n", weight[revrow][0]);
else {
printf ("%6.2lf", weight[revrow][0]);
for (int i = 1; i < revrow; i++)
printf (" %6.2lf", weight[revrow][i]);
printf (" %6.2lf\n", weight[revrow][revrow]);
}
}
}
int main (void) {
double people[SIZEP][SIZEP] = {{ 51.18 },
{ 55.90, 131.25 },
{ 69.05, 133.66, 132.82 },
{ 53.43, 139.61, 134.06, 121.63 }},
weight[SIZEP][SIZEP] = {{ 0 }};
pyramid (people, weight, 0);
return 0;
}
$ ./bin/pyramidrecurse
51.18
55.90 131.25
69.05 133.66 132.82
53.43 139.61 134.06 121.63
51.18
81.49 156.84
109.79 252.82 211.24
108.33 320.92 366.09 227.25
#include <stdio.h>
#include <string.h>
void compute (int size, double (*people)[size], double (*weight)[size], int row)
{
if (row == 0) { /* print people, set weight */
printf ("%6.2lf\n", people[row][0]);
weight[row][0] = people[row][0];
}
else {
/* print 1st person, set 1st weight */
printf ("%6.2lf", people[row][0]);
weight[row][0] = people[row][0] + weight[row-1][0] / 2.0;
/* print inner people, set inner weights */
for (int i = 1; i < row; i++) {
printf (" %6.2lf", people[row][i]);
weight[row][i] = people[row][i] +
(weight[row-1][i-1] + weight[row-1][i]) / 2.0;
}
/* print last person, set last weight */
printf (" %6.2lf\n", people[row][row]);
weight[row][row] = people[row][row] + weight[row-1][row-1] / 2.0;
}
}
void unwind (int size, double (*weight)[size], int row)
{
int revrow = size - (row + 1); /* print weights in reverse order */
if (revrow == 0) /* same logic as computing weights applies */
printf ("\n%6.2lf\n", weight[revrow][0]);
else {
printf ("%6.2lf", weight[revrow][0]);
for (int i = 1; i < revrow; i++)
printf (" %6.2lf", weight[revrow][i]);
printf (" %6.2lf\n", weight[revrow][revrow]);
}
}
void pyramid (int size, double (*people)[size], double (*weight)[size], int row)
{
if (row < size) { /* recursive test condition */
/* computations before recursive call */
compute (size, people, weight, row);
/* recursive call */
pyramid (size, people, weight, row + 1);
/* return from recursion */
unwind (size, weight, row);
}
}
int main (int argc, char **argv) {
int size; /* read from user or file */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
if (fscanf (fp, "%d", &size) != 1) { /* read size */
fprintf (stderr, "error: invalid format '%s'\n", argv[1]);
return 1;
}
double people[size][size], /* declare VLAs, but you */
weight[size][size]; /* can't initialize VLAs */
memset (people, 0, size * sizeof *people); /* zero both arrays */
memset (weight, 0, size * sizeof *weight);
for (int i = 0; i < size; i++)
for (int j = 0; j <= i; j++)
if (fscanf (fp, "%lf", &people[i][j]) != 1) {
fprintf (stderr, "error: reading people[%d][%d]\n", i, j);
return 1;
}
fclose (fp); /* close file */
pyramid (size, people, weight, 0); /* compute/print arrays */
return 0;
}
$ cat dat/pyramidweight.txt
4
51.18
55.90 131.25
69.05 133.66 132.82
53.43 139.61 134.06 121.63
$ ./bin/pyramidrecursefnvla dat/pyramidweight.txt
51.18
55.90 131.25
69.05 133.66 132.82
53.43 139.61 134.06 121.63
51.18
81.49 156.84
109.79 252.82 211.24
108.33 320.92 366.09 227.25
void pyramid (int size, double **people, double **weight, int row)
double **people = NULL, /* pointer to pointer to double */
**weight = NULL;
/* first allocate size pointers to each people and weight */
people = malloc (size * sizeof *people);
if (people == NULL) { /* validate every allocation */
perror ("malloc-people");
exit (EXIT_FAILURE);
}
weight = malloc (size * sizeof *weight);
if (!weight) { /* validate every allocation */
perror ("malloc-weight");
exit (EXIT_FAILURE);
}
/* now allocate a block of size double for each pointer,
* let's use calloc here to both allocate and set all bytes zero.
*/
for (int i = 0; i < size; i++) { /* loop over pointers */
people[i] = calloc (size, sizeof *people[i]); /* allocate doubles */
if (!people[i]) { /* validate every allocation */
perror ("calloc-people[i]");
exit (EXIT_FAILURE);
}
weight[i] = calloc (size, sizeof *weight[i]); /* allocate doubles */
if (!weight[i]) { /* validate every allocation */
perror ("calloc-weight[i]");
exit (EXIT_FAILURE);
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void compute (double **people, double **weight, int row)
{
if (row == 0) { /* print people, set weight */
printf ("%6.2lf\n", people[row][0]);
weight[row][0] = people[row][0];
}
else {
/* print 1st person, set 1st weight */
printf ("%6.2lf", people[row][0]);
weight[row][0] = people[row][0] + weight[row-1][0] / 2.0;
/* print inner people, set inner weights */
for (int i = 1; i < row; i++) {
printf (" %6.2lf", people[row][i]);
weight[row][i] = people[row][i] +
(weight[row-1][i-1] + weight[row-1][i]) / 2.0;
}
/* print last person, set last weight */
printf (" %6.2lf\n", people[row][row]);
weight[row][row] = people[row][row] + weight[row-1][row-1] / 2.0;
}
}
void unwind (int size, double **weight, int row)
{
int revrow = size - (row + 1); /* print weights in reverse order */
if (revrow == 0) /* same logic as computing weights applies */
printf ("\n%6.2lf\n", weight[revrow][0]);
else {
printf ("%6.2lf", weight[revrow][0]);
for (int i = 1; i < revrow; i++)
printf (" %6.2lf", weight[revrow][i]);
printf (" %6.2lf\n", weight[revrow][revrow]);
}
}
void pyramid (int size, double **people, double **weight, int row)
{
if (row < size) { /* recursive test condition */
/* computations before recursive call */
compute (people, weight, row);
/* recursive call */
pyramid (size, people, weight, row + 1);
/* return from recursion */
unwind (size, weight, row);
}
}
int main (int argc, char **argv) {
int size; /* read from user or file */
double **people = NULL, /* pointer to pointer to double */
**weight = NULL;
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
exit (EXIT_FAILURE);
}
if (fscanf (fp, "%d", &size) != 1) { /* read size */
fprintf (stderr, "error: invalid format '%s'\n", argv[1]);
exit (EXIT_FAILURE);
}
/* first allocate size pointers to each people and weight */
people = malloc (size * sizeof *people);
if (people == NULL) { /* validate every allocation */
perror ("malloc-people");
exit (EXIT_FAILURE);
}
weight = malloc (size * sizeof *weight);
if (!weight) { /* validate every allocation */
perror ("malloc-weight");
exit (EXIT_FAILURE);
}
/* now allocate a block of size double for each pointer,
* let's use calloc here to both allocate and set all bytes zero.
*/
for (int i = 0; i < size; i++) { /* loop over pointers */
people[i] = calloc (size, sizeof *people[i]); /* allocate doubles */
if (!people[i]) { /* validate every allocation */
perror ("calloc-people[i]");
exit (EXIT_FAILURE);
}
weight[i] = calloc (size, sizeof *weight[i]); /* allocate doubles */
if (!weight[i]) { /* validate every allocation */
perror ("calloc-weight[i]");
exit (EXIT_FAILURE);
}
}
/* the rest is the same - except for parameter types for pyramid */
for (int i = 0; i < size; i++) /* read people values from file */
for (int j = 0; j <= i; j++)
if (fscanf (fp, "%lf", &people[i][j]) != 1) {
fprintf (stderr, "error: reading people[%d][%d]\n", i, j);
return 1;
}
fclose (fp); /* close file */
pyramid (size, people, weight, 0); /* compute/print arrays */
for (int i = 0; i < size; i++) {
free (people[i]);
free (weight[i]);
}
free (people);
free (weight);
return 0;
}
$ valgrind ./bin/pyramidrecursemalloc dat/pyramidweight.txt
==1851== Memcheck, a memory error detector
==1851== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==1851== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==1851== Command: ./bin/pyramidrecursemalloc dat/pyramidweight.txt
==1851==
51.18
55.90 131.25
69.05 133.66 132.82
53.43 139.61 134.06 121.63
51.18
81.49 156.84
109.79 252.82 211.24
108.33 320.92 366.09 227.25
==1851==
==1851== HEAP SUMMARY:
==1851== in use at exit: 0 bytes in 0 blocks
==1851== total heap usage: 11 allocs, 11 frees, 872 bytes allocated
==1851==
==1851== All heap blocks were freed -- no leaks are possible
==1851==
==1851== For counts of detected and suppressed errors, rerun with: -v
==1851== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)