Tidskomplexitet
↑Snabböversikt
Section titled “Snabböversikt”Tidskomplexitet beskriver hur mängden arbete förändras när indata blir större. Den anger inte exakt tid i sekunder. Om dubbelt så mycket indata ungefär fördubblar antalet iterationer använder vi ofta en linjär modell som O(n).
Vad räknas som en operation?
Section titled “Vad räknas som en operation?”Välj en operation som representerar arbetet, till exempel en jämförelse eller en läsning från en array. I modellen antas en enkel operation ha ungefär konstant kostnad. Hårdvara, cacheminne och språkets implementation kan ändå påverka verklig tid.
Tre exempel
Section titled “Tre exempel”Konstant
Section titled “Konstant”int first = values[0]; // O(1) om arrayen inte är tomint first = values.at(0); // O(1), throws if emptyEn läsning görs oavsett hur stor arrayen är.
Linjär
Section titled “Linjär”foreach (int value in values) Console.WriteLine(value); // O(n) totaltfor (int value : values) std::cout << value << '\n'; // O(n) totalAlla n värden besöks en gång.
Kvadratisk
Section titled “Kvadratisk”for (int i = 0; i < values.Length; i++) for (int j = 0; j < values.Length; j++) Compare(values[i], values[j]); // O(n²) totaltfor (std::size_t i = 0; i < values.size(); ++i) for (std::size_t j = 0; j < values.size(); ++j) compare(values[i], values[j]); // O(n^2)De nästlade looparna gör n × n jämförelser.
Analysera kod steg för steg
Section titled “Analysera kod steg för steg”- Bestäm vad
nbetyder. Är det antalet objekt, tecken eller något annat? - Välj en relevant operation. Räkna till exempel jämförelser i stället för källkodsrader.
- Räkna upprepningar. En loop över hela indata ger ofta
O(n). Halveras sökområdet blir det oftaO(log n). - Kombinera delarna. Efterföljande delar adderas, medan nästlade loopar ofta multipliceras.
- Behåll den dominerande termen.
3n² + 2n + 8kan beskrivas somO(n²).
Bästa, genomsnittliga och sämsta fall
Section titled “Bästa, genomsnittliga och sämsta fall”Linjär sökning hittar målet direkt om det ligger först. I sämsta fall granskar den hela listan. Om alla positioner är lika sannolika blir det genomsnittliga antalet jämförelser proportionellt mot n när målet finns.
Vad teorin inte säger
Section titled “Vad teorin inte säger”O(n log n) är inte automatiskt snabbare än O(n²) för varje liten lista. Minnesallokeringar, cachebeteende och konstanter spelar roll. Använd komplexitet för att förstå skalning och mätning för att jämföra verkliga implementationer.
Två loopar betyder inte alltid kvadratisk tid
Section titled “Två loopar betyder inte alltid kvadratisk tid”Två efterföljande loopar över n objekt ger n + n iterationer och är fortfarande linjära. Nästlade loopar är ofta kvadratiska, men bara när båda gör ungefär n iterationer. En triangulär nästlad loop gör cirka n(n-1)/2 iterationer och har fortfarande tillväxten Θ(n²).
Dold kostnad i hjälpfunktioner
Section titled “Dold kostnad i hjälpfunktioner”En ensam rad som collection.Contains(value) är inte automatiskt konstant. Det beror på samlingens typ. En lista kan behöva söka linjärt, medan en hashtabell normalt har annan förväntad kostnad. Studera metoden som anropas, inte bara looparna runt den.
Mäta på ett bra sätt
Section titled “Mäta på ett bra sätt”Testa flera indatastorlekar i en konsekvent miljö. Anteckna om data är slumpad, sorterad eller utformad för att ge dåliga fall. Ett snabbt test med få värden säger sällan mycket om långsiktig skalning.
