【问题标题】:C# container for storing permutations用于存储排列的 C# 容器
【发布时间】:2011-05-01 12:48:38
【问题描述】:

我正在寻找一个不寻常的 c# 容器库,用于 调度搜索算法。搜索算法评估解决方案 通过不同的排列来识别并寻找它可以的最佳解决方案 寻找。作为算法的一部分,它需要预先记住 “访问”解决方案,因此它可以避免最终进入循环循环。因此我 需要一个由排列索引的容器。排列是 一个大小为 N 的数组,以“随机”形式保存从 0 到 N-1 的值 顺序。

容器只需要存储一个布尔值,表示位置有 被访问过。它需要快速查找,它需要使 有效利用内存。

我怀疑一棵树可能是最优的......但前提是存在一个现有的 库,因为这个问题也受到我实现它的可用时间的限制。

最好的问候

【问题讨论】:

    标签: c# containers


    【解决方案1】:

    您可以使用哈希集快速查找排列。

    创建一个类以用作哈希集中的键,并为该类创建一个相等比较器,例如:

    publc class Permutation {
    
      private int[] _values;
    
      public Permutation(int[] values) {
        _values = values;
      }
    
      public class Comparer : IEqualityComparer<Permuation> {
    
        public int GetHashCode(Permuation x) {
          int code = 0;
          foreach (int value in x._values) {
            code = code * 251 + value;
          }
          return code;
        }
    
        public bool Equals(Permuation x, Permuation y) {
          if (x._values.Length != y._values.Length) return false;
          for (int i=0; i<x._values.Length; i++) {
            if (x._values[i] != y._values[i]) return false;
          }
          return true;
        }
    
      }
    
    }
    

    然后你可以创建一个使用类作为键的哈希集,它是比较器来评估相等性:

    var permutations = new HashSet<Permutation>(new Permutation.Comparer());
    

    现在您可以创建排列对象并将其放入集合中并对其进行测试:

    permuations.Add(new Permuation(new int[]{1,2,3}));
    
    Permutation lookingFor = new Permutation(new int[]{1,2,3});
    bool exists = permutations.Contains(lookgFor); // returns true
    
    Permutation lookingFor = new Permutation(new int[]{1,3,2});
    bool exists = permutations.Contains(lookgFor); // returns false
    

    【讨论】:

    • 是的,hashset 是显而易见的解决方案之一。不过,OP 提到了内存效率,因此尚不清楚他是否有能力将所有访问过的排列保持原样。无论如何,这是个好建议。
    • 非常感谢您的回答,还有代码。我注意到每次计算散列时都需要 N 次乘法,并且乘法相对昂贵。如果使用树,则不需要这样做,因为它只需要比较。此外,比较次数将明显少于“N”,因为这将是一个非常稀疏的数组。我相信如果不超过哈希,树应该和内存一样有效。由于这些原因,我目前希望找到一个基于树的容器。问候
    • @Howard May:乘法并不昂贵。它们曾经是,但不是现代处理器。我刚刚做了一个快速测试,我根本无法测量加法和乘法之间的任何性能差异。
    • @Howard,在树中,如果没有匹配项,比较次数可以小于 N。但如果有匹配,则必须进行所有 N 比较。
    【解决方案2】:

    总是需要权衡取舍。要么是速度,要么是内存。排列可以转换为索引,如here 所述,但成本很高。另一方面,您不需要转换它们。根据您所写的内容,我了解到您的算法适用于排列,因此它“知道”它们。在这种情况下,它可以按原样存储(访问)它们(例如,在列表或哈希集中)。在这种情况下,您无需花费额外的时间将排列“压缩”到索引中,但您需要确保有足够的内存。

    另一个值得做的脑力练习是确定您的算法需要多少种不同的排列来存储“已访问”状态。通过这种方式,您可以更实际地决定是否需要节省内存,或者您可以选择执行速度更快的选项。

    还有前段时间,我google了“c# permutations”,找到了很多组合库,不知道能不能提供你想要的,建议你看看能不能适合你。

    【讨论】:

      【解决方案3】:

      我认为hash table 可能是您正在寻找的。查找时间是恒定的,向容器中添加新元素的时间也是恒定的(只要您不“过度填充”它,那么增加容器容量需要线性时间)。

      【讨论】:

        【解决方案4】:

        只要我的两分钱:have a look at this code

        给定的链接包含一个用树实现的排列容器,这意味着快速查找和公平的内存使用。

        也许GetPermutations() 方法可以使用Stack&lt;T&gt; 进行改进,但留给读者作为练习:D

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-03-17
          • 1970-01-01
          • 1970-01-01
          • 2021-11-27
          • 1970-01-01
          • 2017-10-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多