有没有一种方法可以使选择特定变量的效率更高?

时间:2020-09-23 06:57:53

标签: c++

因此,我正在编写一个程序,其中包含9种不同的迷宫,这些迷宫存储在2d数组中,所有数组均填充有硬编码值。当玩家选择迷宫时,我想将所选迷宫中的硬编码值复制到活动迷宫的2d数组中。当我写出它时,我以最直接的方式做到了,如下所示。然后我想让它看起来更好,使它迷宫……...肿。切换用例不会减少行数,因此我想采取某种方法立即将int mazeSelection变量放入所选迷宫的变量名中。但是似乎您不能在运行时更改变量名,也不能使用字符串变量来表示另一个变量的名称。例如,string mazenumber = "maze" + tostring(mazeSelection);然后执行mazenumber[11][11]是行不通的,但这是我想做的基本想法。

结果是,有没有办法使这段代码更有效?

    if(mazeSelection == 1)
        maze[11][11] = maze1[11][11];
    if(mazeSelection == 2)
        maze[11][11] = maze2[11][11];
    if(mazeSelection == 3)
        maze[11][11] = maze3[11][11];
    if(mazeSelection == 4)
        maze[11][11] = maze4[11][11];
    if(mazeSelection == 5)
        maze[11][11] = maze5[11][11];
    if(mazeSelection == 6)
        maze[11][11] = maze6[11][11];
    if(mazeSelection == 7)
        maze[11][11] = maze7[11][11];
    if(mazeSelection == 8)
        maze[11][11] = maze8[11][11];
    if(mazeSelection == 9)
        maze[11][11] = maze9[11][11];

2 个答案:

答案 0 :(得分:4)

所以您的问题不够详细,但是假设您有这个问题

int maze[11][11], maze1[11][11]; // etc

那么首先要说的是

maze[11][11] = maze1[11][11];

不复制您的迷宫。这是一个非常常见的初学者误解,您可以通过这种方式引用整个数组,但是maze1[11][11]仅引用坐标(11,11)处的一个迷宫元素,而不是整个迷宫。更糟糕的是,由于数组的大小是11 x 11,因此该元素实际上并不存在,因此代码只是一个错误。 (令人惊讶地)没有简单的方法可以用C ++复制数组。

最简单的建议(感谢@molbdnilo)是将迷宫放入结构中。

struct Maze
{
    int tiles[11][11];
};

Maze maze, maze1; // etc

现在可以用通常的方式复制结构了,所以

maze = maze1;

是法定密码,并且确实复制了迷宫。

然后,您可以走得更远,制作一系列迷宫,并编写以下简单代码

Maze selected_maze, all_mazes[10];

selected_maze = all_mazes[mazeSelection];

答案 1 :(得分:0)

适合您的情况的最简单方法是存储在vector中选择值所需要的内容,然后仅对该向量进行索引。即而不是写作

if (x == 0)
    y = z0;
else if (x == 1)
    y = z1;
else if (x == 2)
    y = z2;

你做

static vector<ValueT> values = {z0, z1, z2, ValueT()/*no answer for 3*/, z4, z5};
if (x < values.size())
    y = values[x];
else
    y = ValueT(); // No value found!

请注意,如果要检查的键(如果条件成立)覆盖密集的整个向量范围[0;size),则上述解决方案效果很好,如果缺少某些值,则可以将特殊值存储在相应向量的插槽中,表示没有答案。

如果要稀疏键空间,则向量中将有太多无值元素,并且此解决方案可能浪费内存,那么接下来的其他解决方案也可以。但是就给定键获得正确值的速度而言,这种矢量解是最快的。

