在日志结构化文件系统中查找记录的算法

时间:2015-06-02 20:28:25

标签: algorithm logging data-structures filesystems

我有记录日志。每条记录都有一个ID和时间戳。即使可以删除其间的记录,新记录也会以单调递增的ID附加到日志中。

问题是 - 如果给你一个时间戳T1,提供一个有效的算法来确定时间戳= Ceil(T1)的日志记录。

注意事项。数百万条记录的日志可能非常大。由于记录删除,可能会丢失记录。

示例:如果log record =(ID,Timestamp),则log可以显示如下:

(1,10),(2,11),(5,15),(8,18),(9,19),(10,20)

查找最小时间戳大于或等于17的记录的ID。

答案是8。

查找最小时间戳大于或等于11的记录的ID。

答案是2。

查找最小时间戳大于或等于22的记录的ID。

答案是Nil

查找最小时间戳大于或等于5的记录的ID。

答案是1

我已经提出了简单的数据结构来解决这个问题。

/* index:    0  1   2   3   4  5  6   7   8  9  10   11   12  */

int ids[]=     {1,  2,            6,  7,        10,  11,  12};
int map[]=  {0, 1,  1,  0,  0, 0, 1,  1,  0, 0, 1,   1,   1};
int time[]= {0, 10, 20, 0,  0, 0, 60, 70, 0, 0, 100, 110, 120};
int start= 1, end = 12;  // this is known to us.

ids []是所有ID的列表。鉴于此列表可能是数百万,我们无法将此列表编入索引。因此在上面的示例中,缺少ID 3,4,5,8,9。但是这份名单正在增加。

map []是位图,可以告诉您是否存在给定的ID。这是一个廉价的操作。

time []是存在的每个ID的时间戳数组。记得假设获取时间戳实际上是昂贵的操作。

ID和时间戳值之间也没有相关关系。而不是10,20,等等,它可能像1133,2987 ......等等。但是按顺序递增。

您需要填写此功能:

int
find_ceil_id(int timestamp) 
{
  .....
  ....
  return(id)
}

1 个答案:

答案 0 :(得分:0)

如果此功能在搜索之间保留在内存中,我们可以利用之前的搜索来缩小未来的搜索范围。如果到达时间戳是昂贵的,那么这可能是一个非常显着的改进。但是如果它们已经在你的帖子中的数组中已经存在,那么这主要是一个没有实际意义的点。 假设时间戳是唯一的,我将从此开始寻求解决方案:

int FindFirstNonZero(int startIdx)
{
    int myIdx=startIdx;
    while (map[myIdx] == 0)
    {
        myIdx++;
    }
    return(myIdx);
}

int FindLastNonZero(int startIdx)
{
    int myIdx=startIdx;
    while (map[myIdx] == 0)
    {
        myIdx--;
    }
    return(myIdx);
}

int find_ceil_id(int timestamp) 
{
    int low=FindFirstNonZero(0);
    int high=FindLastNonZero(map.count -1);
    int checkIndex = FindLastNonZero((low + high)/2);
    int checkTime;

    while (low < FindLastNonZero(high - 1))
    {
        checkTime = time[checkIndex];
        if (checkTime >= timestamp) {
            high = checkIndex;
        } else {
            low = checkIndex;
        }
        checkIndex = FindLastNonZero((low+high) / 2);
        if (checkIndex == low) {
            checkIndex = FindFirstNonZero(low+1);
        }
    }
    return (high);
}

从您的一些评论中,似乎时间戳可以重复。是这样吗?如果是这样,它将需要对上述内容进行微小改动......没关系,做出改变,甚至使代码更简单。

这是一个基本的二进制搜索,它将在log2(N)尝试中找到正确的元素,N是ID数组的大小。因此,对于ID数组中的超过一百万个条目,它只需要检查其中的20个以获得正确的条目。对于超过十亿的条目,它只需要检查30。

我没有编译和测试代码,这取决于你。但它应该有用。

相关问题