【问题标题】:sorting large vectors using user defined function in c/c++使用 c/c++ 中的用户定义函数对大向量进行排序
【发布时间】:2015-02-27 01:56:14
【问题描述】:

我编写了以下代码,用于根据我的排序标准对两个向量进行排序:

typedef pair<unsigned, pair<vector<unsigned>, vector<unsigned> > > Elem;
bool bucketComparator(const Elem& a, const Elem& b) {
    //find the min and max of "a" and "b"
    // return true if a should go before b in the sort
    unsigned minA,maxA;
    unsigned minB,maxB;
    if((a.second.first).size()<=1){
        minA=maxA=*((a.second.first).begin());
    } else{
        minA=*std::min_element((a.second.first).begin(),(a.second.first).end());
        maxA=*std::max_element((a.second.first).begin(),(a.second.first).end());
    }
    if((b.second.first).size()<=1){
        minB=maxB=*((b.second.first).begin());
    } else{
        minB=*std::min_element((b.second.first).begin(),(b.second.first).end());
        maxB=*std::max_element((b.second.first).begin(),(b.second.first).end());
    }
    if((minA<=minB)&&(maxA<=maxB)){
        return true;
    } else{
        return false;
    }
}
main()
{
   vector<Elem> A;
   //initializing vector A with values
   std::sort(A.begin(), A.end(), bucketComparator);
   //further computation using vector A
}

错误:大数据的分段错误。

当向量 A 的大小为 223080 或更大时,我发现出现分段错误。但是当向量 A 的大小小于 100 时,代码运行良好。我无法理解其原因,因为我在 64GB RAM 上运行代码。有人可以帮我解决这个问题吗?

此外,当我在 linux 上运行 top 命令时,我发现程序在停止之前甚至没有消耗 0.1%(64GB)的可用 RAM,因为分段错误。

我什至尝试通过首先使用 std::sort 和冒泡排序对向量进行排序来找到最大值和最小值——但我仍然遇到同样的错误。

我正在运行以下版本的 gcc:gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3

有什么方法可以让我编写我的程序,以便它根据我在:bucketComparator 中使用的排序标准对大向量进行排序。我对 c 和 c++ 都很好。

此外,当我执行简单的 std::sort: 时,代码不会给出分段错误:

std::sort(A.begin(), A.end());

【问题讨论】:

  • 您将应用程序编译为什么? 64位还是32位?如果您只能访问 2-4GB 的 RAM,那么 RAM 的数量将无济于事。
  • (a.second.first).size()(或 b)是否有可能为 0,所以您在我认为不好的情况下取消引用空向量上的 begin()
  • 您没有提供严格的弱排序。如果minA = minBmaxA = maxB,则bucketComparator( a, b )bucketComparator( b, a ) 都返回true,这是不允许的。请参阅here 了解更多信息。
  • @StegVerner 将minA &lt;= minB ... 更改为minA &lt; minB ...,或者可能保留minA&lt;=minB,但将第二部分更改为maxA&lt;maxB。只要确保它遵循我上面提供的链接中描述的规则。
  • @StegVerner 你是什么意思?你正在对它们进行分类,一个必须在另一个之前。如果对于两个值abf(a,b)f(b,a) 都返回false,则它们被认为是等效的,并且它们之间的顺序不能保证。如果您希望它们与原来的顺序相同,可以使用std::stable_sort

标签: c++ c


【解决方案1】:

std::sort 的文档描述了比较器属性:

二进制函数,接受范围内的两个元素作为参数,并返回一个可转换为 bool 的值。返回的值指示作为第一个参数传递的元素是否被认为在其定义的特定严格弱排序中位于第二个之前。

该函数不得修改其任何参数。

这可以是函数指针或函数对象。

严格的弱排序由以下特征 (source) 定义:

Irreflexivity                   f(x, x) must be false.
Antisymmetry                    f(x, y) implies !f(y, x)
Transitivity                    f(x, y) and f(y, z) imply f(x, z).
Transitivity of equivalence     Equivalence (as defined above) is transitive: if x is equivalent to y and y is equivalent to z, then x is equivalent to z.

如果f(x,y)f(y,x) 都为假,则两个元素xy 被认为是等效的。

你定义的函数不遵循这些规则,特别是它违反了非自反性和反对称;当minA == minB &amp;&amp; maxA == maxBbucketComparator(a,b)bucketComparator(b,a) 都产生true 值时。由于函子无效,因此会导致未定义的行为。

您需要更新您的函子以提供严格的弱排序。一种解决方案可能是更改语句:

if((minA<=minB)&&(maxA<=maxB))

if( minA <= minB && maxA < maxB )

【讨论】:

    【解决方案2】:

    我唯一能看到可能错的是你取消引用std::min_elementstd::max_element返回的内容,而不检查它们返回的内容是否是&lt;vector&gt;.end(),这是可能的。当某个地方的指针在不应该被取消引用时被取消引用时,几乎总是会发生 Seg 错误。

    例如,如果向量为空,std::min_elementstd::max_element 将返回 &lt;vector&gt;.end(),您正在取消引用。

    【讨论】:

      【解决方案3】:

      如果向量 a.second.firstb.second.first 为空,则程序将在取消引用从 begin() 调用中获取的迭代器时崩溃。

      bool bucketComparator(const Elem& a, const Elem& b) {
          //find the min and max of "a" and "b"
          // return true if a should go before b in the sort
          unsigned minA,maxA;
          unsigned minB,maxB;
      
          const vector<unsigned> &vecA = a.second.first;
          const vector<unsigned> &vecB = b.second.first;
      
          //check if vectors empty
          if (vecA.empty()){
              return true;
          }
          if (vecB.empty()){
              return false;
          }
      
          if((vecA).size()==1){
              minA=maxA=*((vecA).begin());
          } else{
              minA=*std::min_element((vecA).begin(),(vecA).end());
              maxA=*std::max_element((vecA).begin(),(vecA).end());
          }
          if((vecB).size()==1){
              minB=maxB=*((vecB).begin());
          } else{
              minB=*std::min_element((vecB).begin(),(vecB).end());
              maxB=*std::max_element((vecB).begin(),(vecB).end());
          }
          if((minA<=minB)&&(maxA<=maxB)){
              return true;
          } else{
              return false;
          }
      }
      

      我还建议使用本地 const 引用变量来提高代码的可读性和性能。

      【讨论】:

      • 如果两者都为空,这将返回 true,因此不提供严格的弱排序
      猜你喜欢
      • 2011-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多