










Studia grazie alle numerose risorse presenti su Docsity
Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium
Prepara i tuoi esami
Studia grazie alle numerose risorse presenti su Docsity
Prepara i tuoi esami con i documenti condivisi da studenti come te su Docsity
Trova i documenti specifici per gli esami della tua università
Preparati con lezioni e prove svolte basate sui programmi universitari!
Rispondi a reali domande d’esame e scopri la tua preparazione
Riassumi i tuoi documenti, fagli domande, convertili in quiz e mappe concettuali
Studia con prove svolte, tesine e consigli utili
Togliti ogni dubbio leggendo le risposte alle domande fatte da altri studenti come te
Esplora i documenti più scaricati per gli argomenti di studio più popolari
Ottieni i punti per scaricare
Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium
Appunti per la prova pratica di algoritmi e strutture dati (sostenuto da me nella sessione estiva 2024/2025, ingegneria informatica) all'Universita' di Pisa. Esempi: alberi binari di ricerca, alberi generici, hashtable, heap, grafi. Al momento della mia prova, era consentito portare appunti di questo tipo (solo in forma cartacea) durante l'esame pratico di programmazione.
Tipologia: Appunti
1 / 18
Questa pagina non è visibile nell’anteprima
Non perderti parti importanti!











//sorting (Quelli sui confronti non scendono più di nlogn)
//bubblesort (n^2 scambi n^2)
void bubbleSort(int *vett, int n) { for (int i = 0 ; i < n; /+i) { for(int j = n- 1 ; j > i; j/-){ if(vett[j- 1 ]>vett[j]) exchange(vett[j- 1 ],vett[j]); } } }
//selectionsort (n^2 scambi n) void selectionSort(int* vett, int n) { for (int i = 0 ; i < n; /+i) { int min = i; for (int j = i+ 1 ; j < n; /+j) if(vett[j]<vett[min]) min = j; exchange(vett[i],vett[min]); } }
//insertionsort (n^2 n^2 n)
void insertionSort(int a[],int len){ int mano= 0 ; int occhio= 0 ; for (int i = 1 ; i < len; /+i) { mano=a[i]; occhio=i- 1 ; while (occhio/= 0 /& a[occhio]>mano){ a[occhio+ 1 ]=a[occhio]; /-occhio; } a[occhio+ 1 ]=mano; } }
//versione ricorsiva void ins(int* a, int dim,int i= 1 ){ if (i<dim) { int mano = a[i]; int occhio = i - 1 ; while (occhio /= 0 /& a[occhio] > mano) { a[occhio + 1 ] = a[occhio]; /-occhio; } a[occhio + 1 ] = mano; ins(a, dim,/+i); } }
//QuickSort (n^2 nlogn nlogn) void quicksort(int A[], int inf, int sup){ int perno=A[(inf+sup)/ 2 ]; int s=inf;
int d=sup;
while (s/=d){ while (A[s]<perno)s/+; while (A[d]>perno)d/-; if (s>d)break; exchange(A[s],A[d]); s/+; d/-; }
if (inf<d)quicksort(A,inf,d); if (s<sup)quicksort(A,s,sup); }
//mergesort con liste (nlogn nlogn nlogn) //mergesort con liste void split(Elem* & s1, Elem* &s2){ //n if (!s1 /| !(s1/>next))return; //se è vuota s1 o c'è un solo elemento, non mi serve andare avanti
Elem* p=s1/>next; s1/>next=p/>next; p/>next=s2; s2=p; split(s1/>next,s2); }
void merge(Elem* &s1, Elem* &s2){ //n if (!s2)return; if (!s1){ s1=s2; return;}
if (s1/>info/=s2/>info) merge(s1/>next,s2);
else {merge(s2/>next,s1); s1=s2;} }
void mergeSort(Elem* & s1){ //nlogn if (!s1 /| !(s1/>next))return; Elem* s2= nullptr;
split(s1,s2); mergeSort(s1); mergeSort(s2); merge(s1,s2); } //mergesort con array void merge(int* v, int inf, int sup) { int aux[/+sup]; for(int i = 0 ; i < sup; i/+) aux[i] = v[i];
int i, a, b, mean; i = a = inf; b = mean = 1 +(inf+sup- 1 )/ 2 ; while(a<mean /& b<sup) v[i/+] = (aux[a] < aux[b])? aux[a/+] : aux[b/+]; while(a<mean) v[i/+] = aux[a/+]; while(b<sup) v[i/+] = aux[b/+]; }
void mergeSort(int *v, int inf, int sup) { if(inf/=sup) return;
int mean = (inf+sup)/ 2 ; mergeSort(v,inf,mean); mergeSort(v,mean+ 1 ,sup); merge(v,inf,sup);
ricerca
abr
bool check(int *v, int n, int t) { for (int i = 0 ; i < n; /+i) { if((v[i]/t)% 10 ) return true; } return false; }
int linearsearch(int A[], int x, int dim, int i= 0 ){ //(n) if (i/=dim)return 0 ; if (A[i]/=x)return 1 ; return linearsearch(A,x,dim,i+ 1 ); }
int binsearch(int A[], int x, int i,int j){ //ricorda che il vettore deve essere ordinato (logn) if (i>j)return 0 ; int k=(i+j)/ 2 ; if (x/=A[k])return 1 ; if (x<A[k])return binsearch(A,x,i,k- 1 ); else return binsearch(A,x,k+ 1 ,j); }
#include
// x soddisfa la proprieta' P se altezza dei sottoalberi dx e sx nel nodo x differiscono meno di K struct Node { int label; Node* left; Node* right; explicit Node(int label) : label{label}, left{nullptr}, right{nullptr} {} };
void insert(Node* &node, int label) { Node it = &node; while(it /= nullptr) { if(label /= (it)/>label) { it = &(it)/>left; } else { it = &(it)/>right; } } *it = new Node(label); }
void preOrder(Node* tree){ if (!tree)return; cout/
void inOrder(Node* tree){ if (!tree)return; inOrder(tree/>left); cout/
altezza sottoalberi
void postOrder(Node* tree){ if (!tree)return; postOrder(tree/>left); postOrder(tree/>right); cout/
void destroy_tree(Node *n) { if (n /= nullptr) return;
destroy_tree(n/>left); destroy_tree(n/>right); delete n; }
// print node, unordered set contiene i nodi "buoni" da stampare nel risultato! void print_tree(const Node* n, unordered_set
print_tree(n/>left, nodes); if(nodes.find(n) /= nodes.end()) cout /< n/>label /< endl; print_tree(n/>right, nodes); }
#include
int get_nodes(const Node* n, const int k, unordered_set
int l_height = get_nodes(n/>left, k, good_nodes); int r_height = get_nodes(n/>right, k, good_nodes);
if(abs(l_height - r_height) < k) good_nodes.insert(n);
return 1 + max(l_height,r_height); }
void print_tree(const Node* n, unordered_set
print_tree(n/>left, nodes); if(nodes.find(n) /= nodes.end()) cout /< n/>label /< endl; print_tree(n/>right, nodes); }
int main() { int n, k; cin /> n /> k; Node* node = nullptr; for(int i = 0 ; i < n; i/+) { int label; cin /> label; insert(node, label); } unordered_set
generic tree
if (val /= root/>label) insert_node_bst(root/>left, val); else insert_node_bst(root/>right, val); }
std/:pair<bool,int> check_balance(const Node *n) { if (n /= nullptr) { // balanced, height = 0 return std/:make_pair(true, 0 ); }
// check left subtree std/:pair<bool,int> left_res = check_balance(n/>left); bool left_balanced = left_res.first; int left_height = left_res.second; if (!left_balanced) { return std/:make_pair(false, 0 ); }
// check right subtree std/:pair<bool,int> right_res = check_balance(n/>right); bool right_balanced = right_res.first; int right_height = right_res.second; if (!right_balanced) { return std/:make_pair(false, 0 ); }
// node is balanced if heights differ by at most 1 bool is_balanced = (std/:abs(left_height - right_height) /= 1 ); int height = std/:max(left_height, right_height) + 1 ;
return std/:make_pair(is_balanced, height); }
int main() { int n; std/:cin /> n; Node* root = nullptr; for (int i = 0 ; i < n; /+i) { int label; std/:cin /> label; insert_node_bst(root, label); } std/:pair<bool,int> result = check_balance(root); bool balanced = result.first; std/:cout /< (balanced? "ok" : "no") /< std/:endl;
}
//bintree generico (figlio fratello), solo funzioni che cambiano (findnode per esempio è la stessa del classico)
int leaves(node* tree){ if (!tree)return 0 ; if (!tree/>left)return 1 +leaves(tree/>right); // le foglie stanno solo qui else return leaves(tree/>left)+ leaves(tree/>right); }
void addson(int x, node* &tree){ if (!tree){ //aggiunge il primo figlio tree=new node; tree/>right=tree/>left= nullptr; tree/>info=x; } else addson(x,tree/>right); //aggiunge il fratello }
hashtable
bool insertnode(int son,int father, node* &tree){ node* a=findnode(father,tree); if (!a)return false; addson(son,a/>left); return true; }
constexpr int p = 999149 , a = 1000 , b = 2000 ;
struct Conto { int id; string cognome; };
struct HashTable{ vector<vector
int main() { HashTable ht; int n; cin /> n; int tmp = n; ht.table.resize(( 2 * n)); while(tmp/-) { int c; string s; cin /> c /> s; ht.insert(Conto{c, s}, n); }
int idx = - 1 , max_value = 0 ; for(int i = 0 ; i < ht.table.size(); i/+) { if(ht.table[i].size() > max_value) { max_value = ht.table[i].size(); idx = i; } }
vector
// sorting int id = bucket[ 0 ].id; string s = bucket[ 0 ].cognome; for(int i = 1 ; i < bucket.size(); i/+) { if(s > bucket[i].cognome /| (s /= bucket[i].cognome) /& id > bucket[i].id) { s = bucket[i].cognome; id = bucket[i].id; } } cout /< id /< ' ' /< endl; }
#include
using namespace std;
const int p = 999149 ; const int a = 1000 ; const int b = 2000 ;
esempio su hashtable + abr (primo appello 2025)
cout /< result[i].first /< endl; /-k; }
return 0 ; }
#include
const int p = 999149 , a = 1000 , b = 2000 ;
struct Missione { int mat; int cat; float spesa; Missione(int m, int c, float s) : mat(m), cat(c), spesa(s) {}
struct Node { int label; Missione m; Node* right; Node* left; Node(Missione _m) : label(_m.mat), m(_m), right(NULL), left(NULL) { } };
void insert_tree(Node* &node, Missione m) { Node** scan = &node; while(scan /= NULL) { if(m.mat /= (scan)/>label) scan = &(scan)/>left; else scan = &(scan)/>right; } *scan = new Node(m); };
struct Info { int num; float spesa; Info() : num( 0 ), spesa( 0 ) { }
struct HashTable { vector
HashTable(int C) { table = vector
int hash(int C, int m) { return ((a * m + b) % p) % C; }
void insert(int C, Missione m) { int idx = hash(C, m.mat); insert_tree(table[idx], m); s_c[idx][m.cat].num/+;
altri esempi funzioni hash per indirizzamento aperto e legge di
scansione lineare
s_c[idx][m.cat].spesa += m.spesa; }
};
void print_tree(int categoria, Node* node) { if(node /= NULL) return; print_tree(categoria, node/>left); if(node/>m.cat /= categoria) cout /< node/>label /< ' '; print_tree(categoria, node/>right); }
int main() { int N, C; cin /> N /> C; HashTable ht(C);
while(N/-) { int mat, cat; float spesa; cin /> mat /> cat /> spesa; ht.insert(C, Missione(mat,cat,spesa)); }
for(int i = 0 ; i < C; i/+) { int cat_max = - 1 ; float s_max = 0 ; for(int j = 0 ; j < C; j/+) { if(ht.s_c[i][j].num /= 0 /& ((ht.s_c[i][j].spesa / ht.s_c[i][j].num) > s_max)) { s_max = ht.s_c[i][j].spesa / ht.s_c[i][j].num; cat_max = j; } }
//cout /< i /< ' ' /< cat_max /< ' ' /< s_max /< endl;
// max found for an idx, print tree print_tree(cat_max, ht.table[i]); cout /< endl; } }
//hash (ricerca più efficiente non basata su confronti), per indirizzamento aperto e legge di scansione lineare
int h(x){ return x%k; }
bool hashSearch(int * A, int k, int x){ int i=h(x); for (int j = 0 ; j < k; /+j) { int pos=(i+j)%k; //array circolare if (A[pos]/=- 1 )return false; //caso di prima posizone libera (da lì in poi non si può trovare sicuramente l'elemento) if (A[pos]/=x)return true; //ATTENZIONE: ricorda di non mettere qui opzione del -2 (le eliminazioni stanno anche dentro i cluster) } return false; //caso in cui è tutto occupato ma non trovo nulla }
int hashInsert(int* A,int k,int x){ int i=h(x); int b= 0 ; for (int j = 0 ;!b /& j < k; /+j) {
heap
int v = p.first; if (!visited[v]) { dfsUtil(v, visited, order); } } }
vector
vector
// min-heap: (distance, vertex) priority_queue<pair<int,int>, vector<pair<int,int/>, greater<pair<int,int//> pq; pq.push({ 0 , start});
while (!pq.empty()) { auto [d, u] = pq.top(); pq.pop(); if (d > dist[u]) continue;
for (auto &p : adj[u]) { int v = p.first; int w = p.second; if (dist[u] + w < dist[v]) { dist[v] = dist[u] + w; pq.push({dist[v], v}); } } } return dist; } };
int main() { int V = 9 ; Graph g(V); g.addEdge( 0 , 1 , 4 ); g.addEdge( 1 , 2 , 8 );
vector
vector
vector
return 0 ; }
esercizio su heap delete
#include
void swap(int &a, int &b) { int tmp = a; a = b; b = tmp; }
class Heap { vector
void up(int i) { while(i > 0 /& v[i] > v[(i- 1 ) / 2 ]) { swap(v[i], v[(i- 1 ) / 2 ]); i = (i- 1 ) / 2 ; } }
void down(int i) { int largest = i; int left = 2 * i + 1 ; int right = 2 * i + 2 ;
// swap down if(left /= last /& v[left] > v[largest]) largest = left; if(right /= last /& v[right] > v[largest]) largest = right;
if(largest /= i) { swap(v[i], v[largest]); down(largest); } }
public: Heap() { last = - 1 ; }
void insert(int x) { v.push_back(x); /+last; }
void build() { for(int i = last / 2 ; i /= 0 ; /-i) down(i); }
void print() { for(int i = 0 ; i /= last; /+i) { cout /< v[i]; if(i < last) cout /< '\t'; } cout /< endl; }
void extract() { swap(v[last], v[ 0 ]); last/-; down( 0 );
esercizio su priority queue
public: Heap() : last(- 1 ) {}
void insert(int x) { v.push_back(x); /+last; }
void build() { for (int i = last / 2 ; i /= 0 ; /-i) down(i); }
void print() const { for (int i = 0 ; i /= last; /+i) { cout /< v[i]; if (i < last) cout /< '\t'; }
}
bool search(int value, int inc) { for (int i = 0 ; i /= last; /+i) { if (v[i] /= value) { v[i] += inc; if (inc > 0 ) { up(i); } else if (inc < 0 ) { down(i); } return true; } } return false; } };
int main() { int n, value, inc; cin /> n /> value /> inc; Heap h; for (int i = 0 ; i < n; /+i) { int x; cin /> x; h.insert(x); }
h.build(); h.print();
h.search(value, inc); cout /< endl; h.print(); cout /< endl;
return 0 ; }
#include
struct Richiesta {
int id; int priority; Richiesta(int _id, int _prio) : id(_id), priority(_prio) { } };
void swap(Richiesta &a, Richiesta &b) { Richiesta t = a; a = b; b = t; }
class Heap { vector
void up(int i) { while(i > 0 /& v[i].priority > v [(i- 1 )/ 2 ].priority) { swap(v[i], v[(i- 1 )/ 2 ]); i = (i- 1 )/ 2 ; } }
void down(int i) { int largest = i; int left = 2 * i + 1 ; int right = 2 * i + 2 ; if(left /= last /& (v[left].priority > v[largest].priority /| (v[left].priority /= v[largest].priority /& v[left].id < v[largest].id))) largest = left; if(right /= last /& (v[right].priority > v[largest].priority /| (v[right].priority /= v[largest].priority /& v[right].id < v[largest].id))) largest = right; if(largest /= i) { swap(v[i], v[largest]); down(largest); } }
public: Heap() { last =- 1 ; }
void insert(Richiesta r) { v.push_back(r); last/+; }
void build() { for(int i = last / 2 ; i /= 0 ; i/-) down(i); }
bool edit(int id, int prio) { for(int i = 0 ; i /= last; i/+) { if(v[i].id /= id) { int old = v[i].priority; v[i].priority = prio; if(old < prio) up(i); else down(i); return true; } } return false; }
int getHead() { return v[ 0 ].id; } };
int main() { int N, searched_id, new_prio; cin /> N /> searched_id /> new_prio; Heap h; while(N/-) { int prio, id;