【问题标题】:How to realize sequent addition of elements to vector, sorting them before to insert?如何实现对向量的元素顺序添加,在插入之前对其进行排序?
【发布时间】:2020-01-30 15:56:44
【问题描述】:

我尝试编写将元素插入向量的程序,并按字母顺序对它们进行排序。之前要插入的元素与另一个元素进行比较,直到它超过已插入的元素。在假定使用.insert() 添加比较元素之后。我想在不使用排序算法的情况下实现它。

std::string name;
std::vector<std::string> students;
std::vector<std::string>::iterator beg = students.begin();
  while (std::cin>>name){
        for (std::vector<std::string>::iterator e = students.end() ; beg !=e ; ) {
            if (!name.compare(*beg))
            {
                students.insert(beg, name);
                break;
            }
            else
                beg++;      
         }
    }

为了避免指向最后一个元素的迭代器失效,我每次迭代都会更新它。 问题是在这部分代码之后我检查了向量但它是空的。

【问题讨论】:

  • 尽管您声称,显示的代码显然不会“在每次迭代中更新它”。所示代码的哪一部分在每次迭代时正确重置了beg 迭代器?未定义的行为。
  • 真的,我改一下
  • 另外,compare() 不是一个布尔函数,并且不会按照您认为的方式工作。你的比较是错误的。
  • 措辞上的挑剔:根据定义,不使用算法就无法排序。任何让你对向量进行排序的代码都是算法的实现。我猜你的意思是&lt;algorithm&gt; 没有标准算法。但为什么?另请注意,在每个 insert 之后进行排序不是很有效。最好接受所有输入,然后排序
  • @Konstantin 您将其标记为algorithm,所以这里是——您应该使用std::lower_bound 或std::upper_bound。 vector 已经排序,因此通过二进制搜索项目应该去的地方更有效地将项目插入排序向量中,而不是从头开始并比较每个元素。

标签: c++ string algorithm vector stl


【解决方案1】:

这个比较

if (!name.compare(*beg))

没有意义。它只检查两个字符串是否相等。

例如下面的代码 sn-p

std::string s1 = "one";
std::string s2 = "one";
std::cout << !s1.compare( s2 ) << '\n';

它的输出是1。表示两个对象相等。

此外,for 循环可以在没有找到可以插入字符串的位置的情况下结束,例如当向量最初为空时。

还有这句话

std::vector<std::string>::iterator beg = students.begin();

必须在外部 while 循环内。即迭代器在循环的每次迭代中都要重新初始化。

这是一个演示程序,展示了如何实现内部循环。

#include <iostream>
#include <string>
#include <vector>
#include <iterator>

void insert( std::vector<std::string> &v, const std::string &s )
{
    auto it = std::begin( v );

    while (  it != std::end( v ) && not( s < *it ) ) ++it;

    v.insert( it, s );
}

int main() 
{
    std::string names[] = { "One", "Two", "Three" };
    std::vector<std::string> v;

    for ( const auto &s : names )
    {
        insert( v, s );
    }


    for ( const auto &s : v ) std::cout << s << ' ';
    std::cout << '\n';

    return 0;
}

程序输出是

One Three Two

即字符串是按升序插入的。

相对于你的代码 sn-p 循环看起来像

while ( std::cin >> name )
{
    auto it = std::begin( students ); // or students.begin()

    while (  it != std::end( students ) && not( name < *it ) ) ++it;

    students.insert( it, name );
}

您也可以使用标准算法std::find_if 来代替内部while 循环。例如

#include <iostream>
#include <string>
#include <functional>
#include <vector>
#include <iterator>
#include <algorithm>

//...

while ( std::cin >> name )
{
    using namespace std::placeholders;
    auto it = std::find_if( std::begin( students ), std::end( students ), 
                            std::bind( std::greater_equal<>(), _1, name ) );

    students.insert( it, name );
}

【讨论】:

  • 那真的是完整的答案)但是如果我们每次迭代都“结束”迭代器,我们如何在这部分代码void insert( std::vector&lt;std::string&gt; &amp;v, const std::string &amp;s ) { auto it = std::begin( v ); while ( it != std::end( v ) &amp;&amp; not( s &lt; *it ) ) ++it; v.insert( it, s ); } 中使用std::end( v )?我一定是什么都不懂
  • @Konstantin 从 C++ 11 开始,在标头 中声明了通用函数 std::begin 和 std::end ,允许将它们应用于任何标准容器或数组。跨度>
  • 我的意思是在insert() 之后end 迭代器发生了变化,不是吗?但在下一次迭代中,您使用了相同的 end
  • @Konstantin 因为它是一个函数,所以使用该函数重新计算结束迭代器。
【解决方案2】:

对于一个空向量 begin 和 end 是相同的,因此你永远不会插入任何东西。

不清楚你为什么不想使用排序算法,因此我会提出以下建议:

std::string name;
std::vector<std::string> students;
while (std::cin>>name){
    students.push_back(name);
}
std::sort(students.begin(),students.end());

或者,将最后一行替换为您最喜欢的排序例程。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-07
    • 1970-01-01
    • 2019-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-08
    相关资源
    最近更新 更多