对定义为向量<double>的矩阵进行排序

时间:2016-11-03 09:31:04

标签: c++ sorting stl qsort

假设我有一个大小为A的方形矩阵n,定义为std::vector<double>

std::vector<double> A(n*n);

矩阵的元素以通常的方式访问:

double a_ij = A[i*n + j];

我需要按照相对于第一列的升序对矩阵的行进行排序。

qsort函数允许我使用数组和函数指针来完成它,但我想找到一种方法来实现这一点,使用向量和std::sort

另外,请注意,出于性能原因,我不希望将矩阵定义为向量矢量。

修改

我传递给qsort的函数:

static int comparisonFunction(const void* firstRow, const void* secondRow) 
{
    if (((double *)firstRow)[0] < ((double *)secondRow)[0]) return -1;
    else if (((double *)secondRow)[0] < ((double *)firstRow)[0]) return 1;
    return 0;
}

电话:

std::qsort(matrixArray, nbRows, sizeof(double)*nbRows, comparisonFunction);

3 个答案:

答案 0 :(得分:3)

CREATE PROCEDURE createviewupdatepenaltypointsconsecutive AS BEGIN DECLARE @STMT AS NVARCHAR(MAX) = ' ALTER VIEW consecutive AS WITH cte as ( SELECT *, LAG([pointsRewarded], 1) OVER (PARTITION BY [EmployeeID] ORDER BY [WeekNumber]) as prev1_points, LAG([pointsRewarded], 2) OVER (PARTITION BY [EmployeeID] ORDER BY [WeekNumber]) as prev2_points, LAG([pointsRewarded], 3) OVER (PARTITION BY [EmployeeID] ORDER BY [WeekNumber]) as prev3_points FROM week1 ) SELECT *, CASE WHEN [pointsRewarded] = -10 AND prev1_points = -10 AND prev2_points = -10 AND prev3_points = -10 THEN -200 WHEN [pointsRewarded] = -10 AND prev1_points = -10 AND prev2_points = -10 THEN -100 WHEN [pointsRewarded] = -10 AND prev1_points = -10 THEN -50 ELSE 0 END penalty FROM cte ' EXEC sp_executesql @STMT; END 适用于迭代器,并不关心迭代器实现。因此,如果您定义std::sort包裹struct RowIter,成员std::vector<double>& matrixsize_t RowSize(以及operator+(size_t)operator-等)一个operator++,然后Row operator*() const可以按该迭代器排序。

遗憾的是,工作比std::sort还要多,但它会推广到非POD类型。

答案 1 :(得分:2)

可以用$insert_oc_desc = "INSERT INTO oc_product_description (product_id, language_id, name, description, tag, meta_title, meta_description, meta_keyword) VALUES (SELECT product_id FROM oc_product WHERE product_id NOT IN (SELECT product_id FROM oc_product_description), 2, '" . $model . "', '&lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-size: 14px; line-height: 20px; text-align: justify;&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;/p&gt;&lt;div&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-size: 14px; line-height: 20px; text-align: justify;&quot;&gt;&lt;br&gt;&lt;/span&gt;&lt;/div&gt;', '" . $model . "," . $man_name . "', '" . $model . " ,Pret " . $updated_price . " lei', '', '" . $model . "," . $man_name . "')"; 替换require_once("dompdf/autoload.inc.php"); //require('WriteHTML.php'); $html = '<body> <div id="watermark"><img src="/var/htdocs/PDF/header.png" height="100%" width="100%"></div> <div id="header"> <h3 style="padding-top:10px;">'.$_POST['name'].'</h3> </div> <div id="footer"> <h3 style="padding-top:8px; padding-right:25px;" class="CIJ">ABSOLUTE MARKET INSIGHTS</h3> </div> <div> <br><br><div class="ooo" style="padding-top: 20px;">'.$_POST['comment'].'</div> </div> </body>'; use Dompdf\Dompdf; $dompdf = new Dompdf(); $canvas = $dompdf->get_canvas(); $dompdf->load_html($html); $dompdf->render(); $dompdf->stream($_POST["name"], array("Attachment" => false)); 来对基础数组进行排序,但您必须定义:

  • 直接访问向量的底层存储的行类型 - 此处不能使用向量,因为即使数组或数组仍然是数组,向量向量也不是方形大小的向量。更糟糕的是,我知道没有可移植的方法将现有存储分配给矢量。该Row类型必须是可移动构造和可移动分配的,并且正确支持交换。
  • 该Row类型的RandomAccessIterator,能够正确处理基础数组的结尾。

由您来做,但标准C ++的所有版本都明确支持C库,因此在此用例中使用qsort没有任何害处,因为它更简单,最终不容易出错。 std::sort方式只需要7行,这很容易控制和同行评审。 漂亮的 C ++方式将需要至少2个具有非平凡构造函数的类,因此更多行和更多错误的可能性。

如果你真的不能使用qsort,也许是内部编码规则,那么我只需将数据复制到矢量矢量,对其进行排序并将数据复制回初始矢量。它涉及2个额外的矩阵完整副本,但至少使用标准类,并且需要的编码要少得多。

答案 2 :(得分:0)

最简单的解决方案是保留qsort()并使用std::vector::data(),它返回指向第一个元素的指针,从而允许您使用与{C}相同的std::vector阵列:

std::qsort(matrixArray.data(), nbRows, sizeof(double)*nbRows, comparisonFunction);

正确使用std::sort()是可能的,但是很冗长,因为您不仅需要一个随机访问迭代器类来按行迭代,而且还需要一个抽象行的类,以便std::sort()可以交换它们

解决这个问题,但仍然使用std::sort的方法是将要排序的元素与索引一起提取到自己的std::vector中。然后对该向量进行排序,最后通过该向量中的索引对原始矩阵中的行重新排序。

#include <vector>
#include <tuple>
#include <algorithm>

const int n = 10;

std::vector<double>
row_sort(std::vector<double> const& A)
{
  std::vector<std::tuple<int, double> > first_element(n);
  for(int i = 0; i < n; ++i)
  {
    first_element[i] = std::make_tuple(i, A[i*n]);
  }

  std::sort(std::begin(first_element), std::end(first_element),
            [](std::tuple<int, double> const& lhs,
               std::tuple<int, double> const& rhs)
            {
              return std::get<1>(lhs) < std::get<1>(rhs);
            });

  std::vector<double> result(n*n);
  for(int i = 0; i < n; ++i)
  {
    std::copy_n(&A[std::get<0>(first_element[i])*n], n, &result[i*n]);
  }

  return result;
}