How to keep only duplicates efficiently?

后端 未结 10 751
闹比i
闹比i 2021-01-04 06:14

Given an STL vector, output only the duplicates in sorted order, e.g.,

INPUT : { 4, 4, 1, 2, 3, 2, 3 }
OUTPUT: { 2, 3, 4 }

The algorithm is

10条回答
  •  甜味超标
    2021-01-04 06:58

    This is in the style of the standard library. Credit for algorithm goes to James! (If you +1 me, you better +1 him, or else). All I did was make it standard library style:

    #include 
    #include 
    #include 
    #include 
    #include 
    
    // other stuff (not for you)
    template 
    void print(const char* pMsg, const T& pContainer)
    {
        std::cout << pMsg << "\n    ";
        std::copy(pContainer.begin(), pContainer.end(),
            std::ostream_iterator(std::cout, " "));
        std::cout << std::endl;
    }
    
    template 
    T* endof(T (&pArray)[N])
    {
        return &pArray[0] + N;
    }
    
    // not_unique functions (for you)
    template 
    ForwardIterator not_unique(ForwardIterator pFirst, ForwardIterator pLast,
                               BinaryPredicate pPred)
    {
        // correctly handle case where an empty range was given:
        if (pFirst == pLast) 
        { 
            return pLast; 
        }
    
        ForwardIterator result = pFirst;
        ForwardIterator previous = pFirst;
    
        for (++pFirst; pFirst != pLast; ++pFirst, ++previous)
        {
            // if equal to previous
            if (pPred(*pFirst, *previous))
            {
                if (previous == result)
                {
                    // if we just bumped bump again
                    ++result;
                }
                else if (!pPred(*previous, *result))
                {
                    // if it needs to be copied, copy it
                    *result = *previous;
    
                    // bump
                    ++result;
                }
            }
        }
    
        return result;
    }
    
    template 
    ForwardIterator not_unique(ForwardIterator pFirst, ForwardIterator pLast)
    {
        return not_unique(pFirst, pLast,
                    std::equal_to());
    }
    
    
    //test
    int main()
    {
        typedef std::vector vec;
    
        int data[] = {1, 4, 7, 7, 2, 2, 2, 3, 9, 9, 5, 4, 2, 8};
        vec v(data, endof(data));
    
        // precondition
        std::sort(v.begin(), v.end());
        print("before", v);
    
        // duplicatify (it's a word now)
        vec::iterator iter = not_unique(v.begin(), v.end());
        print("after", v);
    
        // remove extra
        v.erase(iter, v.end());
        print("erased", v);
    }
    

提交回复
热议问题