在中间插入时保持集合排序的算法

时间:2010-02-01 20:33:23

标签: algorithm

假设我有很多元素 每个元素都有一个“位置”字段,它是一个正整数 没有两个元素对字段“position”具有相同的值。

该集合唯一支持的操作是:addElement(newElement,positionAfterElement),其中:
  - newElement是要添加的新元素(其位置目前尚不清楚)
  - positionAfterElement是集合的现有元素。

该功能将保证:
  - position(positionAfterElement)<位置(为newElement)
  - 集合中没有其他元素在position(positionAfterElement)和position(newElement)之间的位置

我可以根据需要更改所有元素位置的值,但我希望最小化更改次数(平均)。

我应该如何实现addElement函数?

我可以将更高位置的所有元素推到1但我很确定必须有更好的方法来做到这一点。

感谢大家的帮助。

3 个答案:

答案 0 :(得分:3)

使用平衡树。在树的每个节点处,保持其下方项目数的计数(left.count + right.count + 1)。然后,您可以在遍历项目时轻松计算项目的索引。这是操作次数的O(n log n)时间。

答案 1 :(得分:1)

这是一个基本想法:

expected_number_of_elements = 10^6
spread_factor = 100
first element gets position = spread_factor * expected_number_of_element
each following element inserted:
    if its inserted in last position, give it the last element's position + spread_factor
    if its inserted in the first position, give it the first element's position - spread_factor
    otherwise, put it in the middle between its 2 closest neighbors
    if you don't have any space left: expand_the_array


expand_the_array:
    spread_factor = spread_factor * 10
    iterate over all the elements, and multiply position by 10.

扩展数组是一项昂贵的操作,但由于它平均增加了数组的大小(假设您的输入是随机的,而不是由对手制作),您将很少进行此操作。

这个解决方案的主要缺点是,你必须注意int溢出....

答案 2 :(得分:1)

好的,所以这是我用伪代码实现的:

addElement(newElement, positionAfterElement):
    p0 <- positionOf(positionAfterElement)
    c <- 5
    finished <- false
    while (not finished):
        search for all elements which positions are in the range [p0 + 1, p0 + c]
        if there are less than c elements in that range:  // the range is not full
            adjust position of elements in the range, and position of newElement,
            so that
              - elements are correctly ordered
              - element positions are "evenly spread out" within the range
            finished <- true
        else:                                             // the range is full
            c <- c * 2
    end while
end addElement