简体   繁体   English

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

[英]Dividing an STL list container to elements greater than value and elements lower than value

I'm making a function that recieves as parameter a list and a value K the function should divide the list to two parts the first part, in the same list without using another container contains the elements that are lower than the value K, the second part contains elements that are greater or equal to K, here's my attempt: 我正在制作一个函数,该函数将一个列表和一个值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 output example: 输入输出示例:

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}  

It seems that the function gets stuck in an infinite loop and doesn't end, I can't figure that out, final exams are close guys, help is appreciated. 似乎该函数陷入无限循环并且没有结束,我无法弄清楚,期末考试很亲密,热心帮助。

Edit: i tried something else based on a suggested solution but i can't tell for sure if it's valid, can someone confirm it : 编辑:我根据建议的解决方案尝试了其他方法,但我不能确定它是否有效,有人可以确认它:

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;
    }
}

If you want the implementation of the method instead of calling a function to do the job, here is what you want, based on the code 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 ;
}

Driver program to test above function: 驱动程序测试以上功能:

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, ", ") );
}

the output is as below: 输出如下:

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,

You need to return an iterator instead of void so that you can know where is the boundary between the first part and second. 您需要返回一个迭代器而不是void以便您可以知道第一部分和第二部分之间的边界在哪里。

There is no need to push or pop items anywhere. 无需在任何地方推送或弹出项目。 Enumerating the list and swapping elements as needed is all that is required. 仅需要枚举列表和交换元素。

#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;
}

Output 产量

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 

As a bonus, I modified the iterator algorithm to return the iterator position p as the function result, thereby knowing the first element in the resulting sequence that is greater-than or equal-to the test value (may come in handy). 另外,我修改了迭代器算法以将迭代器位置p作为函数结果返回,从而知道结果序列中的第一个元素大于或等于测试值(可能派上用场)。 This allow you to have a start/end of the low-sequence ( lst.begin(), p ) and for the high sequence ( p, lst.end() ). 这使您可以具有低序的开始/结束( lst.begin(), p )和高序的开始/结束( p, lst.end() )。 The generic container support was solely because I was bored. 通用容器的支持仅仅是因为我很无聊。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM