15.9 一个更合理的距离矩阵

优质
小牛编辑
131浏览
2023-12-01

虽然这段代码可以工作,但它本可以组织的更好。既然我们已经写了一个原型,那么我们就处于评价其设计并改进之的有利位置了。

那现在的代码有些什么问题呢?

  1. 我们提前不知道要创建多大的距离矩阵,所以我们选择了一个任意大的数字(50),然后创建了一个固定大小的矩阵。更好的方式是允许距离矩阵以类似Set的方式扩充,而apmatrix类的resize函数使之成为可能。

  2. 矩阵中的数据没有很好的封装。我们不得不以城市名的集合与矩阵本身作为参数传给processLine,这样很不合适。再就是,因为我们没提供执行错误检查的访问函数,所以使用距离矩阵容易出错。有个好的想法是,将表示城市名的Set对象和表示距离的apmatrix对象组合到DistMatrix类中。

下面是DistMatrix类头文件大概形式的一个草稿:

class DistMatrix {
private:
  Set cities;
  apmatrix<int> distances;

public:
  DistMatrix (int rows);

  void add (const apstring& city1, const apstring& city2, int dist);
  int distance (int i, int j) const;
  int distance (const apstring& city1, const apstring& city2) const;
  apstring cityName (int i) const;
  int numCities () const;
  void print ();
};

我们可以使用这个接口来简化main函数:

void main ()
{
  apstring line;
  ifstream infile ("distances");
  DistMatrix distances (2);

  while (true) {
    getline (infile, line);
    if (infile.eof()) break;
    processLine (line, distances);
  }

  distances.print ();
}

也可以简化 processLine函数:

void processLine (const apstring& line, DistMatrix& distances)
{
  char quote = ’\"’;
  apvector<int> quoteIndex (4);
  quoteIndex[0] = line.find (quote);
  for (int i=1; i<4; i++) {
    quoteIndex[i] = find (line, quote, quoteIndex[i-1]+1);
  }

  // 将行分割为子串
  int len1 = quoteIndex[1] - quoteIndex[0] - 1;
  apstring city1 = line.substr (quoteIndex[0]+1, len1);
  int len2 = quoteIndex[3] - quoteIndex[2] - 1;
  apstring city2 = line.substr (quoteIndex[2]+1, len2);
  int len3 = line.length() - quoteIndex[2] - 1;
  apstring distString = line.substr (quoteIndex[3]+1, len3);
  int distance = convertToInt (distString);

  // 将新数据添加到距离矩阵中
  distances.add (city1, city2, distance);
}

我把实现DistMatrix类的成员函数留作练习请读者完成。