【问题标题】:Inserting and removing elements from an array while maintaining the array to be sorted从数组中插入和删除元素,同时保持要排序的数组
【发布时间】:2011-10-29 07:50:32
【问题描述】:

我想知道是否有人可以帮助我解决这个问题。我正在使用 C/C++ 进行编程,我需要执行以下操作:

我得到一个包含浮点数的排序数组 P(最大的在前)。它通常具有非常大的尺寸..有时会保存 10 兆像素图像的相关值。我需要遍历数组直到它为空。在循环内进行额外的处理。

问题的要点是,在循环开始时,我需要从数组中删除具有最大值的元素,检查某些条件,如果它们成立,那么我需要将元素重新插入数组但是在降低他们的价值之后。但是,我希望在重新插入后对数组进行有效排序。

有人可以指出我这样做的方法吗?我尝试过每次插入时重新排序的天真方法,但这似乎真的很浪费。

【问题讨论】:

    标签: c++ c sorting priority-queue


    【解决方案1】:

    改变数据结构。重复访问最大元素,然后快速插入新值,这样您仍然可以有效地重复访问最大元素,这是 heap 的工作,可能是 fairly easily created from your array in C++

    顺便说一句,请不要谈论“C/C++”。没有这样的语言。相反,您对您编写内容的风格做出了模糊的暗示,其中大部分都会让有经验的程序员感到很糟糕。

    【讨论】:

    • 术语heap 在 C 和 C++ 中有另一个更常见的含义,更详尽的描述或链接会有所帮助。
    • 在C++中,priority_queue就是这样一个堆。
    • 感谢您的快速回复.. 我确实查找了最大根堆和优先级队列.. 但这里有一点细微差别,因为我必须将所有相等的数组值作为一个组来处理。我的意思是我不仅要删除最大元素,还要删除所有具有最大值的元素(如果有多个)..我可以用堆来做到这一点吗?
    • 可以弹出max元素,然后检查堆顶是否有相同的值,反复弹出直到不再有。
    【解决方案2】:

    您可以使用二进制搜索来确定在从数组中删除更改后的值的插入位置。请注意,在前面或中间某处插入或删除也不是很有效,因为它需要分别向上或向下移动所有具有更高索引的项目。

    ISTM,您应该在完成对原始数组的迭代后将更改的项目放入一个新数组并对其进行一次排序。如果内存有问题,而您确实必须在原地做事,请原地更改值并且只排序一次。

    我想不出更好的方法来做到这一点。一直保持数组排序似乎效率很低。

    【讨论】:

      【解决方案3】:

      我会调查http://www.cplusplus.com/reference/stl/priority_queue/,因为它就是为此而设计的。

      【讨论】:

        【解决方案4】:

        由于数组已经排序,您可以使用二进制搜索来查找插入更新值的位置。 C++为此提供了std::lower_boundstd::upper_bound,C提供了bsearch。只需将所有现有值在数组中上移一个位置,并将新值存储在新清除的位置。

        【讨论】:

        • 我想,必须一直移动所有元素以进行插入几乎会抵消首先保持事物排序的好处。无论哪种方式,每次都是 O(N),使用 std::lower_bound 只是一个常数因子的改进。
        • @Karl 最坏的情况是 O(N)。根据具体情况,这可能是一个可接受的解决方案(碰巧我在想完全相同的事情!)如果数组包含诸如 100 99 96 90 85 82 80 ... 之类的值,并且这些值正在减少,说 10 - 这样做一点也不坏。编辑:马克的回答可能有点误导,因为它说你必须改变“所有现有的元素”。例如,在按降序排序的数组中,您只需移动大于调整值的元素,正如我在回答中提到的那样。
        • priority_queue 会自动执行此操作。
        【解决方案5】:

        如果您不大幅减少删除的值,这里有一些伪代码可能会正常工作:

        例如,假设您正在处理数组中具有最大值的元素,并假设数组按降序排序(最大在前)。

        1. 删除array[0]

        2. newVal = array[0] - adjustment,其中adjustment 是您要减少的值。

        3. 现在循环,只调整您需要的值:

        伪代码:

        i = 0
        while (newVal < array[i]) {
          array[i] = array[i+1];
          i++;
        }
        array[i] = newVal;
        swap(array[i], array[i+1]);
        

        同样,如果您没有大量减少删除的值(相对于数组中的值),这可以相当有效地工作。

        当然,通常更好的选择是使用更合适的数据结构,例如堆。

        【讨论】:

        • “通常更好的选择是使用更合适的数据结构,例如堆。”似乎是重要的部分。
        【解决方案6】:

        也许使用另一个临时数组会有所帮助。

        这样你可以先单独对“改变”的元素进行排序。

        然后,只需将两个子数组的常规合并 O(n) 到 temp 数组,然后将所有内容复制回原始数组。

        【讨论】:

        • 每次都要合并,这比简单地重新插入相同的数据要慢。
        • 但据我了解,他需要从数组中删除最大值的元素,然后将它们的值减小后重新插入到数组中。因此,所有“更改”的值都将立即收到...这意味着只需要一次合并...
        • 是的,但是不能原地合并,这意味着你必须接触 3N 个数据。通过某种简单的移位和插入(如 vector::insert),最多 N 被触摸到位。
        猜你喜欢
        • 2012-11-22
        • 2022-06-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-01
        • 1970-01-01
        • 2010-11-24
        • 1970-01-01
        相关资源
        最近更新 更多