使用哈希表构建符号表

Building symbol table using hash table

本文关键字:符号 构建 哈希表      更新时间:2023-10-16

我正在尝试使用哈希表构建符号表。一般思路是

int alpha;
2 int beta;
3 alpha = 0; // the alpha declared in line 1
4 beta = 0; // the beta declared in line 2
5 gamma = 0; // Error! gamma hasn't been declared.
6 {
7 int beta; // This beta shadows the one declared in line 2.
8 int gamma;
9 alpha = 0; // the alpha declared in line 1
10 beta = 0; // the beta declared in line 7
11 gamma = 0; // the gamma declared in line 8
12 }

等等。您只能使用向量、列表、堆栈和队列库,并尝试使其尽可能快。我的想法是在每个作用域上,我在列表中声明哈希表并将所有信息保存到该表中,每当我有新作用域时,我都会将新的哈希表push_back到列表中。但是,当程序在很远的地方寻找超出范围的项目时,这种方法似乎非常慢,因为您必须查找每个范围才能找到该项目。

你们有什么想法来实现这个比这快得多的范围吗?它应该更快,因为我的实现比"他们提供的慢速版本"慢

多谢!

所有内容只有一个哈希表,以及一堆上下文对象。每当看到"{"时,在堆栈上推送一个新对象。当您隐藏变量时,请记住上下文对象中的旧符号,并在哈希表中覆盖它。当您看到"}"并弹出上下文时,请恢复您在那里记住的符号。

当我这样做时,我将哈希表用于符号,而不是实体。对于每个符号,我都有一个实体列表。 每个实体分为两个列表,一个来自符号,第二个来自范围。 目录从符号像堆栈一样管理:当我访问一个符号时,范围内的实体始终是列表中的第一个。 当我离开示波器时,我遍历了它的实体列表,并将它们从符号。

这是一段时间前,在STL之前(甚至在C++之前(;我手动实现所有内容,并使用侵入式链列表,算法设计如此之好,我可以删除一个元素从列表中不知道列表本身的位置。 (这是使用手写的双链表相对容易。 今天,随着STL(以及访问位置的重要性(,我可能会简单地在每个实体中放置指向列表头部的指针。 使用 STL,以及考虑到位置,我可能会使用std::vector作为列表对于每个实体(符号表因此是std::string的映射 std::vector (。 符号表查找,一旦找到条目,就很简单在向量上调用back()(在检查它是否不为空后,如果当向量变为空时,不会清除条目(。 当你在新范围内创建新实体,在向量上调用push_back,并将向量的地址保存在作用域的条目中(a std::stack std::vector<std::vector<Entity>*>(;离开时范围,你迭代此堆栈顶部的向量,调用 pop_back其所有条目,然后将其从堆栈中弹出。 (和显然,当输入新示波器时,您将一个新的空向量push作用域堆栈。

维护双重列表意味着对于所有操作,您知道确切地访问哪个元素,而无需迭代什么;永远无法访问实体以查看它是否是实体你正在寻找。 在我那个时代,这相当简单,但很多代码,需要相当小心,我的实现可能今天不会那么快,因为地方差。 今天,随着STL,您需要的代码要少得多,并且通过使用std::vector进行所有列表,你会得到稍微好一点的地方;你还是要小心,这样您就不会最终保存将失效的迭代器。(但如上所述实现,您不需要;所有访问总是到向量的最后一个元素,所以保存地址载体本身就足够了。 当然,前提是你的哈希实现不会移动向量。

这是一个好主意。在大多数语言中,作用域很少嵌套得很深,可能平均嵌套 3 或 4 个。所以我不会担心"遥远"的事情,因为这些将是病理病例。