2012-09-14 13 views
6

wiem, że deque jest bardziej efektywne niż wektora kiedy wstawki są z przodu lub na końcu i wektor jest lepiej, jeśli mamy do czynienia wskaźnik arytmetycznych. Ale który z nich należy użyć, gdy musimy wykonać wstawienia w środku.? i dlaczego.?vs deque wkładania w środkowej

+3

Deque może nie być bardziej wydajny, zwłaszcza jeśli jest tylko niewielka liczba elementów. –

+0

W przypadku stosunkowo niewielkich kolekcji tanich przedmiotów do kopiowania, "wektor" bije pozostałe pojemniki rękami w dół, niezależnie od operacji. (Zmierzyłem "wektor " zamiast "deque " dla FIFO z maksymalnie 12 znakami, i chociaż 'deque' jest zoptymalizowany do tego wykorzystania,' wektor' był znacznie szybszy na testowanej maszynie.) –

Odpowiedz

10

Można by pomyśleć, że a deque miałoby tę zaletę, ponieważ przechowuje dane podzielone na bloki. Jednak implementacja operator[] w stałym czasie wymaga, aby wszystkie te bloki miały taki sam rozmiar. Wstawienie lub usunięcie elementu w środku nadal wymaga zmiany wszystkich wartości po jednej stronie lub drugiej, tak jak w przypadku vector. Ponieważ kod vector jest prostszy i ma lepszą lokalizację do buforowania, powinien wyjść z przodu.

0

Deque będzie nadal wydajniejszy, ponieważ nie będzie musiał przesuwać połowy tablicy za każdym razem, gdy wstawi się element.

Oczywiście będzie to miało znaczenie, jeśli weźmie się pod uwagę dużą liczbę elementów, a nawet wtedy, gdy zalecane jest przeprowadzenie testu porównawczego i sprawdzenie, który z nich działa lepiej w danym przypadku. Pamiętaj, że premature optimization is the root of all evil.

+0

O ile nie wstawisz na jednym z końców, 'deque' będzie wymagać przesunięcia niektórych elementów: albo wszystkie przed wstawieniem, albo wszystkie po wstawieniu. –

+0

@JamesKanze prawda, ale zwykle tylko ograniczona liczba z nich będzie musiała zostać przeniesiona. Jestem prawie pewien, że nie będzie to połowa wszystkich elementów, jak w przypadku wektora. – Qnan

1

std::dequemoże lepiej w dużych pojemnikach, ponieważ jest zwykle implementowany w postaci połączonej sekwencji ciągłych bloków danych, a nie do jednego bloku używanego w std::vector. Tak więc wstawienie w środku spowodowałoby skopiowanie mniejszej ilości danych z jednego miejsca do drugiego i potencjalnie mniejszą realokację.

Oczywiście, niezależnie od wielkości kontenerów i kosztów kopiowania przechowywanych elementów. Z C++ 11 przenieść semantykę, koszt tego drugiego jest mniej ważne. Ale w końcu jedynym sposobem poznania jest profilowanie za pomocą realistycznej aplikacji.

+0

Zgadzam się, ale należy zauważyć, że bloki danych sąsiadujących w ust. 1 są logiczne, a nie fizyczne. OP powinien badać fizyczny układ, aby w pełni zrozumieć konsekwencje wkładek środkowych. – WhozCraig

+0

Jak wskazano w moim komentarzu do odpowiedzi Douga T., jest to nieprawda. Jeśli wstawiasz blisko początku, 'deque' _może_ wybrać przesunięcie tylko elementów przed wstawieniem, przesuwając w ten sposób mniej niż' wektor'. Nie wiem, czy jakakolwiek implementacja faktycznie to robi, ale w każdym razie musi przesunąć _all_ elementów po jednej stronie wstawiania, przed lub po. –

+0

@JamesKanze może źle sformułowałem swoją odpowiedź. Nie zgadzam się z tym, co mówisz. Chodzi mi o to, że * wszystkie * elementów do przeniesienia są bardziej prawdopodobne, aby być mniejszą liczbą "" niż "#", niż "" "". – juanchopanza

3

Kryteria wyboru z pojemników bibliotecznych standard jest, wybrać pojemnik zależnie od:

  1. typ danych, które chcesz przechowywać &
  2. rodzaju operacji, które chcesz wykonać na danych.

Jeśli chcesz wykonać dużą liczbę wstawek w środku, lepiej jest użyć opcji std::list.

Jeśli wybór jest tylko między std::deque i std::vector następnie Istnieje wiele czynników do rozważenia:

  • Zazwyczaj jest jeszcze jedna droga pośrednia w przypadku deque dostępu do elementów, więc elementem dostęp a ruch iteratora jest zazwyczaj nieco wolniejszy.
  • W systemach, w których ograniczenia wielkości bloków pamięci, blokada może zawierać więcej elementów, ponieważ wykorzystuje więcej niż jeden blok pamięci. Zatem max_size() może być większy dla kotów.
  • Deques nie zapewniają wsparcia w zakresie kontroli wydajności i momentu realokacji. W szczególności, jakiekolwiek wstawienie lub usunięcie elementów innych niż na początku lub końcu unieważnia wszystkie wskaźniki, odwołania i iteratory, które odnoszą się do elementów zasobnika. Jednak realokacja może przebiegać lepiej niż dla wektorów, ponieważ zgodnie z ich typową wewnętrzną strukturą , deki nie muszą kopiować wszystkich elementów podczas realokacji.
  • Bloki pamięci może się uwolniony, gdy nie są już używane, a więc wielkość pamięci o deque może się kurczyć (nie jest to warunek nałożony przez standardowy ale większość implementacji zrobić)
+2

To nie jest tak oczywiste, jak mogłoby się wydawać. Na nowoczesnych architekturach, 'std :: list' jest bardzo mało wydajne, ogólnie rzecz biorąc, ze względu na jego słabą lokalizację, a jeśli zawartość jest tania do skopiowania, może być szybsze wstawienie do środka' wektora', pomimo kopii . –

+0

Również wewnętrzna struktura 'deque' wymaga tego, aby kopiowała wszystkie elementy przynajmniej po jednej stronie wstawienia, jeśli wstawienie nie jest na końcu. (Mówiąc bardziej ogólnie, można powiedzieć, że 'wektor' wymaga przesunięcia wszystkich elementów po wstawieniu, a' deque' wymaga przesunięcia wszystkich elementów po lub wszystkich elementów wcześniej). –

Powiązane problemy