我有一个正在运行的旋转函数用于我的“items”int数组。下面的代码完成了它,除了我不必要地转移值。我试图实现“就地”轮换。我的意思是ptrs会增加或减少而不是从数组中获取值。我需要以这种方式“提升”效率水平这个方法。任何建议?
void quack::rotate(int nRotations)
{
if ( count <= 1 ) return;
else // make sure our ptrs are where we want them.
{
intFrontPtr = &items[0].myInt;
intBackPtr = &items[count-1].myInt;
}
for (int temp = 0; nRotations != 0;)
{
if ( nRotations > 0 )
{
temp = *intFrontPtr;
*intFrontPtr = *intBackPtr;
*intBackPtr = temp; // Connect temps for the rotation
--intBackPtr; // Move left [...<-] into the array
}
else if ( nRotations < 0 )
{
temp = *intBackPtr;
*intBackPtr = *intFrontPtr;
*intFrontPtr = temp; // Connect temps for the rotation
++intFrontPtr; // Move right [->...] into the array
}
if ( intBackPtr == &items[0].myInt ||
intFrontPtr == &items[count-1].myInt )
{
intFrontPtr = &items[0].myInt;
intBackPtr = &items[count-1].myInt; // need to re-set
if ( nRotations > 0 ) nRotations--; // Which ways did we rotate?
else nRotations++;
}
}
}
哦,是的,我正在尝试练习c ++,并且知道他们已经有许多函数可以编程执行此操作...我试图“构建我自己的”。我想我已经在语法上得到了它,但效率始终是我奋斗的地方。作为一个新手,我非常感谢对这方面的批评..
答案 0 :(得分:15)
在数组中旋转元素有一个老技巧(我首先在Programming Pearls中看到它)
假设您想要通过三个元素向左旋转数组。
首先反转前三个元素,然后反转剩余的元素,然后反转整个数组。
Starting Array:
1 2 3 4 5 6 7
After reversing the first three elements
3 2 1 4 5 6 7
After reversing the remaining elements
3 2 1 7 6 5 4
Finally reverse the entire array to get the final rotated array
4 5 6 7 1 2 3
可以在适当的位置反转阵列的部分,因此您不需要任何额外的内存。
答案 1 :(得分:6)
您可以保留数据,并有一个“基本索引”成员来指示数组应该从哪里开始。然后,您需要在访问阵列时使用它来调整索引。阵列本身应该是私有的,并且只能通过进行调整的访问器函数来访问。像这样:
class quack
{
public:
explicit quack(int size) : items(new Item[size]), size(size), base(0) {}
~quack() {delete [] items;}
void rotate(int n) {base = (base + n) % size;}
Item &operator[](int i) {return items[(base + i) % size];}
private:
quack(quack const&) = delete; // or implement these if you want
void operator=(quack const&) = delete; // the container to be copyable
Item *items;
int size;
int base;
};
虽然我称之为RotatableArray
,而不是quack
。
答案 2 :(得分:1)
一个接一个地进行旋转真的不是可行的方法。如果你正在进行超过2或3次旋转的任何事情,那么它的速度非常快。
编辑: 作为最后的想法......将元素放在一个(双)链接'循环'列表中(所以最终元素指向第一个),需要旋转才能将头指针移动几个元素。 (头指针是一个指针,指示循环列表中的哪个元素是开头)。
这是迄今为止在元素列表上进行旋转的最快(最简单)方法
答案 3 :(得分:1)
像往常一样,如果你真的需要物理旋转元素,那么C ++的正确答案就是使用std::rotate
,这正是你想要做的。
如果必须手动实现(作为练习作业),请查看这些slides以获取John Bentley的“Programming Pearls”中的算法。
答案 4 :(得分:0)
实际上,这样做的方法是使用索引而不是指针。
int to = 0;
int from = (to + nRotations) % count;
if (to == from)
return;
for (int i=0; i < count; i++) {
swap(from, to);
from = advance(from);
to = advance(to);
}
// ...
static inline int advance(int n, int count) { return (n + 1) % count; }
答案 5 :(得分:0)
我可能有一个替代解决方案来内联旋转数组。如前所述,这种方法的工作原理如下:
,而不是颠倒元素集的旧技巧初始化:
(注意q =向左移动的数量,n =数组的长度)
在i = 0到n-1上循环,其中n =数组的长度
以下内容可能有助于解释其工作原理。
示例,向左旋转2个字符:
a b c d e f g
c d e f g a b
x1 ch1 x2 ch2
2 c 0 a
0 a 5 f
5 f 3 d
3 d 1 b
1 b 6 g
6 g 4 e
4 e 2 c
正如您所看到的,这需要不超过n次迭代,因此线性时间算法也可以内联旋转(除了少量临时变量之外不需要额外的存储空间)。
这是一个实现上述算法的函数,您可以尝试一下:
void rotate(char *ar, int q)
{
if (strlen(ar) < 2)
{
return;
}
if (q <= 0)
{
return;
}
char ch1;
char ch2;
int x1;
int x2;
int i;
int n;
n = strlen(ar);
q %= n;
if (q == 0)
{
return;
}
x1 = q;
ch1 = ar[x1];
x2 = 0;
ch2 = ar[x2];
for (i=0;i<n;i++)
{
ar[x2] = ch1;
ch1 = ch2;
x1 = x2;
x2 -= q;
if (x2 < 0)
{
x2 += n;
}
ch2 = ar[x2];
}
}
答案 6 :(得分:0)
这是我通过修改代码here得到的:
template<class It>
It rotate(It begin, It const middle, It end)
{
typename std::iterator_traits<It>::difference_type i = 0, j;
if (begin != middle && middle != end)
{
while ((i = std::distance(begin, middle)) !=
(j = std::distance(middle, end)))
{
It k = middle;
std::advance(
k,
std::max(typename std::iterator_traits<It>::difference_type(),
j - i));
std::swap_ranges(k, end, begin);
if (i > j) { std::advance(begin, j); }
else { std::advance(end, -i); }
}
}
return std::swap_ranges(middle - i, middle, middle);
}
答案 7 :(得分:0)
以下是sdtom解决方案的代码
void rotateArray(int arr[], int low, int high)
{
while (low<high) {
int temp = arr[low];
arr[low]=arr[high];
arr[high]=temp;
low++;
high--;
}
}
void rotate (int arr[], int k,int uperLimit)
{
rotateArray(arr,0,k);
rotateArray(arr,k+1,uperLimit-1);
rotateArray(arr,0,uperLimit-1);
}
答案 8 :(得分:0)
https://stackoverflow.com/q/17119000/2383578:这与此处讨论的有些相似。将数组旋转特定量。
答案 9 :(得分:0)
有很多方法可以通过d个位置进行数组旋转。
以下链接来自Programming Pearls pdf。看一下这个。用代码非常清楚地解释。