在更困难的情况下,当您需要在if条件中包含任意表达式或在if主体中运行任意代码时,则需要使用更高级的解决方案,例如我刚刚在下面的代码中编码的解决方案(我已经按照复杂性递增的顺序对所有案例进行了编码。所有这些解决方案都在实现做出if / then选择的最快方法。

我会解释一些代码。

如果条件仅检查[0; size)范围内的数字是否相等,而结果只是一个值,则我们使用vector。向量的值可以是要返回的普通对象,也可以是要运行的功能对象(如果在if-body内是复杂的处理程序)。此选择可在恒定的O(1)时间(即非常快(见Time Complexity)中工作。

如果要比较的键稀疏(例如数字10、20、30、40),则我们使用unordered_mapmap,map可用于任何可排序的键(对于map)或支持相等和可哈希化(用于unordered_map)。此解决方案在O(1)的时间内unordered_map有效,即非常快(但常数可能不是很小),如果有数十种if-case,请使用unordered_map。对于map,它可以在O(log(N))的时间内工作(N是处理程序/如果实体的数量),因此它也非常快,请在少于12个的情况下使用。在少数情况下,mapunordered_map快。

对于最复杂的情​​况,如果条件条件是复杂的表达式,而条件实体也是复杂的代码块,即当我们具有func-func映射时,也可以在对数时间(O(log(N))中快速求解但仅适用于所有if-case都可以按以下方式排序(排序)的情况:对于每个当前if-case,我们可以肯定地判断出正确的匹配大小写是否可能(如果存在)位于左侧的处理程序中当前(标志-1)或当前大小写匹配一个(标志0)或正确匹配的大小写(如果存在)可能位于当前右边的处理程序中。换句话说,所有处理程序都可以以一种确定的方式对所有可能的输入参数(如果条件条件表达式功能)进行排序。在这种情况下,我们只使用Binary Search做对数时间std::lower_bound(...)

所有建议都是:

  1. 如果键是非负整数(或者可以通过一些简单的函数将键映射到此类整数),并且如果此整数空间不太稀疏(否则矢量解会浪费内存),则使用{{ 1}}进行映射。按索引从向量中提取数据的时间为std::vector,而且固定时间较小(几个CPU指令),即非常快。

  2. 如果键非常多(超过数百个)并且键是相等可比较的且hash-able,则使用O(1)。密钥的获取时间为std::unordered_map,代表无序时间,但常量时间却不那么小(数百条CPU指令),也就是说,获取时间也不会很快,并且获取时间不会随映射元素的数量而增加。

  3. 如果键不是太多(低于100)并且键是fully-orderable(即可以排序),则使用O(1)。它具有std::map的时间,且常数较小,即速度也非常快。

  4. 如果没有键,即if条件是复杂的表达式,并且有很多(多于)if情况,则使用O(log(N))的成对函数对{{1 }}。搜索匹配的案例将需要std::vector个if-condition-code评估次数,即非常快。

  5. 如果if-case很少(在5-6以下),或者您不需要速度,或者如果无法针对所有参数或规则1-5对if-cases-handler进行排序,则不要”不适用,或者您只是不想使用任何复杂的解决方案,而仅使用简单的ifs。

  6. 规则1-5都是关于快速查找匹配if-case的不同方法。关于值-上面的所有结构都可以存储任何类型的值。所以:

    • 如果if情况仅返回一些数据而无需任何代码计算,则将常规对象存储为结构的值((if_condition_code_matcher, if_body_code)O(log(N))或任何类对象),例如您的情况。通过键获取结构的插槽后,只需返回该值即可。
    • 如果您的if实体包含复杂的代码,则将功能存储为结构的值。通过键获取后,只需将此功能值作为处理程序运行即可。
  7. 此外,如果键是整数(或可映射到键)(如情况1),您也可以使用老式的switch-case。聪明的编译器以仅使用goto命令跳转到匹配的if-body的方式来优化代码。但是对于这种情况,您需要对交换机中的所有案例进行排序,并且在交换机的案例中还应涵盖范围int的所有值。但是不能保证这样的优化,编译器仍然可以定期进行if条件尝试。因此,string解决方案是唯一保证的优化。

下面的代码也可以是run online here

[0;size)