计算C ++

时间:2016-02-01 13:22:26

标签: c++ class types stl

我想结合三种游程长度编码方案(游程长度累积,因此变量)。
让我们从其中两个开始:
第一个包含布尔列表,第二个包含计数器列表。让我们说第一个看起来如下:(值:该值的位置):

[(true:6), (false:10), (true:14), (false:20)]
// From 1 to 6, the value is true
// From 7 to 10, the value is false
// From 11 to 14, the value is true
// From 15 to 20, the value is false

第二个看起来如下(再次(值:该值的位置)):

[(1:4), (2:8), (4:16), (0:20)]
// From 1 to 4, the value is 1
// From 5 to 8, the value is 2
// From 9 to 16, the value is 4
// From 17 to 20, the value is 0

如您所见,两种情况下的立场略有不同:

Case 1 : [6, 10, 14, 20]
Case 2 : [4, 8, 16, 20]

我想通过计算它们的联合来组合这些"位置数组"

[4, 6, 8, 10, 14, 16, 20]

有了这个,我会从那里得到新的方案:

[(true:4), (true:6), (false:8), (false:10), (true:14), (false:16), (false:20)]
[(1:4), (2:6), (2:8), (4:10), (4:14), (4:16), (0:20)]

我想知道:是否有任何C ++标准类型/类可以包含"数组" [6,10,14,20]和[4,8,16,20],计算它们的联合并排序吗?

感谢
多米尼克

3 个答案:

答案 0 :(得分:2)

您需要使用<algorithm>中的std::set_union

我在这里使用std::vector<int>,但它可以是任何模板类型。

#include <iostream>
#include <array>
#include <algorithm>

int main() {
  std::vector<int> a{6, 10, 14, 20};
  std::vector<int> b{4, 8, 16, 20};
  std::vector<int> c;

  std::set_union(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(c));
  for(auto e: c) {
    std::cout << e << ' ';
  }
  std::cout << '\n';
}

Here's the ideone

如果您想在不引入std::vector的情况下仅保留两个c,则只需将b附加到a,对数组进行排序,然后调用{{ 1 {} std::unique。在a可能是一种聪明的方法,但这是天真的方法:

O(n)

Here's the ideone

最后,您可以使用#include <iostream> #include <algorithm> #include <vector> int main() { std::vector<int> a{6, 10, 14, 20}; std::vector<int> b{4, 8, 16, 20}; a.insert(a.end(), b.begin(), b.end()); std::sort(a.begin(), a.end()); auto last = std::unique(a.begin(), a.end()); a.erase(last, a.end()); for(auto e: a) { std::cout << e << ' '; } std::cout << '\n'; } 代替std::inplace_merge。在最糟糕的情况下,它是std::sort,如O(nlogn),但在最好的情况下,它是std::sort。性能相当提高:

O(n)

Here's the ideone

答案 1 :(得分:1)

正如erip暗示的那样,有一种算法只需要你迭代两个向量一次。作为前提条件,它们都必须在开始时进行排序。您可以使用该事实来始终检查哪个较小,并且仅将该向量中的值附加到结果中。它还允许您删除重复项,因为如果要添加值,如果该值是添加到结果向量的最后一个值,则该值将仅为重复值。

我已经掀起了一些代码;我没有对它进行过大量的测试,所以它可能仍然是一个小马车,但是你走了:

// Assume a and b are the input vectors, and they are sorted.
std::vector<int> result;

// We know how many elements we will get at most, so prevent reallocations
result.reserve(a.size() + b.size());

auto aIt = a.cbegin();
auto bIt = b.cbegin();

// Loop until we have reached the end for both vectors
while(aIt != a.cend() && bIt != b.cend())
{
    // We pick the next value in a if it is smaller than the next value in b.
    // Of course we cannot do this if we are at the end of a.
    // If b has no more items, we also take the value from a.
    if(aIt != a.end() && (bIt == b.end() || *aIt < *bIt))
    {
        // Skip this value if it equals the last added value
        // (of course, for result.back() we need it to be nonempty)
        if(result.size() == 0 || *aIt != result.back())
        {
            result.push_back(*aIt);
        }
        ++aIt;
    }
    // We take the value from b if a has no more items, 
    // or if the next item in a was greater than the next item in b
    else
    {
        // If we get here, then either aIt == a.end(), in which case bIt != b.end() (see loop condition)
        // or bIt != b.end() and *aIt >= *bIt.
        // So in either case we can safely dereference bIt here.
        if(result.size() == 0 || *bIt != result.back())
        {
            result.push_back(*bIt);
        }
        ++bIt;
    }
}

它允许在样式和性能方面进行一些优化,但我认为它总体上起作用。

当然,如果您希望将结果重新放回a,您可以修改此算法以直接插入a,但保持这样的速度可能会更快a.swap(result)最后。

您可以在行动here中看到它。

答案 2 :(得分:1)

  

我想知道:是否有任何C ++标准类型/类可以包含&#34;数组&#34; [6,10,14,20]和[4,8,16,20],计算它们的联合并排序吗?

我猜你在提出这个问题之前没做太多研究。这是一个管理有序集的类模板,名为set。如果将两个集合的所有元素添加到一个集合中,您将拥有该集合。

std::set<int> s1{6, 10, 14, 20};
std::set<int> s2{4, 8, 16, 20};

std::set<int> union = s1;
union.insert(s2.begin(), s2.end());