估计阅读时长: 6 分钟

之前在阅读一个使用rust语言编写的contour tracing算法模块的源代码的时候,其中有一个向量的左旋以及右旋的操作。这个操作的具体的含义是和在算法中的轮廓边缘像素的读取方向有关:因为访问方向是一个二维平面的概念,但是在代码中我们只能够使用一个一维的数组的来存储这个二维的信息。所以在这段rust代码之中,作者很巧妙的使用了向量的左旋以及右旋操作来实现一维数组中对二维平面上的方位的访问操作。

// https://github.com/STPR/contour_tracing

/*
    contours: an array of contours
    ol: outlines level
    hl: holes level
    rn: reachable neighbor - for the outlines: 0: none, 1: front left,  2: front, 3: front right
                           - for the holes:    0: none, 1: front right, 2: front, 3: front left
    o: orientation, e.g. to the east:
             N
       ┏━━━━━━━━━━━┓
       ┃ 7   0   1 ┃
     W ┃ 6   o > 2 ┃ E   o = [2, 3, 4, 5, 6, 7, 0, 1]
       ┃ 5   4   3 ┃
       ┗━━━━━━━━━━━┛
             S
*/

// Rotate 90 degrees, clockwise for the outlines (rot = 2) or
// counterclockwise for the holes (rot = -2)
o.rotate_left(rot.rem_euclid(8) as usize);

// Rotate 90 degrees, counterclockwise for the outlines (rot = 2) or
// clockwise for the holes (rot = -2)
o.rotate_right(rot.rem_euclid(8) as usize);

C++ STLstd::rotate()函数

实现上面的rotate_left以及rotate_right rust函数,在c++语言中存在着一个std::rotate函数可以实现相同的功能:

// std::rotate(iterator start, iterator middle, iterator end);
// Input:
vector<int> v{ 10, 20, 30, 40, 50 };

// rotating vector from 2nd element
rotate(v.begin(), v.begin() + 2, v.end());

// Output:
// 30 40 50 10 20

rotate()算法会从左边选择序列的元素。如下图所示,可以将序列中的元素想象成手镯上的珠子。rotate()操作会导致一个新元素成为开始迭代器所指向的第一个元素。在旋转之后,最后一个元素会在新的第一个元素之前。

VB.NET中的rotate函数

依照着C++中的对向量的rotate操作的函数实现原理,在VB.NET代码中实现了下面两个分别用于Left和Right方向旋转向量的通用函数:

Public Sub RotateLeft(Of T)(ByRef ArrayToRotate As T(), ByVal iPlacesToRotate As Integer)
    Dim kdd = ArrayToRotate.Take(iPlacesToRotate).ToArray
    Dim ddk = ArrayToRotate.Skip(iPlacesToRotate).ToArray

    Array.ConstrainedCopy(kdd, Scan0, ArrayToRotate, ArrayToRotate.Length - kdd.Length, kdd.Length)
    Array.ConstrainedCopy(ddk, Scan0, ArrayToRotate, Scan0, ddk.Length)
End Sub

Public Sub RotateRight(Of T)(ByRef ArrayToRotate As T(), ByVal iPlacesToRotate As Integer)
    ArrayToRotate = ArrayToRotate.Reverse.ToArray

    Dim ddk = ArrayToRotate.Take(iPlacesToRotate).Reverse.ToArray
    Dim kdd = ArrayToRotate.Skip(iPlacesToRotate).Reverse.ToArray

    Array.ConstrainedCopy(ddk, Scan0, ArrayToRotate, Scan0, iPlacesToRotate)
    Array.ConstrainedCopy(kdd, Scan0, ArrayToRotate, iPlacesToRotate, ArrayToRotate.Length - iPlacesToRotate)
End Sub

R#脚本语言中的rotate函数

将上面在VB.NET框架底层代码中所实现的向量左旋以及右旋的代码同时也开放给了R#脚本环境中,使用起来的实际效果是和rust代码中差不多的:

const x = [1,2,3,4,5,6,7,8,9];

print("Old vector: ");
print(x);
print("New vector after left rotation 3 times: ");
# 4 5 6 7 8 9 1 2 3
print(x |> rotate_left(3));

cat("\n\n\n");

print("Old vector: ");
print(x);
print("New vector after right rotation 4 times: ");
# 6 7 8 9 1 2 3 4 5
print(x |> rotate_right(4));

谢桂纲
Latest posts by 谢桂纲 (see all)

Attachments

No responses yet

Leave a Reply

Your email address will not be published. Required fields are marked *

博客文章
December 2024
S M T W T F S
1234567
891011121314
15161718192021
22232425262728
293031  
  1. 在mysql之中,针对24小时内的数据按照半个小时进行一次统计数量: ```sql SELECT DATE_FORMAT(FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(add_time) / 1800) * 1800), '%Y-%m-%d %H:%i') AS half_hour, COUNT(*) AS count FROM user_track.page_view WHERE add_time >=…

  2. 针对图对象进行向量化表示嵌入: 首先,通过node2vec方法,将node表示为向量 第二步,针对node向量矩阵,进行umap降维计算,对node进行排序,生成node排序序列 第三步,针对node排序序列进行SGT序列图嵌入,实现将网络图对象嵌入为一维向量