反向执行数组练习...解决方案有效,但我的无效。为什么?

时间:2018-11-10 19:38:03

标签: c# arrays .net

我正在阅读《 C#播放器指南》这本书,然后进入“尝试一下!”。关于数组的章节。

说明如下:

“创建3种方法:一种用于创建数组,一种用于反转数组,另一种用于在最后打印数组。您的main方法将如下所示:

static void Main(string[] args)
{
        int[] numbers = GenerateNumbers();
        Reverse(numbers);
        PrintNumbers(numbers);
}

GenerateNumbers方法应返回10个数字的数组。

PrintNumbers方法应仅使用for或foreach循环一次向下遍历该数组,然后打印出其中的项目。

Reverse方法将是最困难的。尝试一下,看看可以实现什么。如果您遇到困难,这里有一些提示:

提示1:要交换2个值,您需要将一个变量的值放在一个临时位置进行交换:

//Swapping a and b.
int a = 3;
int b = 5;

int temp = a;
int a = b;
int b = temp;

提示2:获取正确的索引进行交换可能是一个挑战。使用for循环,从0开始,一直到数组的长度/2。在for循环中使用的数字将是要交换的第一个数字的索引,而另一个将是数组的长度。减去索引减去1。这是为了说明数组基于0的事实。因此,基本上,您将用array [arrayLength-index-1]交换array [index]。“

话虽如此,到目前为止,这是我的代码:

static void Main(string[] args)
{
        int[] numbers = GenerateNumbers();
        Reverse(numbers);
        PrintNumbers(numbers);
}

// Generates array of numbers and returns array
static int[] GenerateNumbers()
{
        int[] numbers = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        return numbers;
}

// Reverses array to print backwards from 10 to 1
static void Reverse(int[] numbers)
{
        for (int index = 0; index < numbers.Length; index++)
        {
            //swapping array indexes
            int a = numbers[index];
            int b = numbers.Length - index - 1;

            //temp array temporarily holds value while swapping indexes
            int temp = a;
            a = b;
            b = temp;
        }
}

// Prints numbers in array after order has been reversed
static void PrintNumbers(int[] numbers)
{
        for (int index = 0; index < numbers.Length; index++)
        {
            Console.WriteLine(numbers[index]);
        }

        Console.WriteLine();
}

再次,我的代码继续按数字顺序而不是反向打印数组。这是本书中反向方法的解决方案:

static void Reverse(int[] numbers)
    {
        // Initialize one index at the start of the array, and another
        // at the end of the array. The index of the last item in the
        // array is the length of the array - 1.
        int firstIndex = 0;
        int secondIndex = numbers.Length - 1;

        while (firstIndex < secondIndex)
        {
            // To swap two numbers, we need to copy one value out
            // to a safe place so that it doesn't get overwritten.
            int temp = numbers[firstIndex];
            numbers[firstIndex] = numbers[secondIndex];
            numbers[secondIndex] = temp;

            // Move on to the next pair.
            firstIndex++;
            secondIndex--;
        }
    }

奇怪的是,他们使用while循环而不是for循环作为指令状态。

有人可以帮助我了解我的代码出了什么问题和/或如何转换其while语句用作for循环?

2 个答案:

答案 0 :(得分:4)

在您的代码中:

int a = numbers[index];
        int b = numbers.Length - index - 1;

        //temp array temporarily holds value while swapping indexes
        int temp = a;
        a = b;
        b = temp;

您将数字本身放入a,同时将最后一个索引放入b(而不是最后一个索引的数字)。应该是这样的:

        int tmp = numbers[index];
        numbers[index] = numbers[numbers.Length - index - 1];
        numbers[numbers.Length - index - 1] = tmp;
    }

您的for循环还必须遍历数组的一半,然后再将它们交换到其原始位置:

for(int i=0;i<number.Length/2; i++)
{
     int tmp = numbers[index];
     numbers[index] = numbers[numbers.Length - index - 1];
     numbers[numbers.Length - index - 1] = tmp;
}

如果将它们分配给ab,则应像分配它们一样将它们放回(numbers[numbers.Length-index-1]=a; numbers[index]=b;),将数组中的值复制到ab,而不是引用(它们在内存中的地址)

答案 1 :(得分:1)

如果我要反转数组,我会这样做,因为我认为它更简单,更干净:

//new array to hold reverse 
int[] rev = new int[fwd.Length];
//establish an indexer variable for fwd and reverse
//variable f starts at 0 and goes to length -1
//variable r goes the other way
for(int f = 0, r = rev.Length - 1; f < fwd.Length; f++, r--)
  rev[r] = fwd[f];

return rev;

我感谢您的算法,将早期的条目与以后的条目交换,沿数组的一半返回,但是它的数学运算和变量赋值很繁重,似乎造成了混淆,例如“位置2处的数组值”和“计算位置2处的对应位置”

我个人认为,声明另一个相同大小的数组并将其复制到其中,并在向前读取源数组时向后工作是更简单的-这种方法在实现时可能更加无缺陷。

通常必须考虑代码的可读性,可理解性和可维护性以及其他因素。即使付出绝对的性能代价,也要始终努力编写简单且易于解释的代码。通过优化少量代码而获得的微秒数,很容易在几小时或几天内就迷失在脑海中,并说“为什么这个复杂的意大利面不起作用?”,或者更糟的是,对于其他人来说代码并说“这应该做什么,为什么不起作用?”

您还询问了它们的while循环如何转换为for循环。这是一个for循环:

for(setup; test; post-loop-actions)

在他们的代码中:

static void Reverse(int[] numbers)
{
    // setup
    int firstIndex = 0;
    int secondIndex = numbers.Length - 1;

    // test
    while (firstIndex < secondIndex)
    {
        //post-loop-actions
        firstIndex++;
        secondIndex--;
    }
}

启用其while循环,将其翻译为for循环:

static void Reverse(int[] numbers)
{
    // setup
    for(
        int firstIndex = 0, secondIndex = numbers.Length - 1; //setup
        firstIndex < secondIndex;                             //test
        firstIndex++, secondIndex--                           //post-loop-actions
    )
    {
        ...

    }
}

我将for循环花括号部分分成3行;如果while循环示例中的变量名称较短,则可能更适合在线

您可以通过用逗号分隔语句来为循环设置/循环后操作执行多个分配。

这两种形式之间存在实际差异-在while循环形式中,变量是在循环结构外部声明的,并且在循环结束后仍可用于编码。