Wielowymiarowe wektory

Wielowymiarowe wektory
Losiu22
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 10 lat
  • Postów:98
0

Witam,
ostatnio natrafiłem gdzieś w internecie na artykuł o wektorach w C++ i mówiąc szczerzę gościu tam się wypowiadający mnie przekonał.
Mam jednak kilka pytań co do tego;
-Czy to rzeczywiście tak jest z tymi wektorami, że to niby są lepsze niż tablice i zużywają mniej pamięci?
-Jak tworzy się vektory wielowymiarowe (chodzi mi tutaj o taki 4-wymiarowy)
Podrawiam.
Wesołych świąt i szczęśliwego Nowego Roku :D

KR
  • Rejestracja:prawie 16 lat
  • Ostatnio:5 miesięcy
  • Postów:2514
1

Czy to rzeczywiście tak jest z tymi wektorami, że to niby są lepsze niż tablice i zużywają mniej pamięci?

Nie, zajmują tyle samo lub więcej miejsca. Wektor sam realokuje pamięć gdy jej potrzebuje, ale alokuje jej więcej niż potrzebujesz po to żeby przy dodawaniu elementów nie musiał realokować co chwilę. Główną zaletą jest to, że nie musisz się w to ręcznie bawić, a działa on praktycznie tak samo jak ręcznie alokowana tablica. Osobiście używaj vectorów, list, map, ... gdzie się tylko da, ale używaj tylko tej struktury której rzeczywiście potrzebujesz.

Jak tworzy się vektory wielowymiarowe (chodzi mi tutaj o taki 4-wymiarowy)

vector< vector<typ> vector_dwuwymiarowy;
vector< vector< vector<typ> > > vector_trojwymiarowy; (zwroc uwage na spacje miedzy > >, nie wolno jej pominąć)


░█░█░█░█░█░█░█░█░█░█░█░
Endrju
Btw, spacja jest niepotrzebna w C++11.
KR
dopóki większość używa starszej wersji lepiej o niej wspomnieć :) ale przyznam, że nie wiedziałem o niej mimo że mam najnowszą wersje :P
Losiu22
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 10 lat
  • Postów:98
0

Nie mam teraz przy sobie kompilatora jednak spytam dla pewności:
Wektor cztero(czwór?)wymiarowy robi się tak:
vector< vector< vector< vector<typ> > > > nazwa_vectora;
?
No i jak przypisać wartości do tego np. czwartego wymiaru?
nazwa_vectora[0][0][0][4] = liczba?

0

Jesli nie nadasz mu wczesniej wielkosci to wtedy musisz np. do tego ostatniego wymiaru wrzucic caly vector push.backiem tab[0][0][0].push_back(tab2) gdzie tab 2 bedzie vectorem 1 wymiarowym. Dokladnie skladni teraz nie pamietam, bo z pamieci, ale jakos tak to wygladalo.

Losiu22
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 10 lat
  • Postów:98
0
Krycho napisał(a)

Jesli nie nadasz mu wczesniej wielkosci to wtedy musisz np. do tego ostatniego wymiaru wrzucic caly vector push.backiem tab[0][0][0].push_back(tab2) gdzie tab 2 bedzie vectorem 1 wymiarowym. Dokladnie skladni teraz nie pamietam, bo z pamieci, ale jakos tak to wygladalo.

Nie do końca rozumiem.
Chcę dodać po prostu w odpowiednie miejsce liczbę (int) i zastanawiam się czy taki sposób jest poprawny:

Kopiuj
vector< vector< vector< vector<int> > >  > nazwa_vectora;
nazwa_vectora[0][0][0][4] = 1;

EDIT:
No i rozumiem że vektory nie będą powiększać się automatycznie jeśli będę chciał dodać dane poza zakresem. Co wtedy zrobić?

edytowany 1x, ostatnio: Losiu22
0

Jest tak ze jesli tworzysz

Kopiuj
vector <int> nazwa

to wtedy taki vector jakby nie ma wielkosci i kazdy element trzeba mu dodawac poprzez nazwa.push_back(int). Natomiast jesli stworzysz vector <int> nazwa(5)

Kopiuj
 to masz 5 elementowy vector i mozesz normlanie mu przypisac nazwa[0]=1
