使用索引向量重新排序向量[重复]

2023-12-04

我想对向量中的项目重新排序,使用另一个向量来指定顺序:

char   A[]     = { 'a', 'b', 'c' };
size_t ORDER[] = { 1, 0, 2 };

vector<char>   vA(A, A + sizeof(A) / sizeof(*A));
vector<size_t> vOrder(ORDER, ORDER + sizeof(ORDER) / sizeof(*ORDER));

reorder_naive(vA, vOrder);
// A is now { 'b', 'a', 'c' }

以下是一个低效的实现,需要复制向量:

void reorder_naive(vector<char>& vA, const vector<size_t>& vOrder)  
{   
    assert(vA.size() == vOrder.size());  
    vector vCopy = vA; // Can we avoid this?  
    for(int i = 0; i < vOrder.size(); ++i)  
        vA[i] = vCopy[ vOrder[i] ];  
}  

是否有更有效的方法,例如使用 swap()?


该算法基于 chmike 的算法,但重新排序索引的向量为const。这个功能和他的11个都一致! [0..10] 的排列。复杂度为 O(N^2),以 N 为输入的大小,或者更准确地说,最大的大小orbit.

请参阅下文,了解修改输入的优化 O(N) 解决方案。

template< class T >
void reorder(vector<T> &v, vector<size_t> const &order )  {   
    for ( int s = 1, d; s < order.size(); ++ s ) {
        for ( d = order[s]; d < s; d = order[d] ) ;
        if ( d == s ) while ( d = order[d], d != s ) swap( v[s], v[d] );
    }
}

这是我投入更多精力的 STL 风格版本。它大约快了 47%(也就是说,几乎是 [0..10] 的两倍!),因为它尽早完成所有交换,然后返回。重新排序向量由多个轨道组成,每个轨道在到达其第一个成员时都会重新排序。当最后几个元素不包含轨道时,速度会更快。

template< typename order_iterator, typename value_iterator >
void reorder( order_iterator order_begin, order_iterator order_end, value_iterator v )  {   
    typedef typename std::iterator_traits< value_iterator >::value_type value_t;
    typedef typename std::iterator_traits< order_iterator >::value_type index_t;
    typedef typename std::iterator_traits< order_iterator >::difference_type diff_t;
    
    diff_t remaining = order_end - 1 - order_begin;
    for ( index_t s = index_t(), d; remaining > 0; ++ s ) {
        for ( d = order_begin[s]; d > s; d = order_begin[d] ) ;
        if ( d == s ) {
            -- remaining;
            value_t temp = v[s];
            while ( d = order_begin[d], d != s ) {
                swap( temp, v[d] );
                -- remaining;
            }
            v[s] = temp;
        }
    }
}

最后,为了一劳永逸地回答这个问题,一个变体确实破坏了重新排序向量(用-1填充它)。对于 [0..10] 的排列,它比之前的版本快约 16%。因为覆盖输入可以实现动态编程,所以它是 O(N),对于某些序列较长的情况渐近更快。

