【问题标题】:how to create a hash table using the given classes如何使用给定的类创建哈希表
【发布时间】:2014-09-28 12:43:46
【问题描述】:

我目前正在完成我的计算机科学作业,但在最后一点上遇到了问题,我正在寻求一些建议。

使用以下类:

class CounterLinkedList:
    __n_comparisons__ = 0

    def __init__(self, head=None):
        self.head = head
        self.__n_accesses__ = 0

    def __repr__(self):
        node = self.head
        string = str(node)
        while node.next_node:
            string += " -> " + str(node.next_node)
            node = node.next_node
        string = "[" + string + "]"
        return string

class MyString:
    '''A wrapped string that counts comparisons of itself
   against strings and delegates all other operations to the
   string itself.'''
    def __init__(self, i):
        self.i = i

    def __repr__(self):
        return repr(self.i)

    def __getattr__(self, attr):
        '''All other behaviours use self.i'''
        return self.i.__getattr__(attr)    


class CounterNode:
    def __init__(self, word, count=1):
        self.word = MyString(word)
        self.count = count
        self.next_node = None

    def __repr__(self):
        return str(self.word) + ": " + str(self.count)


def _c_mul(a, b):
    """Substitute for c multiply function"""
    return ((int(a) * int(b)) & 0xFFFFFFFF)


def nice_hash(input_string):
    """Takes a string name and returns a hash for the string. This hash value
    will be os independent, unlike the default Python hash function."""
    if input_string is None:
        return 0  # empty
    value = ord(input_string[0]) << 7
    for char in input_string:
        value = _c_mul(1000003, value) ^ ord(char)
    value = value ^ len(input_string)
    if value == -1:
        value = -2
    return value


def hash_word(item, slots):
    return nice_hash(item) % slots

我需要在不使用字典的情况下实现一个哈希表,每次你从单词列表中取出一个单词时,你都会检查它是否在哈希表中,如果是则增加它的计数。如果不是,则将其计数插入表中,如果哈希表槽中已经存在对象,则使用链接。链接是通过链表完成的。

如果我使用输入,代码的输出:

slots = 3
counts, comparisons = word_counter_hash(['list', 'with', 'no', 'repeat', 'words'], slots)
for i in range(slots):
    print(str(i) + ": " + str(counts[i]))
print(comparisons)

应该输出:

0: ['words': 1 -> 'no': 1 -> 'list': 1]
1: ['repeat': 1]
2: ['with': 1]
3 

到目前为止我的代码是:

'''test'''
from classes_2 import CounterNode, CounterLinkedList, hash_word


def word_counter_hash(words_list, slots):
    """test"""
    hash_list = [None]*slots
    num_comparisons = 0
    for new_word in words_list:
        if len(words_list) >= 0:
            n = CounterNode(new_word, 1)
            new_list = CounterLinkedList(n)
            hash_value = hash_word(new_word, slots)
            if hash_list[hash_value] == None:
                del hash_list[hash_value]
                hash_list.insert(hash_value, new_list)
            else:
                first_node = new_list.head
                first_node.next_node = CounterNode(words_list[hash_value], 1)
                first_node = (new_list)
                del hash_list[hash_value]
                hash_list.insert(hash_value, new_list)

    return hash_list, num_comparisons  

但是我的输出和上面的不一样:

0: ['words': 1 -> 'list': 1]
1: ['repeat': 1]
2: ['with': 1]
0

我正在寻求任何关于我可以做些什么来走上正轨的建议,我们将不胜感激。

【问题讨论】:

  • 这段代码有点长。是否有可能削减一点,还是全部都需要?
  • @Veedrac,不幸的是需要巨大的类代码,因为它限制了分配,以及我们制定答案的基础
  • assignment 可能需要它,但现在我们只需要重现该错误。删除与此无关的内容会有所帮助。
  • @Veedrac 对此感到抱歉,我已尽量减少它

标签: python hash linked-list nodes


【解决方案1】:

首先要注意的是:

nice_hash("list") % 3
#>>> 0

nice_hash("no") % 3
#>>> 0

nice_hash("words") % 3
#>>> 0

这些都会在第一个盒子上发生碰撞。因此,让我们尝试删除除第一个框之外的所有框:

