是否可以实现通用维度数据结构?

时间:2010-06-29 15:32:21

标签: c# .net generics data-structures

我正在编写一些自己的数据结构,例如二叉树和四元树,以及kD树。是否可以以允许任意数量维度的方式编写它们?

类似的东西:

KDTree<2, string> twoDTree = new KDTree<2, string>();
twoDTree[3,4] = "X,Y = (3,4)";

KDTree<4, string> fourDTree = new KDTree<4, string>();
fourDTree[0,1,2,3] = "x1,x2,x3,x4 = (0,1,2,3)";

我现在唯一的解决方案是明确创建每个维度,因为它是自己的类:

TwoDTree<string> twoDTree = new TwoDTree<string>();
twoDTree[3,4] = "X,Y = (3,4)";

FourDTree<string> fourDTree = new FourDTree<string>();
fourDTree[0,1,2,3] = "x1,x2,x3,x4 = (0,1,2,3)";

但是这个副本粘贴了大量的代码,应该能够以某种方式重用。

2 个答案:

答案 0 :(得分:1)

不是,但我看到更多选择:

将维度传递给构造函数并使用如下索引器:

public string this[params int[] indexes] {
  get {
    // return the data fr the index
  }
}

这具有在编译时不是“类型安全”的缺点(例如,不会检查传入的维度)。

或创建一堆接口并使用Reflection.Emit创建在运行时实现正确接口的实例:

public interface IMultiDimensional<T> {
  int Dimensions {
    get;
  }

  int Rank(int dimension);
}

public interface I1Dimensional<T>: IMultiDimensional<T> {
  T this[int index] {
    get;
    set;
  }
}

public interface I2Dimensional<T>: IMultiDimensional<T> {
  T this[int index1, int index2] {
    get;
    set;
  }
}

public interface I3Dimensional<T>: IMultiDimensional<T> {
  T this[int index1, int index2, int index3] {
    get;
    set;
  }
}

public interface I4Dimensional<T>: IMultiDimensional<T> {
  T this[int index1, int index2, int index3, int index4] {
    get;
    set;
  }
}

public static TDimensional CreateMulti<TDimensional, TType>() where T: IMultiDimensional<TType> {
  // emit a class with Reflection.Emit here that implements the interface
}

I4Dimensional<string> four = CreateMulti<I4Dimensional<string>, string>();
four[1,2,3,4] = "abc";

答案 1 :(得分:0)

您可以使用多维数组作为通用参数,如下所示:

KDTree<string[,,,]>

但是,您将无法编写索引到多维数组中的通用代码,而不会将其暴露给调用者:

public class KDTree<MDT> {
    // ... 

    public MDT Data { get; }
}

var twoTree = new KDTree<string[,]>();
twoTree.Data[3,4] = "X,Y = (3,4)";

您还可以考虑使用jagged arrays而不是多维数组。然后,您可以创建一个定义数据的类型的泛型类,并在构造函数中指定要使用的维数:

public class KDTree<T> {
   private readonly T[][] m_Data;

   public KDTree( int rows, int columns )  {
      m_Data = new T[rows][];
      for( int r = 0; r < rows; r++ )
        m_Data[r] = new T[columns];
   }
}