Przy wiekszych vectorach jest to samo. Tylko w nawiasie wielkosc sie podawalo jakos(przy 2 wymiarach) 
```cpp
vector< vector<int> >nazwa(4, vector <int>(4))

i masz vector 4 na 4 gdzie mozesz sie odwolywac poprzesz nazwa[0][0]. Dalej analogicznie.

Losiu22
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 10 lat
  • Postów:98
0
Krycho napisał(a)

Jest tak ze jesli tworzysz

Kopiuj
vector <int> nazwa

to wtedy taki vector jakby nie ma wielkosci i kazdy element trzeba mu dodawac poprzez nazwa.push_back(int). Natomiast jesli stworzysz vector <int> nazwa(5)

Kopiuj
 to masz 5 elementowy vector i mozesz normlanie mu przypisac nazwa[0]=1
> Przy wiekszych vectorach jest to samo. Tylko w nawiasie wielkosc sie podawalo jakos(przy 2 wymiarach) 
```cpp
vector< vector<int> >nazwa(4, vector <int>(4))

i masz vector 4 na 4 gdzie mozesz sie odwolywac poprzesz nazwa[0][0]. Dalej analogicznie.

Nadal nie kumam wszystkiego:

kazdy element trzeba mu dodawac poprzez nazwa.push_back(int).

Rozumiem że "int" to jakaś liczba i nie podaję tutaj typu zmiennej.
A jeśli chciałbym dodać element z drugiego wymiaru? Czy jak to działa?
No bo teraz opisałeś chyba jak to się robi przy wektorach jednowymiarowych. Ja natomiast chcę używać 4-wymiarowych. Jak więc mam dodawać elementy do takiego wektora?

edytowany 1x, ostatnio: Losiu22
1
Kopiuj
#include <iostream>
#include <vector>

using namespace std;
int main()
{
    vector< vector< vector< vector<int> > > > tab;
    vector< vector< vector<int> > >tab4;
    vector< vector<int> >tab2;
    vector<int> tab3;
    tab3.push_back(5);
    tab3.push_back(2);
    tab2.push_back(tab3);
    tab4.push_back(tab2);
    tab.push_back(tab4);
    cout << tab[0][0][0][0]; //5
    cout << tab[0][0][0][1]; //2
    return 0;
}

Masz wektor 4 wymiarowy. Jesli nie masz sprecyzowanej wielkosci musisz mu robic cos takiego. Najpierw najbardziej podstawowy wektor 1 wymiarowy. Dodajesz elementy i wrzucasz do 2 wymiarowego caly wektor. Potem do 3 i na koncu do 4. To jest tak jakby kazdy element tego 4 wymiarowego wektora byl wektorem 3 wymiarowym. Nie potrafie tego dobrze wyjasnic po prostu tak jest ;).

JA
  • Rejestracja:prawie 14 lat
  • Ostatnio:ponad 6 lat
  • Lokalizacja:Białystok
  • Postów:258
2
Kopiuj
 vector< vector<int> >      JestemWektorem(4, vector<int>(4)); 

Dwuwymiarowy wektor 4x4
Analogicznie robi się czterowymiarowy:

Kopiuj

//vector< int > //1D
//vector< vector< int > >  //2D  
//vector< vector< vector< int > > >  //3D
//vector< vector< vector< vector< int > > > > //4D




vector< vector< vector< vector< int > > > >  JestemWektorem(4, vector< vector< vector <int> > >(4,  vector< vector<  int > >(4, vector< int >(4, -1) ) ) );
//Czterowymiarowy wektor intów, o startowym rozmiarze 4x4x4x4, wypełniony domyślnie w całości wartością -1;

JestemWektorem[0][0][0][2]=5;
JestemWektorem[3][3][3][3]=-2;
JestemWektorem[0][1][2][3]=0;

cout << JestemWektorem[0][0][0][2] << endl << JestemWektorem[3][3][3][3] << endl << JestemWektorem[0][1][2][3] << endl << JestemWektorem[3][2][1][0];
//Wypisujemy co wpisaliśmy i jedno inne, żeby zobaczyć, że się dobrze wypełniło na starcie.

 