slots = 1
counts, comparisons = word_counter_hash(['a', 'b', 'c'], slots)
print(counts[0])
#>>> ['c': 1 -> 'a': 1]

这会重现问题。好的。现在我们可以替换hash_word

def hash_word(item, slots):
    return 0

效果不好也没关系;它重现了问题。事实上,我们不再需要函数,我们可以硬编码一个哈希值0。

通过这些简化,我们得到:

def word_counter_hash(words_list):
    hash_list = [None]

    for new_word in words_list:
        new_list = CounterLinkedList(CounterNode(new_word, 1))

        if hash_list[0] == None:
            del hash_list[0]
            hash_list.insert(0, new_list)

        else:
            first_node = new_list.head
            first_node.next_node = CounterNode(words_list[0], 1)
            first_node = (new_list)
            del hash_list[0]
            hash_list.insert(0, new_list)

    return hash_list

counts = word_counter_hash(['a', 'b', 'c'])
print(counts[0])
#>>> ['c': 1 -> 'a': 1]

注意:

del hash_list[idx]
hash_list.insert(idx, X)

这只是一种非常缓慢的方式

hash_list[idx] = X

所以我们有

def word_counter_hash(words_list):
    hash_list = [None]

    for new_word in words_list:
        new_list = CounterLinkedList(CounterNode(new_word, 1))

        if hash_list[0] == None:
            hash_list[0] = new_list

        else:
            first_node = new_list.head
            first_node.next_node = CounterNode(words_list[0], 1)
            first_node = (new_list)
            hash_list[0] = new_list

    return hash_list

counts = word_counter_hash(['a', 'b', 'c'])
print(counts[0])
#>>> ['c': 1 -> 'a': 1]

这一行什么都不做:

first_node = (new_list)

由于我们从未真正使用过fist_node,我们可以将其重写为:

def word_counter_hash(words_list):
    hash_list = [None]

    for new_word in words_list:
        new_list = CounterLinkedList(CounterNode(new_word, 1))

        if hash_list[0] == None:
            hash_list[0] = new_list

        else:
            new_list.head.next_node = CounterNode(words_list[0], 1)
            hash_list[0] = new_list

    return hash_list

counts = word_counter_hash(['a', 'b', 'c'])
print(counts[0])
#>>> ['c': 1 -> 'a': 1]

然后我们可以对hash_list[0] = new_list这一行进行去重:

def word_counter_hash(words_list):
    hash_list = [None]

    for new_word in words_list:
        new_list = CounterLinkedList(CounterNode(new_word, 1))

        if hash_list[0] != None:
            new_list.head.next_node = CounterNode(words_list[0], 1)

        hash_list[0] = new_list

    return hash_list

counts = word_counter_hash(['a', 'b', 'c'])
print(counts[0])
#>>> ['c': 1 -> 'a': 1]

所以我们:

  • 制作新列表

  • 如果已经有列表,将new_list第二个元素设置为words_list[0](原为words_list[hash_value]

  • 设置新列表

现在,第二个看起来不对。

所以你应该这样做:

  • 如果节点是None,则新建一个列表

  • 如果节点不是None,则遍历它

    • 如果您发现某物已经存在,请增加其编号

    • 如果不这样做,则将当前节点作为新节点添加到末尾

像这样:

def word_counter_hash(words_list):
    hash_list = [None]

    for new_word in words_list:
        if hash_list[0] == None:
            hash_list[0] = CounterLinkedList(CounterNode(new_word, 1))

        else:
            node = hash_list[0].head

            while True:
                if node.word == new_word:
                    node.count += 1
                    break

                elif not node.next_node:
                    node.next_node = CounterNode(new_word, 1)
                    break

                node = node.next_node

    return hash_list

counts = word_counter_hash(['a', 'b', 'c', 'c', 'a'])
print(counts[0])
#>>> ['a': 2 -> 'b': 1 -> 'c': 2]

我试图让它变得非常简单。

我让你把hash_list[0]改为hash_list[hash_value]

【讨论】:

  • 非常感谢您这么详细的回答!它使事情更容易理解
猜你喜欢
  • 2012-01-02
  • 2011-09-20
  • 2010-10-22
  • 2015-10-06
  • 2011-04-20
  • 2016-10-02
  • 2012-12-16
  • 2013-12-20
  • 1970-01-01
相关资源
最近更新 更多