C++ 迭代排序列表并计算不同的数字

C++ 迭代排序列表并计算不同的数字,c++,list,unique,counting,C++,List,Unique,Counting,我想迭代一个排序列表以获得不同数字的数目 请在下面找到我实现此功能的尝试。列表的大小为k*k。 在对列表进行排序时,我比较连续的项以识别重复项 int count_distinct(list<int> v) { int num = k*k; std::list<int>::iterator it; it = v.begin(); for (int a=0; a<k*k-1; a++) { if(*it == *

我想迭代一个排序列表以获得不同数字的数目

请在下面找到我实现此功能的尝试。列表的大小为
k*k
。 在对列表进行排序时,我比较连续的项以识别重复项

int count_distinct(list<int> v)
{
    int num = k*k;
    std::list<int>::iterator it;
    it = v.begin();
    for (int a=0; a<k*k-1; a++)
    {
        if(*it == *it+1)
            num--;
        it++;
    }

    return num;
}
int count\u distinct(列表五)
{
int num=k*k;
std::list::迭代器;
it=v.begin();

对于(inta=0;a如何使用
std::set
获取唯一元素计数

size_t count_distinct(const list<int>& v)
{    
    std::set<int> temp (v.begin(), v.end());

    return temp.size(); 
}
size\u t count\u distinct(常数列表&v)
{    
设置温度(v.begin(),v.end());
返回温度大小();
}

假设您希望在该列表中查找唯一整数的数量,并且该列表未排序,则可以使用临时集合或无序集合,如下所示:

size_t count_distinct(list<int> v)
{
    std::unordered_set<int> distinct;
    for(auto &x : v)
    {
        distinct.insert(x);
    }
    return distinct.size();
}
size_t count_distinct(const std::list<int>& l) {
    if (l.empty()) return 0;

    size_t distinct = l.size();
    auto prev = l.begin();

    for (auto cur = std::next(prev); cur != l.end(); ++cur, ++prev) {
        if (*cur == *prev)
            --distinct;
    }

    return distinct;
}
size\u t count\u distinct(列表五)
{
std::无序的_集不明显;
用于(自动和x:v)
{
插入(x);
}
返回distinct.size();
}

下面是一个提取所有唯一值的容器的解决方案 (因为你说过你想在事后使用它们):

一种计算唯一值的方法:

template < typename T >
size_t count_unique(const std::list<T> & input)
{
    std::set<T> unique(input.begin(), input.end());
    return unique.size();
}
template < typename T >
void unique(const std::list<T> & input, std::list<T> & output)
{
    std::set<T> unique(input.begin(), input.end());   
    std::copy(unique.begin(), unique.end(), std::back_inserter(output));
}
模板
大小计数唯一(常数标准::列表和输入)
{
std::set unique(input.begin(),input.end());
返回唯一的.size();
}
提取唯一值列表的方法:

template < typename T >
size_t count_unique(const std::list<T> & input)
{
    std::set<T> unique(input.begin(), input.end());
    return unique.size();
}
template < typename T >
void unique(const std::list<T> & input, std::list<T> & output)
{
    std::set<T> unique(input.begin(), input.end());   
    std::copy(unique.begin(), unique.end(), std::back_inserter(output));
}
模板
void unique(常量std::列表和输入,std::列表和输出)
{
std::set unique(input.begin(),input.end());
std::copy(unique.begin()、unique.end()、std::back_插入器(输出));
}
示例程序:

int main(int argc, char** argv)
{
    std::list<int> list = { 1, 3, 4, 10, 3, 1, 6, 7 };
    std::list<int> out;

    std::cout << count_unique(list) << std::endl;

    unique(list, out);
    for (auto & x : out)
        std::cout << x << std::endl;
}
int main(int argc,char**argv)
{
列表={1,3,4,10,3,1,6,7};
列出来;

std::cout您可以使用
std::list::unique()
获取
v
中的所有不同元素,并使用
size()
对它们进行计数。
v
必须进行排序。检查是否使用函数std::is\u sorted()对
v
进行排序。如果没有,则对其进行排序。这还意味着
count\u distinct
对常量列表对象不起作用

size_t count_distinct(list<int>& v)
{
    if (!is_sorted(v.begin(), v.end()))
    {
        v.sort();
    }
    v.unique();
    return v.size();
}
size\u t count\u distinct(列表和v)
{
如果(!已排序(v.begin(),v.end())
{
v、 排序();
}
v、 唯一();
返回v.size();
}

您的代码存在以下问题:

  • 您可以通过值将容器传递给函数。您应该通过常量引用来传递它,以最小化速度和内存损失
  • 你的条件
    *it==*it+1
    总是错误的(你比较
    n
    n+1
    )。可能你想写
    *it=*(it+1)
    ,但是
    std::list
    有,你不能
    +1
    它们
  • 代码应如下所示:

    size_t count_distinct(list<int> v)
    {
        std::unordered_set<int> distinct;
        for(auto &x : v)
        {
            distinct.insert(x);
        }
        return distinct.size();
    }
    
    size_t count_distinct(const std::list<int>& l) {
        if (l.empty()) return 0;
    
        size_t distinct = l.size();
        auto prev = l.begin();
    
        for (auto cur = std::next(prev); cur != l.end(); ++cur, ++prev) {
            if (*cur == *prev)
                --distinct;
        }
    
        return distinct;
    }
    
    然后简单地使用它

    size_t distinct = unique_cnt(l.begin(), l.end());         
    

    还有一种
    std::unique\u copy
    +自定义迭代器方法,但它看起来不够优雅。

    对于排序数据,您可能不会比尝试实现的直接方法更高效

    我更喜欢有一些东西沿着这条线,因为我发现向上计数而不是向下计数更直观:

    std::size_t count_unique_sorted(std::list<int> const& l) {
        if (l.empty()) return 0;
        std::size_t count = 1;
        auto previous_value = l.front();
        // TODO: hope that the compiler fixes that redundant first comparison...
        for (auto next_value : l) {
            if (next_value != previous_value) {
                // the value changed! increment count and update previous_value
                ++count;
                previous_value = next_value;
            }
        }
        return count;
    }
    
    请注意,在这两种情况下,您都希望将列表作为常量引用而不是副本传递到函数中

    如果您觉得这仍然很慢,请随意探索并行化的乐趣。这可能取决于数据量和分布。因此,您应该在那时开始进行一些系统分析


    <> P>除非你需要重新排序这些值,首先要考虑将数据转储到<代码> STD::vector < /COD>第一。有随机访问迭代器简化了事情并且有更好的局部性也可以加速事情…

    <代码> K++< /代码>?你确定吗?<代码>(const Auto Num:v)
    迭代列表。然后使用
    std::map
    作为结果,并在
    num
    索引处计算
    int
    。输入列表是否已排序?@JesperJuhl如果我们只想计算不同的数字,则使用
    set
    即可。如果列表未排序,则我认为
    std::set
    是最佳方法。如果是,则也许手工计算元素是最好的。@Galik Opps是的,我只是盲目复制了OP的片段。@DAle如果你有什么想法,你可以提供一个。你应该添加一个注释,说明输入需要排序,并且不能在常量列表上工作。结果应该是
    大小\u t
    ,而不是
    int
    你应该添加
    std::Is_排序
    至答案,如果未排序,请使用
    std::sort
    使此答案正确