C++ 具有链接列表的哈希表中的前10个频率
下面的代码将在我的哈希表(其中有一组链表)中以最高频率打印我10次。我需要我的代码来打印哈希表中的前10个频率。我不知道如何做到这一点(代码示例会很好,纯英语逻辑/伪代码也一样好)C++ 具有链接列表的哈希表中的前10个频率,c++,pointers,loops,hashtable,linked-list,C++,Pointers,Loops,Hashtable,Linked List,下面的代码将在我的哈希表(其中有一组链表)中以最高频率打印我10次。我需要我的代码来打印哈希表中的前10个频率。我不知道如何做到这一点(代码示例会很好,纯英语逻辑/伪代码也一样好) 我创建了一个名为“tmp”的临时哈希列表,它指向我的哈希表“hashtable” 然后,while循环遍历列表并查找最高频率,即int'tmp->freq' 循环将继续使用变量“topfreq”复制找到的最高频率,直到到达哈希表上链接列表的末尾 我的“node”是一个由变量“freq”(int)和“word”(128
void toptenwords()
{
int-topfreq=0;
int minfreq=0;
字符首字[SIZEOFWORD];
对于(int p=0;p<10;p++)//我们需要前10个频率……所以我们做了10次
{
for(int m=0;mfreq>topfreq)//如果手头的频率大于找到的频率,则存储。。。
{
topfreq=tmp->freq;
strcpy(topword,tmp->word);
}
tmp=tmp->next;
}
}
cout我将维护一组已经使用的单词,并更改最内部的if条件,以测试频率是否大于以前的最高频率,以及tmp->word是否不在已经使用的单词列表中。在哈希表上(然后在其中包含的每个链接列表上)进行迭代时,保留一个自平衡二叉树(std::set)作为“结果”列表。当您遇到每个频率时,将其插入列表,如果列表中有10个以上的条目,则将其截断。完成后,您将拥有一组前十个频率(排序列表),您可以根据需要对其进行操作
使用集合而不是哈希表本身中的链表可能会有执行增益,但您可以自己解决。保留一个包含10个节点指针的数组,并将每个节点插入数组,保持数组的排序顺序。数组中的第十一个节点在每次迭代时都会被覆盖,并且包含垃圾
void toptenwords()
{
int topfreq = 0;
int minfreq = 0;
node *topwords[11];
int current_topwords = 0;
for(int m = 0; m < HASHTABLESIZE; m++) // Go through the entire hast table
{
node* tmp;
tmp = hashtable[m];
while(tmp != NULL) // Walk through the entire linked list
{
topwords[current_topwords] = tmp;
current_topwords++;
for(int i = current_topwords - 1; i > 0; i--)
{
if(topwords[i]->freq > topwords[i - 1]->freq)
{
node *temp = topwords[i - 1];
topwords[i - 1] = topwords[i];
topwords[i] = temp;
}
else break;
}
if(current_topwords > 10) current_topwords = 10;
tmp = tmp->next;
}
}
}
void toptenwords()
{
int-topfreq=0;
int minfreq=0;
节点*topwords[11];
int current_topwords=0;
for(int m=0;m0;i--)
{
中频(topwords[i]>freq>topwords[i-1]>freq)
{
节点*temp=topwords[i-1];
topwords[i-1]=topwords[i];
topwords[i]=温度;
}
否则就断了;
}
如果(当前单词>10)当前单词=10;
tmp=tmp->next;
}
}
}
步骤1(效率低下):
通过插入排序将向量移动到已排序的容器中,但插入大小为10的容器(例如linkedlist或vector),并删除列表底部的所有元素
步骤2(高效):
与步骤1相同,但要跟踪列表底部项目的大小,如果当前项目太小,则完全跳过插入步骤。如果目标是累积单词频率,则包含单词链接列表的哈希表似乎是一种特殊的数据结构
尽管如此,获得十个最高频率节点的有效方法是将每个节点插入优先级队列/堆,例如Fibonacci堆,该堆有O(1)个插入时间和O(n)个删除时间。假设哈希表上的迭代速度很快,该方法的运行时为O(n×O(1)+10×O(n))≡ O(n)。假设总共有n个单词,我们需要最频繁的k个单词(这里,k=10)
如果n比k大得多,我所知道的最有效的方法是保持一个最小堆(即,堆中所有元素的最小频率都是顶部元素)。在每次迭代中,将下一个频率插入堆中,如果堆现在包含k+1个元素,则删除最小的元素。这样,堆始终保持k个元素的大小,随时包含迄今为止看到的k个最高频率元素。在处理结束时,在inc中读取k个最高频率元素恢复秩序
时间复杂度:对于n个字中的每一个,我们做两件事:插入一个大小不超过k的堆,并删除最小的元素。每个操作花费O(logk)时间,因此整个循环需要O(nlogk)时间。最后,我们从大小不超过k的堆中读取k个元素,需要O(klogk)时间,总时间为O((n+k)logk)因为我们知道k绝对值
void toptenwords()
{
int topfreq = 0;
int minfreq = 0;
node *topwords[11];
int current_topwords = 0;
for(int m = 0; m < HASHTABLESIZE; m++) // Go through the entire hast table
{
node* tmp;
tmp = hashtable[m];
while(tmp != NULL) // Walk through the entire linked list
{
topwords[current_topwords] = tmp;
current_topwords++;
for(int i = current_topwords - 1; i > 0; i--)
{
if(topwords[i]->freq > topwords[i - 1]->freq)
{
node *temp = topwords[i - 1];
topwords[i - 1] = topwords[i];
topwords[i] = temp;
}
else break;
}
if(current_topwords > 10) current_topwords = 10;
tmp = tmp->next;
}
}
}