Algorithm 为web服务器设计一个数据结构来存储访问页面的历史记录

Algorithm 为web服务器设计一个数据结构来存储访问页面的历史记录,algorithm,data-structures,Algorithm,Data Structures,服务器必须在过去n天内维护数据。它必须先显示当天访问量最大的页面,然后显示第二天访问量最大的页面,依此类推 我在想一系列的散列图。有什么建议吗?这取决于你想要什么。例如,您是希望存储历史记录中页面的实际数据,还是仅存储URL?如果有人访问了一个页面两次,它应该在历史中出现两次吗 如果您希望存储一个页面的数据,并且希望每个页面只显示一次,则哈希映射是合适的 如果我认为更可能的是,你只想存储URL,但是希望每个存储多次,如果它被访问不止一次,那么数组/向量可能会更有意义。如果您希望看到大量(相对)长

服务器必须在过去n天内维护数据。它必须先显示当天访问量最大的页面,然后显示第二天访问量最大的页面,依此类推


我在想一系列的散列图。有什么建议吗?

这取决于你想要什么。例如,您是希望存储历史记录中页面的实际数据,还是仅存储URL?如果有人访问了一个页面两次,它应该在历史中出现两次吗

如果您希望存储一个页面的数据,并且希望每个页面只显示一次,则哈希映射是合适的


如果我认为更可能的是,你只想存储URL,但是希望每个存储多次,如果它被访问不止一次,那么数组/向量可能会更有意义。如果您希望看到大量(相对)长URL的重复,您可以创建一组URL,并为每次访问存储某种指向相关URL的指针/索引/引用。但是,请注意,维护这一点可能会变得不那么简单。

具有日期类型键和哈希映射类型值的外部哈希映射

具有包含url的字符串类型键和包含访问计数的int类型值的内部哈希映射

C#中的示例:

//外部哈希映射
var visitsByDay=
新字典(currentDate,newvisitsbyURL());
...
//内部哈希映射
公共类VisitsByUrl
{
公共字典URL{get;set;}
公共访问BYURL()
{
URL=新字典();
}
公共无效添加(字符串url)
{
如果(url[url]!=null)
url[url]+=1;
其他的
添加(url,1);
}
}

您可以为具有以下类型遗嘱的每一天保留一个哈希:-

和一个长度为n的队列。每天都会有这些散列。此外,您还将存储单独的hash totalHits,这些hash totalHits将对所有这些进行求和

Class Stats {
        queue< hash<url,hits> > completeStats;
        hash<url,hits> totalStats;
    public:-
        int getNoOfTodayHits(url) {
             return completeStats[n-1][url];
        }
        int getTotalStats(url) {
            return totalStats[url];
        }
        void addAnotherDay() { 
         // before popping check if the length is n or not :) 
         hash<url,hits> lastStats = completeStats.pop();
         hash<url,hits> todayStats;
         completeStats.push_back(todayStats);
           // traverse through lastStats and decrease the value from total stats;
        }
        // etc.

};
类统计信息{
队列完成测试;
散列totalStats;
公众:-
int getNoOfTodayHits(url){
返回完整测试集[n-1][url];
}
int getTotalStats(url){
返回totalStats[url];
}
void addAnotherDay(){
//弹出前检查长度是否为n:)
hash lastStats=completeStats.pop();
散列今日统计数据;
完成测试。推回(今天的统计);
//遍历lastStats并从total stats中减少值;
}
//等等。
};

我们可以结合使用堆栈和哈希映射

我们可以创建一个URL和时间戳的对象,然后将其推送到堆栈上。 最近访问的Url将位于顶部

我们可以使用时间戳结合URL来创建一个键,该键映射到访问的URL的数量

为了按时间顺序显示访问量最大的页面,我们可以弹出堆栈,创建一个键并获取与Url关联的计数。在显示时对它们进行排序


时间复杂度:O(n)+排序时间(取决于访问的页面数量)

我的想法也是一样的。这听起来是一个有效的解决方案。谢谢你的帮助!这与Karthik的期望背道而驰,没有考虑到他声明的功能需求——只有一个,而且不太现实,但是:“它必须先显示当天访问量最大的页面,然后显示第二天访问量最大的页面,依此类推”。散列图不会被排序,而你的散列图会被键入URL——你将如何找到访问量最大的页面?蛮力迭代,对于散列映射,它通常比向量迭代慢。散列映射允许快速的日内更新,但是当N的数组/向量更紧凑、更快时,为什么要使用外部散列映射呢?@Tony:我没说这是唯一的解决方案。对于完美主义类型的开发人员来说,它可能不够成熟/复杂/高效。谢谢你的否决票。有趣的解决方案,非常好。非常感谢。您选择使用哈希表队列而不是哈希表的哈希。你选择这个有什么特别的原因吗??我假设您在搜索统计数据时必须扫描整个队列并给出日期。你的想法是什么?我不需要在hash中处理键的日期:)Pop Push works:P
Class Stats {
        queue< hash<url,hits> > completeStats;
        hash<url,hits> totalStats;
    public:-
        int getNoOfTodayHits(url) {
             return completeStats[n-1][url];
        }
        int getTotalStats(url) {
            return totalStats[url];
        }
        void addAnotherDay() { 
         // before popping check if the length is n or not :) 
         hash<url,hits> lastStats = completeStats.pop();
         hash<url,hits> todayStats;
         completeStats.push_back(todayStats);
           // traverse through lastStats and decrease the value from total stats;
        }
        // etc.

};