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

- Rejestracja:ponad 13 lat
- Ostatnio:prawie 10 lat
- Postów:98
- Rejestracja:prawie 16 lat
- Ostatnio:5 miesięcy
- Postów:2514
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ąć)


- Rejestracja:ponad 13 lat
- Ostatnio:prawie 10 lat
- Postów:98
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?

- Rejestracja:ponad 13 lat
- Ostatnio:prawie 10 lat
- Postów:98
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:
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ć?
Jest tak ze jesli tworzysz
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)
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.

- Rejestracja:ponad 13 lat
- Ostatnio:prawie 10 lat
- Postów:98
Krycho napisał(a)
Jest tak ze jesli tworzysz
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)
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?
#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 ;).
- Rejestracja:prawie 14 lat
- Ostatnio:ponad 6 lat
- Lokalizacja:Białystok
- Postów:258
vector< vector<int> > JestemWektorem(4, vector<int>(4));
Dwuwymiarowy wektor 4x4
Analogicznie robi się czterowymiarowy:
//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
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.

- Rejestracja:ponad 21 lat
- Ostatnio:około 7 godzin
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:
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
const vector<vector<vector<vector<int>>>> tab = // itd.
— spróbujcie to zrobić z constem w poprzednim standardzie…

- Rejestracja:ponad 13 lat
- Ostatnio:prawie 10 lat
- Postów:98
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:
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
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.

- Rejestracja:około 22 lata
- Ostatnio:ponad rok
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ć.

- Rejestracja:ponad 13 lat
- Ostatnio:prawie 10 lat
- Postów:98
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? ^^

- Rejestracja:ponad 13 lat
- Ostatnio:prawie 10 lat
- Postów:98
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)
#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

- Rejestracja:ponad 13 lat
- Ostatnio:prawie 10 lat
- Postów:98
Wprowadziłem ten kod w życie:
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.
