Documente Academic
Documente Profesional
Documente Cultură
Vectori in STL
Vectorii sunt containăre alocate dinamic exact ca tablourile statice având o organizare
secvențială a elementelor.
vector<tip_date> nume;
exemplu
vector<int> v;
Inițial vectorul este gol având 0 poziții. Se obișnuiește ca în lucrul cu tablouri statice
din C să se prealoce numărul de poziții pentru cât se crede că va fi nevoie și folosirea
poziților de la 1. Ambele sunt obiceiuri proaste deși poate face problemele de numărare mai
ușoare se pierde o poziție în zadar care deși pare puțină memorie câte un pic de aici și
deacolo într-un program mai complex și se adună iar despre prealocare nu trebuie să mai
zic, ori prea multă memorie alocata inutil pentru un caz în care se folosesc doar 10 poziții
sau unul mult prea mare, de aceea este folositor o astfel de clasa.
După declarare se pot adăuga elemente în vector folosind funcția membru ca orice
membru cu .(punct)
for(int i=1;i<=10;i++)
v.push_back(i);
for(int i=0;i<v.size();i++)
cout<<v[i]<<" "; | cout<<v.at(i)<<" ";
pre.
1 2 3 4 5 6 7 8 9 10
Atenție Elementele sunt mereu indexate de la 0, astfel .size() va fi mereu o poziție invalidă,
ex. v={5,2,1}, v[0]=5,v[1]=2,v[2]=1. .size()=3, sunt 3 elemente însă de la 0-
2 sunt 3 elemente.
Ce este un Iterator?
Un iterator este un pointer la adresă specific fiecărui tip de container pentru
parcurgerea lui din adresă în adresă.
Cum funcționeaza?
Iteratorul se declară pentru fiecare tip de container și fiecare tip de date a
containerului. NU se pot folosi pentru alte containere de alt tip. După declarare se atribuie
Lectia 2. Vector in STL. Grafuri Neorientate.
Exemplu
vector<int> v;
vector<int>::iterator it;
for(it=v.begin();it!=v.end();it++)
cout<<*it<<" ";
Mai Mult
Se poate forta prin instructiunea auto să determine ce fel iterator este nevoie pentru
a parcurge containerul.
vector<int> v;
for(auto i:v)
cout<<i<<" ";
while(v.size()>5)
v.pop_back();
Constructor și alocare
Vectorul nu este obligatoriu să fie gol el poate să fie declarat cu un anumit număr de
poziții exact cum s-ar face la cei statici și să fie modificate pe parcurs. De asemenea
el are în componență un constructor care spune cu ce să umple fiecare poziție.
vector<int> v(100)
Vector cu 100 de elemente cu pozitii de la 0-99 cu valoarea 0 implicită.
vector<int> v(100,1)
Vector cu 100 de elemente cu pozitii de la 0-99 cu valoarea 1.
vector<int> v; // 0 elemente
v.push_back(5) // 1 element {5}
v.resize(2) // 2 elemente {5,0}
v.push_back(6), v.push_back(10) // 4 elemente {5,0,6,7}
v.resize(3) // 3 elemente {5,0,6}
v.resize(10) // 10 elemente {5,0,6,0,0,0,0,0,0,0}
Acest lucru se poate folosi in cazul vectorilor de fecventă.
Lectia 2. Vector in STL. Grafuri Neorientate.
vector<int> v;
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x;
if(x>=v.size())
v.resize(v.size())
v[x]=1;
}
Stergeri și inserare
Acest lucru se poate realiza în aproximativ o(n), limitata de modalitate de structurare
a vectorului folosind .erase(), .insert().
Grafuri neorientate.
Reprezentarea grafuri neorientate se face prin:
Matricea de adiacenta
Cod ce construieste si afiseaza matricea de adiacenta
#include <bits/stdc++.h>
using namespace std;
ifstream fin("adiacenta.in");
ofstream fout("adiacenta.out");
vector< vector<bool> >a(101,vector<bool>(101));
int main()
{
int n,m,i,j;
fin >> n >> m;
for(int p = 1 ;p <= m ; p++)
{
Lectia 2. Vector in STL. Grafuri Neorientate.
return 0;
}
Lista de adiacenta
#include < bits/stdc++.h>
using namespace std;
int n, m, a, b;
matrice G;
vector <int> vecini;
vector <int>::iterator it;
int main()
{
fin >> n;
while (fin >> a >> b)
G[a][b] = G[b][a] = true;
for (int i = 1; i <= n; i++)
{
vecini.clear();
for (int j = 1; j <= n; j++)
if (graf[i][j]) vecini.push_back(j);
fout << vecini.size() << " ";
for (it = vecini.begin(); it != vecini.end(); it++)
fout << *it << " ";
fout << "\n";
}
}
Parcurgerea grafurilor
Parcurgerea unui graf presupune examinarea sistematică a vârfurilor grafului, cu scopul
prelucrării informațiilor asociate vârfurilor.
Există două metode fundamentale de parcurgere a grafurilor:
parcurgerea în adâncime (Depth First Search - DFS)
parcurgerea în lățime (Breadth First Search - BFS).
se vizitează în ordine toți vecinii nevizitați ai vecinilor vârfului de start și așa mai departe, până la
epuizarea tuturor vârfurilor accesibile din vârful de start.
Exemplu:
while(!q.empty())
{
int k=q.front();
for(vector<int> :: iterator it=G[k].begin();it<G[k].end();it++)
if(viz[*it]==0)
{
viz[*it]=1;
t[*it]=k;
q.push(*it);
}
fout<<k<<" ";
q.pop();
}
}
Observații:
Parcurgerea în lățime are o proprietate remarcabilă: fiecare vârf este vizitat pe cel mai scurt
drum / lanț începând din vârful de start.
Complexitatea parcurgerii în lățime (BFS) în cazul reprezentării prin liste de adiacență este
𝑂(𝑛+𝑚) (în cazul reprezentării prin matrice de adiacență complexitatea este 𝑂(𝑛2)).
void citirem()
{
int x,y;
fin>>n>>m>>k;
while(fin>>x>>y)
A[x][y]=A[y][x]=1;
///A[x][y]=1; pt orientate
}
int coada[N],viz[N],ic,sfc;
void bfsr()
{
if(ic<=sfc)
{
for(int k=1;k<=n;k++)
if(A[coada[ic]][k]==1 && viz[k]==0)
{
sfc++;
coada[sfc]=k;
viz[k]=1;
}
ic++;
bfsr();
}
}
int main()
{
citirem();
ic=sfc=1;
Lectia 2. Vector in STL. Grafuri Neorientate.
coada[ic]=k;
viz[k]=1;
bfsr();
for(int i=1;i<=sfc;i++) fout<<coada[i]<<" ";
return 0;
}
Parcurgând graful din figură în adâncime considerând drept vârf de start vârful 3 putem obține
următoarea ordinea de vizitare a vârfurilor accesibile din nodul de start: 3,4,1,2,6,7,10,5,9
(Pentru această succesiune, ordinea de vizitare a vecinilor unui vârf este ordinea crescătoare a
numerelor lor)
Implementare:
Graful va fi reprezentat prin liste de adiacență (în una dintre cele trei variante). Pentru a reţine
care vârfuri au fost deja vizitate în timpul parcurgerii vom utiliza un vector 𝑣𝑖𝑧, cu 𝑛 componente din
mulţimea {0,1}, cu semnificaţia
𝑣𝑖𝑧[𝑖] = 1 dacă vârful 𝑖 a fost deja vizitat, respectiv 0, în caz contrar.
Observând că ordinea de parcurgere completă a vecinilor unui nod este ordinea inversă a
“atingerii” lor, abordarea cea mai simplă folosită pentru parcurgerea efectivă este cea recursivă.
#include <bits/stdc++.h>
using namespace std;
ifstream fin("dfs.in");
ofstream fout("dfs.out");
const int N=101;
bitset <N> viz;
vector <int> G[N];
inline void dfs(int x)
{
viz[x]=1;
fout<<x<<" ";
for(vector <int>::iterator it=G[x].begin();it!=G[x].end();it++)
Lectia 2. Vector in STL. Grafuri Neorientate.
{
if(viz[*it]==0)
{
dfs(*it);
}
}
}
int main()
{
int n,m,i,X,x,y;
fin>>n>>m>>X;
for(i=1;i<=m;i++)
{
fin>>x>>y;
G[x].push_back(y);
G[y].push_back(x);
}
for(i=1;i<=n;i++) sort(G[i].begin(),G[i].end());
dfs(X);
}
Observații:
Complexitatea parcurgerii în adâncime (DFS) în cazul reprezentării prin liste de adiacență este
𝑂(𝑛+𝑚) (în cazul reprezentării prin matrice de adiacență complexitatea este 𝑂(𝑛2)).
Implementare cu matrici de adiacenta
#include <fstream>
#define N 101
using namespace std;
ifstream fin("dfs.in");
ofstream fout("dfs.out");
int A[N][N],n,m,k,viz[N];
void citirem()
{
int x,y;
fin>>n>>m>>k;
while(fin>>x>>y)
A[x][y]=A[y][x]=1;
///A[x][y]=1; pt orientate
}
int main()
{
citirem();
dfs(k);
return 0;
}