template< typename order_iterator, typename value_iterator >
void reorder_destructive( order_iterator order_begin, order_iterator order_end, value_iterator v )  {
    typedef typename std::iterator_traits< value_iterator >::value_type value_t;
    typedef typename std::iterator_traits< order_iterator >::value_type index_t;
    typedef typename std::iterator_traits< order_iterator >::difference_type diff_t;
    
    diff_t remaining = order_end - 1 - order_begin;
    for ( index_t s = index_t(); remaining > 0; ++ s ) {
        index_t d = order_begin[s];
        if ( d == (diff_t) -1 ) continue;
        -- remaining;
        value_t temp = v[s];
        for ( index_t d2; d != s; d = d2 ) {
            swap( temp, v[d] );
            swap( order_begin[d], d2 = (diff_t) -1 );
            -- remaining;
        }
        v[s] = temp;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用索引向量重新排序向量[重复] 的相关文章

随机推荐

  • 我需要帮助创建实例变量和构造函数[关闭]

    很难说出这里问的是什么 这个问题模棱两可 含糊不清 不完整 过于宽泛或言辞激烈 无法以目前的形式合理回答 如需帮助澄清此问题以便重新打开 访问帮助中心 抱歉 我知道这个答案很明显 但我想我只是太慢了 谁能给我实例变量和构造函数的明确定义 实
  • 如何使 WPF ListView 项目水平重复,就像水平滚动条一样?

    我有一个 WPF ListView 它垂直重复数据 我不知道如何让它水平重复 就像 Windows 资源管理器中的幻灯片视图一样 我当前的 ListView 定义是
  • Jaspersoft Studio 在更改报告的数据适配器时添加 uuid

    我目前正在从报表4 5 1 to 贾斯珀软件工作室 5 5 我注意到当我更改数据适配器时贾斯帕软件工作室它添加了uuid标记到报告的 XML 我与不同的数据库有不同的连接 但我讨厌必须进入 Notepad 来删除uuid 从 XML 中 当
  • 在android imageview中使用glide显示google驱动器图像

    我的驱动器网址是 https drive google com file d 0B3DFHb2 MdGYa2NMUkVtVkZ1V1k view usp sharing 我想使用 glide 在 android imageview 中显示它
  • iOS 和 Xcode:在 UITableView 中设置委托和数据源时出现不兼容类型错误

    我正在尝试以编程方式制作一个应用程序 其中包含一个 UITableView 它根据应用程序的文档目录中的文件创建项目列表 我已经能够将文件读入数组 filepathsArray 但是当我尝试使用数组填充表格时 编译崩溃并且 Xcode 抛出
  • BitmapFactory.decodeStream 无法从 ftp 解码 png 类型

    我的错误是什么 如何显示来自 FTP 的 png 我是 android 新手 尝试显示来自不同连接 源的图像 然后我已经显示了从可绘制和 HTTP 加载的图像 现在 我尝试从 FTP 显示 当我使用时 我收到消息 解码器 gt 解码返回 f
  • MySQL 理解基本连接

    我正在努力理解基本的 MySQL 连接 基本上我有 2 个表 其中一个包含客户的名字和地址 ID 另一个包含实际地址 我希望它不只是显示客户名称和地址 ID 而是显示客户名称和实际地址 我的基本选择语句是这样的 SELECT firstNa
  • 使用 Retrofit 获得通用 URL 的任何方法

    我有几个接受相同 GET 参数的 URL 主要用于分页目的 如下所示 public interface AsynchronousApi GET api users public void listUsers Query limit Inte
  • 从jquery处理android中的后退按钮

    我们用 jQuery 开发了一个与 android 集成的应用程序 只有一个 Activity 从这个活动中 我们加载一个 HTML 文件 在这个文件上我们显示和隐藏 div 内容 查看此处提供的网页并按 android 中提供的后退按钮时
  • 在 FullCalendar 中显示周数

    我正在寻找一种在议程周视图上显示周数的方法 我试过了这个方法但没有结果 实际上 我需要像这样将数字放在日历标题中 titleFormat month Calendar br MMMM yyyy week Calendar br Week W
  • log_softmax() 如何实现以更快的速度和数值稳定性计算其值(和梯度)?

    MXNet 和 PyTorch 都提供了计算 log 的特殊实现 softmax 速度更快 数值更稳定 但是 我在这两个包中都找不到该函数 log softmax 的实际 Python 实现 谁能解释一下这是如何实现的 或者更好的是 给我指
  • 快速行插入 UITableView 会导致 NSInternalInconsistencyException

    我有一个 UITableView 有时会快速插入新行 新行的插入由通知观察者处理 该通知观察者监听每当基础数据发生更改时触发的更新通知 我在所有数据模型更改和实际通知发布本身周围使用 synchronized 块 希望每个增量数据更改 和行
  • 遍历已填充的行

    因此 我尝试使用 VBA 迭代 Excel 电子表格中的工作表 我想遍历每一行 然后遍历每一列 尽管进行了谷歌搜索 但我实际上无法找到一种直观的方法来做到这一点 我假设必须填充一行的第一个单元格 如果没有 那么那一定是结束 我可以强制执行这
  • 为什么我们必须在 C# 中同时定义 == 和 !=?

    C 编译器要求每当自定义类型定义运算符时 它还必须定义 see here Why 我很好奇为什么设计者认为有必要 以及为什么编译器不能在只有另一个运算符存在时默认为其中一个运算符提供合理的实现 例如 Lua 允许您仅定义相等运算符 而您可以
  • Javascript 正则表达式和边界

    一位同事问我一个正则表达式问题 我似乎无法找到并回答他 我们使用边界在文本编辑器中突出显示特定长度的文本 但这里有一些示例代码显示了该问题 问题是 第一个文字 str replace 有效
  • 如何在反应中显示表格中的对象数组

    最近在学习react 我将状态设置为对象数组 我想在页面上的表格中显示该数组 每个对象在一行上 我一直在研究地图 但是我在理解它时遇到了一些困难 我能够在代码中的不同位置很好地使用映射来映射array 但我在通过映射时遇到问题对象数组 此代
  • 如何使用 Google Visualization Query 搜索电子表格

    我有这个简单的网页它使用 google visualization Query 从中提取三个特定单元格的值电子表格 然后根据三个相应输入字段的唯一 id 属性设置其值 google load visualization 1 packages
  • 从子路由渲染的 Jade 模板链接到静态文件

    我在使用 Node js Express Jade 时遇到了一个非常基本的问题 该问题非常难以描述 在我的 node js 应用程序中 我使用 Express 框架来路由 HTTP 请求 我还使用 Jade 模板作为视图 它们本身链接到我通
  • 如何从数据库表中为用户添加地理位置标记?

    我想对每个用户进行地理定位 我在用户表中添加两个字段纬度和经度 这是我的地图页面map html
  • 使用索引向量重新排序向量[重复]

    这个问题在这里已经有答案了 我想对向量中的项目重新排序 使用另一个向量来指定顺序 char A a b c size t ORDER 1 0 2 vector