簡體   English   中英

如何在c ++中將數組移到右邊?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM