4

我正在实施排序。该程序从带有 ASCII 字符的文本文件中读取。每行有两个元素,由空格分隔。假设输入是“a b”。这定义了 a 和 b 之间的优先关系,即“a 必须出现在 b 之前”。

所以如果文件是

抗体
直流
BD

输出是

一个
b
d
C

我创建了两个链表

  • bigList:存储唯一元素(count跟踪前面的元素)
  • smallList: 存储前面的元素
  • 项目清单

我的代码做了什么的总结

  • 逐行读取文件
  • 每行抓取两个元素
  • 检查它们是否已经存在,如果不存在则插入它们
  • 根据计数打印出结果

它实际上打印出文件中的所有元素,就像上面的输入一样,我的输出是

一个
b
b
d
d
C

我是 C 编程新手,请让我知道我做错了什么。

4

1 回答 1

2

我对拓扑排序知之甚少,但我认为我知道的足够多,可以发表明智的评论。任何人都应该随时编辑此回复。

我看到这个实现有几个问题。一些与 C 有关,另一些与算法有关,所以让我一次过一遍。


问题定义拓扑排序确实被定义为有向图中元素的优先级。但是,仅凭这句话并不能完全定义问题。具体来说,拓扑排序是从指定源顶点开始的图元素的优先级。例如,假设您有以下有向图:

a -> b
b -> c
c -> a

如果你从 vertex 开始a,你的拓扑顺序应该是{a, b, c}. 如果你从 vertex 开始c,你的拓扑顺序应该是{c, a, b}. 因此,如果没有源顶点,问题定义就毫无意义。这种顶点的一种选择可以是图中没有指向它的边的某个顶点,即每个入射边都是出边。

要记住的另一件事是图形连通性。从任何其他顶点到达任何顶点并不总是可能的。因此,在实现此类算法时值得牢记。


好的数据结构是好的算法的关键。如果你想在有向图中对事物进行排序,最好的办法是创建一个有向图数据结构,这本身就涉及创建一个Node数据结构和一个Edge数据结构。我建议查找邻接列表。一旦你有了这样的数据结构,就可以在图上运行广度优先搜索,并且你会得到你的拓扑优先级作为一个简洁的结果。

在实现邻接列表时,您仍然需要将所有元素存储在一个地方。链表通常不是最好的方法,因为插入一个列表需要恒定的时间(假设对数据进行排序),搜索一个需要线性时间。那是次优的。正如@David RF所建议的那样,红黑树AVL 树将是要走的路。但是,我不会从这个优化开始。只要你有一个完善的工作算法,你总是可以改进你的存储数据结构。毕竟,链表和搜索树的接口是一样的。


如果您使用正确的算法,该算法可以很快。我在实践中没有处理过拓扑排序,所以我不知道每一个复杂性和每一个边缘情况。但!如果您使用传统的节点边数据结构进行广度优先搜索(请注意,边可以在节点内隐式定义),您的搜索本身应该使用广度优先搜索花费线性时间。

我已经阅读了你的算法,我不得不承认我并没有完全理解你的大列表和小列表的概念。模棱两可的名字并没有真正的帮助。也许它通过隐藏在某个地方的一个小错误来完成这项工作,但它不太可读。也许其他人可以评论您当前的实施。

于 2013-03-06T10:15:58.747 回答