[英]How can I shift an array to the right in c++?
我正在嘗試實現一個函數,用於將對象數組移動到數組的右側。 我在互聯網上找到的所有內容都是循環移位的實現,但這不是我想要的。 如果theres實際上是空的,那么我想將元素向右移動。 假設您創建了一個對象Packet數組,其大小為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]開始。 但這似乎不是很有效。
還有其他想法嗎?
假設數組有n個元素:
if(a[n-1]==null){
memmove(a+1, a, (n-1)*sizeof(Packet*));
a[0]=null;
}
另一種方法是不移動數組的元素,而是移動用於訪問它的索引。 基本上,你想要做的是添加1模數n。
從右到左迭代數組,將元素n-1
賦值給元素n
。 到達第一個元素時,為其指定null
。 (不管什么意思)
如果你要做很多事情(並且數組不小),可以考慮使用std::deque
,因為它允許在兩端進行有效的插入和刪除。 然后可以從后面彈出N
空值並在前面推動N
空值來替換N
位置的右移。 您也可以使用std::rotate
。
對於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和nonPOD類型,因為copy_backward
負責值類別,如果它是POD,那么它使用memmove
(至少在gcc使用的std庫中)。
std::advance
for random access迭代器使用簡單的加法/減法。
std::fill
也像std::copy*
一樣處理PODness。
指針類型的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
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;
}
應該做的伎倆。
您可以嘗試實現一個鏈接列表,它允許您移位/取消移位或推送/彈出元素(在這種情況下將釋放空間)。
這樣做的循環方式有什么問題? 它非常有效。 例如。:
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;
}
在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);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.