Lecție-punte: alegerea câmpurilor importante

Mediu~11 min4 pași

De ce contează?

Când completezi un formular, nu scrii toată povestea vieții — doar rubricile de care are nevoie cererea: nume, dată, semnătură. O structură bună e la fel: conține exact câmpurile cerute de problemă, nici mai multe, nici mai puține.

Pornește de la operații, nu de la date

Întrebarea greșită e „ce date am?". Întrebarea bună e „ce trebuie să fac cu ele?". Câmpurile structurii ies din operațiile cerute:

  • Ce citești din intrare? → câmpuri de bază.
  • După ce sortezi sau cauți? → cheia trebuie să fie un câmp.
  • Ce conține răspunsul? → câmpul (sau câmpurile) afișate la final.
Observația-cheie

O structură nu trebuie să fie o copie a întregului enunț. Câmpurile inutile ocupă memorie și încarcă codul. Ține doar ce folosesc efectiv operațiile.

Câmpul „ascuns" care salvează soluția: indicele inițial

Capcana clasică: sortezi un vector de structuri, apoi enunțul cere „pe ce poziție era inițial elementul X". După sortare, ordinea de citire s-a pierdut.

Soluția: adaugi un câmp care reține poziția de la citire, înainte de sortare:

struct Elem {
    int valoare;
    int indiceInitial;   // pozitia la citire, supravietuieste sortarii
};

// la citire:
for (int i = 0; i < n; i++) {
    cin >> v[i].valoare;
    v[i].indiceInitial = i;   // memorez ordinea originala
}

Acum, oricât ai sorta, v[i].indiceInitial îți spune de unde a venit fiecare element.

Câmpuri precalculate

Dacă o valoare derivată se folosește des — de exemplu o cheie de departajare compusă, un raport, o sumă — calculeaz-o o dată și ține-o într-un câmp. Eviți să o recalculezi la fiecare comparație din sort.

struct Produs {
    int pret, cantitate;
    long long total;   // pret * cantitate, precalculat
};

Comparatorul folosește direct a.total < b.total, fără înmulțiri repetate.

Observația-cheie

Echilibru: precalculează doar ce se folosește des și e scump de recalculat. Un câmp în plus pentru o valoare folosită o singură dată e balast — calculează-l pe loc.

Exemplu de gândire

Problemă: „n elevi cu nume și 3 note; afișează-i ordonați descrescător după medie, iar la egalitate în ordinea citirii".

Câmpurile care ies din cerință:

  • nume — apare în răspuns.
  • media — cheie de sortare; o precalculezi din cele 3 note (nu ții cele 3 note dacă nu-ți mai trebuie).
  • indiceInitial — pentru departajarea „în ordinea citirii".

Nimic în plus. Structura urmează fix operațiile.

Greșeli frecvente

Capcane la alegerea câmpurilor:

  • Pierzi ordinea inițială: sortezi fără un câmp indiceInitial și nu mai poți reconstrui pozițiile de la citire.
  • Câmpuri inutile: copiezi tot enunțul în structură; memorie și cod irosite.
  • Recalculezi în comparator o valoare scumpă: înmulțiri/medii repetate la fiecare comparație → sortare mai lentă. Precalculează-le într-un câmp.
  • Tip greșit pentru câmp precalculat: o sumă/produs ca int poate da overflow. Alege long long pentru câmpuri derivate mari.

Recapitulare

  • Câmpurile unei structuri ies din operațiile cerute (citire, sortare, răspuns), nu din tot enunțul.
  • Reține indiceInitial înainte de sortare dacă răspunsul depinde de ordinea originală.
  • Precalculează în câmpuri doar valorile derivate folosite des și scumpe de recalculat; atenție la tipul lor (overflow).

Întrebarea 1 / 3

Cum decizi ce câmpuri pui într-o structură?