`
wen866595
  • 浏览: 267994 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

向量旋转

阅读更多

 

本文先发布于:http://coderbee.net/index.php/algorithm/20130619/224

 

向量旋转

题目均来自《编程珠玑》,代码实现是用Go语言。

 

将一个n元一维向量向左旋转(循环移位)i个位置。例如,当n=8时且i=3时,向量abcdefgh旋转为defghabc。简单的代码使用一个n元的中间向量在n步内完成该工作。能否仅用数十个额外直接的存储空间,在正比于n的时间内完成向量的旋转?

 

旋转操作对应于交换相邻的不同大小的内存块:每当拖动文件中的一块文件到其他地方时,就要求程序交换两块内存中的内容。

 

两个简单直接的方法

方法一:首先将 x 的前 i 个元素复制到一个临时数组中,然后将余下的 n-i 个元素向左移动 i 个位置,最好将最初的 i 个元素从临时数组中复制到 x 中余下的位置。这种办法使用 i 个额外的位置产生了过大的存储空间的消耗。

 

方法二:定义一个函数将 i 向左旋转一个位置(其时间正比于 n),然后调用该函数 i 次。该方法产生了过多的运行时间消耗。

 

下面介绍三种更好的方法。

 

跳跃交换实现

这个算法的思路就是:向量旋转后,vec[i]存储的将是vec[2i]的值,vec[2i]存储的是vec[3i]的值,如此类推。

 

要注意的就是,如果 n % i != 0,那么,要移动的部分超出 n%i 的长部分位于 i - n%i 的后面,本来应该在前的,所以又需要对这一部分进行旋转。

 

实现


func VectorRotateByMagic(vec []byte, n int) {
    need, n := checkParam(vec, n)
    if !need {
        return
    }

    length := len(vec)
    for i := 0; i < n; i++ {
        v, j := vec[i], i+n
        for ; j < length; j += n {
            vec[j-n] = vec[j]
        }
        vec[j-n] = v
    }

    mod := length % n
    if mod != 0 {
        VectorRotateByMagic(vec[length-n:], n-mod)
    }
}

func checkParam(vec []byte, n int) (bool, int) {
    length := len(vec)
    if length < 2 {
        return false, n
    }

    if n < 0 {
        n = -1 * n
        n = n % length
        n = length - n
    } else {

        n = n % length
    }

    if n == 0 {
        return false, n
    }

    return true, n
}

 

用求逆实现

下面这张图足以说明这个算法的思路来了:

 

 

实现


func VectorRotateWithReverse(vec []byte, n int) {
    need, n := checkParam(vec, n)
    if !need {
        return
    }

    util.Reverse(vec[0:n])
    util.Reverse(vec[n:])
    util.Reverse(vec)
}

// util.Reverse
func Reverse(arr []byte) {
        var b byte
        for l, r := 0, len(arr)-1; l < r; l, r = l+1, r-1 {
            b = arr[l]
            arr[l] = arr[r]
            arr[r] = b
        }
}

 

用交换向量实现

原理:旋转向量x其实就是交换向量ab的两段,得到向量ba。 这里的a代表x中的前i个元素。假设a比b短,将b分为bL和bR,使得bR具有与a相同的长度。 交换a和bR,也就将a bL bR转换为bR bL a。序列a此时已处于其最终位置,因此现在的同样问题就集中到交换b的两部分。 由于新问题与原来的问题具有相同的形式,可以递归地解决。

 

实现


func VectorRotate(vec []byte, n int) {
    need, n := checkParam(vec, n)
    if !need {
        return
    }

    rotate(vec, n)
}

func rotate(vec []byte, l int) {
    length := len(vec)
    if length < 2 {
        return
    }

    r := length - l

    if l <= r {
        swapChunk(vec, 0, vec, length-l, l)
        rotate(vec[0:length-l], l)
    } else {
        swapChunk(vec, 0, vec, length-r, r)
        rotate(vec[r:], l-r)
    }
}

func swapChunk(src []byte, srcIndex int, dst []byte, dstIndex int, length int) {
    for i := 0; i < length; i, srcIndex, dstIndex = i+1, srcIndex+1, dstIndex+1 {
        t := src[srcIndex]
        src[srcIndex] = dst[dstIndex]
        dst[dstIndex] = t
    }
}

func checkParam(vec []byte, n int) (bool, int) {
    length := len(vec)
    if length < 2 {
        return false, n
    }

    if n < 0 {
        n = -1 * n
        n = n % length
        n = length - n
    } else {

        n = n % length
    }

    if n == 0 {
        return false, n
    }

    return true, n
}

问题扩展

向量旋转函数将向量ab变为ba。如何将向量abc变为cba?(这对交换非相邻内存块的问题进行建模)

 

这个问题其实可以先把 bc看作一个整体,那么问题就变为向量旋转的问题,旋转后变为bca,再对bc部分进行旋转,仍然是个向量旋转问题,旋转后即可得到最终结果cba。

 

如果用求逆的思路,仍然跟上面的类似。

 

 

  • 大小: 66.9 KB
1
3
分享到:
评论

相关推荐

    计算向量旋转矩阵的代码

    这是一个MATLAB代码。输入参数为两组不同坐标系中的向量,通过计算实现两组向量之间的旋转。组后将旋转矩阵进行分解求出三个旋转角。

    WPF 基础 2D 图形学知识 求向量旋转角度.rar

    在本文中,我们将深入探讨WPF(Windows Presentation Foundation)中的2D图形学,特别是关于向量旋转角度的知识。WPF是.NET Framework的一部分,提供了一种强大的机制来创建丰富的、交互式的用户界面,其中包括复杂...

    11_MUSIC算法_matlab向量旋转_music_

    在MATLAB中,向量旋转是通过矩阵乘法实现的,通常使用旋转变换矩阵。在MUSIC算法中,可能需要对传感器阵列的几何结构进行虚拟旋转,以改善方向估计的性能。这可以通过改变阵列的相位响应或者调整数据矩阵来实现。...

    C++实现一维向量旋转算法

    【C++一维向量旋转算法详解】 在C++编程中,处理一维向量的旋转操作是一项常见的任务,尤其在数据结构和算法领域。这个问题通常被称为数组循环移位,即给定一个长度为n的一维向量,需要将其向左或向右旋转i个位置。...

    N维空间中的旋转方法(仅是数学推导,不是代码)

    此外,旋转的方向定义为将x向量旋转至y向量的方向,即rotP0,π/2(x)=y。 通过数学推导,我们可以将任意N维空间中的旋转问题简化为在二维平面上进行旋转。首先,将向量v投影到平面P0上,得到vp,然后在这个二维平面...

    cordic 向量旋转matlab程序

    自己编写的cordic vector旋转的matlab程序,输入角度 z 在 -180 到 +180 之间

    matlab 函数,绕向量K旋转角度theta, 等效于旋转矩阵R

    matlab 函数 R = fnKTheta2R(k,theta),输入单位向量K,角度theta, 输出等效的旋转矩阵R

    程序:四元数欧拉角旋转向量旋转矩阵变换transform.cpp

    代码!!!!重要!!!! 学习中关于机器人领域中四元数、欧拉角、旋转矩阵、旋转向量的相互转换关系总结,整理加深记忆。 每一个都有相互转换关系,并注释

    Rotation Using Eigen Vectors:这是一个使用特征向量旋转图片的小程序。-matlab开发

    因此,使用特征向量旋转图像可以实现精确的几何变换,同时保留图像的主要特征。 在该MATLAB小程序中,首先需要对图像进行预处理,包括读取图像、转换为灰度图像(如果原图是彩色的)以及进行尺寸标准化。然后,通过...

    findRotationAngle.m:绕第三个向量旋转时两个向量之间的角度-matlab开发

    在MATLAB编程环境中,`findRotationAngle.m` 文件是一个用于计算向量旋转角度的函数,特别是在三维空间中绕着第三个向量进行旋转的情况。这个函数的主要目的是解决如何找到一个向量(a)需要旋转多少角度,使其在与...

    C#坐标旋转算法

    在C#编程语言中,处理坐标旋转通常涉及到矩阵运算和向量数学。本文将深入探讨标题和描述中提到的两个知识点:如何实现A点绕B点旋转X度的新坐标算法,以及计算两点坐标之间的距离。 首先,我们来讨论A点绕B点旋转X度...

    Unity实现绕任意轴任意角度旋转向量

    Unity实现绕任意轴任意角度旋转向量 Unity是一个功能强大且广泛应用的游戏引擎,它提供了强大的图形处理和物理引擎功能,但在实际应用中,我们会遇到各种复杂的问题,其中之一就是旋转向量问题。本文将为大家详细...

    绕轴旋转向量:将三维向量绕指定轴旋转指定角度。-matlab开发

    在MATLAB编程环境中,绕轴旋转向量是一个常见的任务,特别是在3D图形、机械工程、计算机视觉等领域。罗德里格斯公式(Rodrigues' rotation formula)是一种简便的方法,用于计算三维空间中向量绕固定轴旋转后的新...

    计算旋转向量和平移向量.rar

    在"计算旋转向量和平移向量.rar"的压缩包中,主要涉及的是如何通过OpenCV计算两帧连续图像之间的旋转和平移参数。这些参数通常被称为刚体变换,因为它们描述了图像在空间中的线性变换。 1. **旋转和平移的概念**: ...

    matlab开发-旋转使用生成向量

    "旋转使用生成向量"的标题指的是利用本征向量(或特征向量)来实现图像的旋转。这种技术基于线性代数的概念,可以高效且精确地变换图像。下面将详细介绍这个过程以及相关知识点。 首先,我们要理解什么是本征向量和...

    c++计算三维点云rt矩阵转欧拉角

    这个矩阵描述了如何从一个向量旋转到另一个向量。通常,我们使用向量叉乘和标量积来找到旋转轴和旋转角度。向量A到B的旋转变换矩阵可以通过以下步骤得到: 1. 计算向量A和B的叉乘结果,得到旋转轴N。 2. 使用标量积...

    C#实现计算一个点围绕另一个点旋转指定弧度后坐标值的方法

    它涉及到坐标平移、角度计算、向量旋转等概念,这些知识对于理解计算机图形学和游戏开发中的几何变换至关重要。通过学习和实践这样的方法,开发者可以更好地掌握C#在处理复杂几何问题时的能力。

Global site tag (gtag.js) - Google Analytics