Potem możesz go sobie poszerzać za pomocą resize() albo dodawać elementy na wierzch przez push_back().
Oczywiście3 wygodniej byłoby sobie zrobić jakieś typedefy do tego, na przykład tak jak tutaj - http://www.daniweb.com/software-development/cpp/threads/137814

Kopiuj
 
typedef  vector<int>       vector1D;
typedef  vector<vector1D>  vector2D;
typedef  vector<vector2D>  vector3D;
typedef  vector<vector3D>  vector4D;


vector4D JestemWektorem(4, vector3D(4, vector2D(4, vector1D(4,-1) )  ) );

JestemWektorem[0][0][0][2]=5;
JestemWektorem[3][3][3][3]=-2;
JestemWektorem[0][1][2][3]=0;

cout << JestemWektorem[0][0][0][2] << endl << JestemWektorem[3][3][3][3] << endl << JestemWektorem[0][1][2][3] << endl << JestemWektorem[3][2][1][0];

Na przykład tak.

edytowany 2x, ostatnio: Jadeszek
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 7 godzin
1

dodam jeszcze, że w C++11 nie trzeba kombinować z osobnym wypełnianiem push_backami podwektorów i podwektorów tych podwektorów, tylko można zapodać takiego kombosa:

Kopiuj
  vector<vector<vector<vector<int>>>> tab = 
  {{{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}}},
   {{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}}},
   {{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}}},
   {{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}}}};
 
  cout << tab[1][1][1][1] << endl;

a nawet

Kopiuj
const vector<vector<vector<vector<int>>>> tab = // itd.

— spróbujcie to zrobić z constem w poprzednim standardzie…

edytowany 2x, ostatnio: Azarien
02
a jest jakiś powód, żeby do takiej tablicy używać const vectora zamiast const tablicy?
Endrju
Oczywiście. Funkcja xyz może wymagać podania jej czterowymiarowego vectora. Jeżeli użyjesz go tylko raz miło jest zadeklarować go const.
Losiu22
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 10 lat
  • Postów:98
0
Azarien napisał(a)

dodam jeszcze, że w C++11 nie trzeba kombinować z osobnym wypełnianiem push_backami podwektorów i podwektorów tych podwektorów, tylko można zapodać takiego kombosa:

Kopiuj
  vector<vector<vector<vector<int>>>> tab = 
  {{{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}}},
   {{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}}},
   {{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}}},
   {{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}},{{1,2,3},{1,2,3}}}};
 
  cout << tab[1][1][1][1] << endl;

a nawet

Kopiuj
const vector<vector<vector<vector<int>>>> tab = // itd.

— spróbujcie to zrobić z constem w poprzednim standardzie…

OK. Wszystko jasne :D
Tak z ciekawości spytam: jak sprawdzić jakie mam C++?
Mówiąc szczerze nigdy nie wiedzialem że istnieją rózne wersje tego języka.

Endrju
  • Rejestracja:około 22 lata
  • Ostatnio:ponad rok
1

W zasadzie standard jest jeden. ISO/IEC 14882:2011, zwany C++11, przyjęty 12 sierpnia br. Oczywiście nie wszystkie kompilatory wspierają go w 100%, dlatego przez jakiś czas będzie sie mówić o tym C++11 i poprzednim C++03 i o tym jak to różne rzeczy działają w nich inaczej. W GCC trzeba dodać -std=c++0x do komendy kompilatora, żeby go używać, w MSVC (cl) chyba nie trzeba niczego dodawać.


"(...) otherwise, the behavior is undefined".
edytowany 1x, ostatnio: Endrju
Losiu22
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 10 lat
  • Postów:98
0
Jadeszek napisał(a)

[...]

Potem możesz go sobie poszerzać za pomocą resize() albo dodawać elementy na wierzch przez push_back().
Oczywiście3 wygodniej byłoby sobie zrobić jakieś typedefy do tego, na przykład tak jak tutaj - http://www.daniweb.com/software-development/cpp/threads/137814

A czy to rozszerzanie jest konieczne?
Nie lubię mieć braków w wiedzy więc zagłębiłem się w te arcyciekawy artykuł (:P):
http://sadi.ovh.org/arty/cppwektory.php
W którym autor niezbicie twierdzi, że wektory same sobie znajdują pamięć dla naszych zmiennych i nie trzeba troszczyć się o wstawianie "push_back()" i tym podobnych.
Jest to w części: "Wektory, a dynamiczne tablice"

