我正在尝试实现一个将对象数组移动到数组右侧的函数。我在互联网上找到的所有内容都是循环移位的实现,但这不是我想要的。如果theres实际上是空的,那么我想将元素向右移动。 假设您创建了一个对象数据包数组,其大小为10
Packet* a[] = { p4 , p3 , p2 , p1, null, null, null, null, null, null }
移位功能只会将所有内容都移到右侧
{ null ,p4 , p3 , p2 , p1, null, null, null, null, null }
并且在数组末尾有一个元素
{ p10, p9, p8, p7 ,p6 ,p5 ,p4 , p3 , p2 , p1}
该功能不会改变任何东西。
{ p4 , p3 , p2 , p1, null, null, null, null, null, null }
我的实现想法是将数组复制到临时数组中, 擦除原始数组上的所有内容,然后复制到其中但从位置[1]开始而不是位置[0]。但这似乎不是很有效。
还有其他想法吗?
答案 0 :(得分:9)
假设数组有n个元素:
if(a[n-1]==null){
memmove(a+1, a, (n-1)*sizeof(Packet*));
a[0]=null;
}
另一种方法是不移动数组的元素,而是移动用于访问它的索引。基本上,你想要做的是添加1模数n。
答案 1 :(得分:4)
从右到左迭代数组,将元素n-1
分配给元素n
。当您到达第一个元素时,请为其指定null
。 (无论那意味着什么)
答案 2 :(得分:2)
如果你要做很多事情(并且数组不小),可以考虑使用std::deque
,因为它允许在两端有效插入和删除。然后,可以从后面弹出N
null并在前面推送N
null来替换N
个位置的右移。您也可以使用std::rotate
。
答案 3 :(得分:2)
对于POD和非POD类型的任何容器(包括原始数组),请使用以下命令:
template <class Iterator, class Distance>
void shiftRight(Iterator begin, Iterator end, Distance dist)
{
typedef typename std::iterator_traits<Iterator>::value_type value_type;
Iterator newBegin = begin, oldEnd = end;
std::advance(newBegin, dist);
std::advance(oldEnd, -dist);
std::copy_backward(begin, oldEnd, end);
std::fill(begin, newBegin, value_type());
}
它适用于POD和非POD类型,因为copy_backward
负责值类别,如果它是POD,那么它使用memmove
(至少在gcc使用的std库中)。
std::advance
使用简单的加法/减法。
std::fill
也会像std::copy*
一样照顾POD。
value_type()
只是NULL,对于bool false,对于整数类型0等等。
数组用法:
int* a[] = { 0, new int(1), new int(2), 0, 0, new int(3) };
std::for_each(a, a + sizeof(a) / sizeof(*a), [](int* a) { !a ? (std::cout << "null\n") : (std::cout << *a << "\n"); });
shiftRight(a, a + sizeof(a) / sizeof(*a), 3);
std::cout << "-----------------------------------------------------\n";
std::for_each(a, a + sizeof(a) / sizeof(*a), [](int* a) { !a ? (std::cout << "null\n") : (std::cout << *a << "\n"); });
按预期输出:
null
1
2
null
null
3
-----------------------------------------------------
null
null
null
null
1
2
答案 4 :(得分:1)
C ++中明显的答案是使用std::vector
,在这种情况下,使用它
变得如此简单:
if ( a.back() == NULL ) {
a.insert( a.begin(), NULL );
a.pop_back();
}
您可能还会考虑std::deque
,这将允许push_front
,
而不是insert
。对于这种简单复制的小阵列
对象。 std::vector
的简单性通常会胜出。
如果必须使用C样式数组,例如:
if ( *(end( a ) - 1) == NULL ) {
std::copy_backwards( begin( a ), end( a ) - 1, end( a ) );
a[0] = NULL;
}
应该这样做。
答案 5 :(得分:0)
你可以尝试实现一个链接列表,它允许你移动/取消移动或推/弹元素(在这种情况下将释放空间)。
循环方式有什么问题?它非常有效。例如:
bool insert(Packet *queue[], int *rear, int front, Packet *value)
{
int tmp = (*rear+1) % MAX;
if (tmp == front)
return false;
*rear = tmp;
queue[*rear] = value;
return true;
}
bool delete(Packet *queue[], int rear, int *front, Packet **value)
{
if (*front == rear)
return false;
*front = (*front+1) % MAX;
*value = queue[*front];
return true;
}
答案 6 :(得分:0)
在C ++ 11中,我们有std::rotate
。
int [] values = {1, 2, 3, 4, 5};
std::rotate(
std::begin(values),
std::next(std::begin(values)), // the new 'top'
std::end(values));
*std::rbegin(values) = 0;
assert(values[0] == 2);
assert(values[1] == 3);
assert(values[2] == 4);
assert(values[3] == 5);
assert(values[4] == 0);