将STL列表容器划分为大于value的元素和低于value的元素

时间:2014-01-25 03:34:12

标签: c++ stl

我正在创建一个函数,作为参数接收列表和值K函数应该将列表分成两部分第一部分,在同一列表中不使用另一个容器包含低于值K,第二部分包含大于或等于K的元素,这是我的尝试:

template <class T> 
void dividie_list(list<T> & mylist, T k){
    list<int>::iterator it;

    it = mylist.begin();
    while(it != mylist.end()){
        if(*it >= k){
            mylist.push_back(*it);
            it = mylist.erase(it);
        }
        else
            ++it;
    }   
}

输入输出示例:

Input : mylist={1,3,4,14,11,9,7,16,25,19,7,8,9 } y k=8  
Output: {1, 3, 4, 7, 7,9, 11, 16, 25, 19, 14, 8, 9}  

似乎这个功能陷入了无限循环而且没有结束,我无法弄明白,期末考试是亲密的,感谢帮助。

编辑:我根据建议的解决方案尝试了其他方法,但我无法确定它是否有效,有人可以确认一下:

template <class T>
 void dividie_list(list<T> & mylist, T k)
{
    typename list<T>::iterator first = mylist.begin();
    typename list<T>::iterator last = mylist.end();

    --last;

    while(first != last){
    if(*first >= k){
        swap(*first,*last);
        --last;
    }
    else
        ++first;
    }
}

2 个答案:

答案 0 :(得分:1)

如果您想要实现该方法而不是调用函数来完成工作,那么根据代码on this page,这就是您想要的。

#include <list>
#include <algorithm>
#include <iostream>

using namespace std;

template <class T>
void dividie_list(list<T> & mylist, T k)
{
    typename list<T>::iterator first = mylist.begin();
    typename list<T>::iterator last = mylist.end();

    while (first!=last) 
    {
        while (*first < k)
        {
            ++first;
            if (first==last) return;
        }
        do
        {
            --last;
            if (first==last) return;
        } while (!(*last < k));

        swap (*first,*last);
        ++first;
    }

    return ;
}

测试以上功能的驱动程序:

int main()
{
    int a[] = {1,3,4,14,11,9,7,16,25,19,7,8,9 };
    list<int> l(a, a + sizeof(a) / sizeof(int) );

    copy(l.begin(), l.end(), ostream_iterator<int>(cout, ", ") );
    cout<<'\n';
    dividie_list(l, 8);
    copy(l.begin(), l.end(), ostream_iterator<int>(cout, ", ") );
}

输出如下:

1, 3, 4, 14, 11, 9, 7, 16, 25, 19, 7, 8, 9,
1, 3, 4, 8, 7, 7, 9, 16, 25, 19, 11, 14, 9,

您需要返回迭代器而不是void,以便您可以知道第一部分和第二部分之间的边界。

答案 1 :(得分:1)

无需在任何地方推送或弹出物品。只需按需要枚举列表和交换元素即可。

#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
#include <list>

// iterator based parition implementation.
template<typename Iter>
Iter divide_list(Iter begin, Iter end,
     const typename std::iterator_traits<Iter>::value_type& val)
{
    Iter p = begin;
    for (Iter it = begin; it != end; ++it)
    {
        if (*it < val)
        {
            if (it != p)
            {
                std::cout << "Swapping " << *it << " and " << *p << '\n';
                std::iter_swap(it, p);
            }
            ++p;
        }
    }
    return p;
}

// generic container wrapper
template<template<typename, typename...> class V, typename T, typename... Args>
void divide_list(V<T,Args...>& seq, const T& arg)
{
    divide_list(std::begin(seq), std::end(seq), arg);
}

int main()
{
    std::list<int> lst { {1,3,4,14,11,9,7,16,25,19,7,8,9 } };

    for (auto x : lst)
        std::cout << x << ' ';
    std::cout << std::endl;

    divide_list(lst, 8);

    for (auto x : lst)
        std::cout << x << ' ';
    std::cout << '\n' << std::endl;

    // also works with vector (and deque)
    std::vector<int> vec { {6,4,9,14,11,2,7,9,25,16,7,8,3 } };

    for (auto x : vec)
        std::cout << x << ' ';
    std::cout << std::endl;

    divide_list(vec, 8);

    for (auto x : vec)
        std::cout << x << ' ';
    std::cout << std::endl;

    return 0;
}

<强>输出

1 3 4 14 11 9 7 16 25 19 7 8 9 
Swapping 7 and 14
Swapping 7 and 11
1 3 4 7 7 9 14 16 25 19 11 8 9 

6 4 9 14 11 2 7 9 25 16 7 8 3 
Swapping 2 and 9
Swapping 7 and 14
Swapping 7 and 11
Swapping 3 and 9
6 4 2 7 7 3 14 9 25 16 11 8 9 

作为奖励,我修改了迭代器算法以返回迭代器位置p作为函数结果,从而知道结果序列中的第一个元素大于或等于测试值(可能派上用场吧。这允许您具有低序列(lst.begin(), p)和高序列(p, lst.end())的开始/结束。通用容器支持完全是因为我很无聊。