Zwróć uwagę na to, że deklarujemy tylko 3 elementy, a dalej chcemy operować na 10. Jest to jawne wykroczenie poza zakres, połączone z niszczeniem danych z pamięci, która nie należy do naszego programu. A raczej tak by było, gdybyśmy użyli zwykłej tablicy. Wektor jednak jest na tyle sprytny, że zwiększa swoje rozmiary, gdy chcemy coś zrobić z polem, które nie istnieje. Innymi słowy wektor zawsze ma dokładnie tyle pól ile trzeba, ale nie mniej niż zadeklarowaliśmy. Dlatego stosując wektor w programie, w którym najpierw pobieramy od użytkownika rozmiar tablicy, a potem jej elementy, praktycznie nie obchodzą nas kwestie związane z pamięcią!

A więc jak to w końcu jest? ^^

Endrju
  • Rejestracja:około 22 lata
  • Ostatnio:ponad rok
1

Lolwut. Zmień w tamtym kodzie [i] na .at(i) i dostaniesz piękny wyjątek. Przy [i] runtime się również wysypuje. std::vector nic sam nie zrobi, to jakieś brednie.


"(...) otherwise, the behavior is undefined".
Losiu22
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 10 lat
  • Postów:98
0

OK. Tym razem to już mam nadzieję ostatnia wątpliwość:
Jak użyć "push_back()" do wielowymiarowego wektora,jeśli przykładowo chciałbym dodać element z wymiaru trzeciego?
Ja nie wiem jakim cudem tego nie ma w internecie. Toż to podstawa.
EDIT:
Co prawda kolega dał tutaj kod:

Krycho napisał(a)
Kopiuj
#include <iostream>
#include <vector>

using namespace std;
int main()
{
    vector< vector< vector< vector<int> > > > tab;
    vector< vector< vector<int> > >tab4;
    vector< vector<int> >tab2;
    vector<int> tab3;
    tab3.push_back(5);
    tab3.push_back(2);
    tab2.push_back(tab3);
    tab4.push_back(tab2);
    tab.push_back(tab4);
    cout << tab[0][0][0][0]; //5
    cout << tab[0][0][0][1]; //2
    return 0;
}

Masz wektor 4 wymiarowy. Jesli nie masz sprecyzowanej wielkosci musisz mu robic cos takiego. Najpierw najbardziej podstawowy wektor 1 wymiarowy. Dodajesz elementy i wrzucasz do 2 wymiarowego caly wektor. Potem do 3 i na koncu do 4. To jest tak jakby kazdy element tego 4 wymiarowego wektora byl wektorem 3 wymiarowym. Nie potrafie tego dobrze wyjasnic po prostu tak jest ;).

natomiast tu jest straszny "misz-masz". Nic nie rozumiem.
I nie da się tego rozwiązać bez potrzeby tworzenia innych wektorów?</del>
Działa :D

edytowany 3x, ostatnio: Losiu22
Losiu22
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 10 lat
  • Postów:98
0

Wprowadziłem ten kod w życie:

Kopiuj
vector< vector< vector< vector<int> > > > Vpush_back(int dana,  vector< vector< vector< vector<int> > > >vector4){
    vector< vector< vector<int> > >vector3;
    vector< vector<int> >vector2;
    vector<int> vector1;

    vector1.push_back(dana);
    vector2.push_back(vector1);
    vector3.push_back(vector2);
    vector4.push_back(vector3);

    return vector4;
}

Tknął mnie tylko jeden mały szczegół :/
Za każdym razem nowa liczba będzie dodawana na początek (czyli zawsze zmieniane będzie to: vector[0][0][0][0])
Dlaczego? Bo za każdym razem tworzymy od nowa vector1 :/
Czy ktoś zna jakieś rozwiązanie co zrobić aby dodać następny element do wektora a nie nadmienić pierwszy?
PS: Nie ma tutaj opcji typu: usuń post? Poprzedni wysłał się 2 razy.

edytowany 3x, ostatnio: Losiu22
xeo545x39
Jest, w lewym dolnym rogu postu, taki znaczek czerwony z minusikiem.
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)