Programmering nivå 2
Kap 2.3 – Sökning och sortering
Hitta, ordna och jämför data i listor med algoritmer och inbyggda metoder.
Mål med lektionen
När du har arbetat klart med denna lektion ska du:
- Förstå hur man söker efter ett värde i en lista.
- Känna till skillnaden mellan linjär och binär sökning.
- Känna till hur enkla sorteringsalgoritmer fungerar på en övergripande nivå.
- Kunna sortera listor med Pythons inbyggda metoder
sort()ochsorted(). - Förstå när olika typer av sökning och sortering är användbara, utan krav på att skriva egna sök- eller sorteringsalgoritmer från grunden.
Så här lär du dig bäst
Börja med att testa exempel med små listor och skriv gärna ut varje steg. Analysera hur många steg som krävs vid olika metoder. Målet är att känna till hur några vanliga sök- och sorteringsalgoritmer fungerar, men i egna program ska du i första hand använda Pythons inbyggda verktyg.
Sökning i listor
Sökning betyder att programmet letar efter ett värde i en samling data. Resultatet kan till exempel
vara indexet där värdet finns, eller -1 om värdet saknas.
Linjär sökning
Linjär sökning går igenom varje element i listan tills rätt värde hittas.
def linear_search(lst, target):
for i in range(len(lst)):
if lst[i] == target:
return i
return -1
names = ["Anna", "Bo", "Sara"]
print(linear_search(names, "Bo")) # 1
Fördel: fungerar alltid. Nackdel: kan bli långsam för stora listor.
Steg för steg: så fungerar koden
def linear_search(lst, target):skapar en funktion som tar emot två saker: en lista och värdet vi letar efter.for i in range(len(lst)):går igenom listans index från0till sista positionen. Om listan har tre element blir indexen0,1och2.if lst[i] == target:jämför elementet på den aktuella positionen med det vi söker efter.- Om värdet hittas körs
return i. Funktionen skickar då tillbaka indexet och avslutas direkt. - Om loopen hinner gå igenom hela listan utan träff körs
return -1. Det betyder att värdet inte finns i listan.
I exemplet är listan ["Anna", "Bo", "Sara"] och vi söker efter "Bo".
Programmet jämför först "Anna" på index 0. Det är fel. Sedan jämför det
"Bo" på index 1. Det är rätt, därför returnerar funktionen
1.
Interaktiv övning: linjär sökning
Testa hur linjär sökning jämför ett namn i taget tills målet hittas eller listan tar slut.
Prova till exempel att:
- söka efter
Booch se att sökningen stannar på index1 - söka efter
Saraoch se att fler jämförelser behövs - söka efter ett namn som inte finns
Binär sökning
Binär sökning är mycket snabbare, men kräver att listan är sorterad.
Viktigt: Binär sökning fungerar inte korrekt på en osorterad lista. Om listan inte är sorterad ska du antingen sortera den först eller använda linjär sökning.
def binary_search(lst, target):
low = 0
high = len(lst) - 1
while low <= high:
mid = (low + high) // 2
if lst[mid] == target:
return mid
elif lst[mid] < target:
low = mid + 1
else:
high = mid - 1
return -1
numbers = [3, 6, 9, 12, 15]
print(binary_search(numbers, 12)) # 3
Binär sökning halverar sökområdet varje gång, vilket gör metoden effektiv för stora sorterade listor.
Steg för steg: så fungerar binär sökning
- Listan måste först vara sorterad. I exemplet är listan
[3, 6, 9, 12, 15]. low = 0betyder att sökområdet börjar vid första indexet i listan.high = len(lst) - 1betyder att sökområdet slutar vid sista indexet.while low <= high:fortsätter söka så länge det finns ett möjligt område kvar.mid = (low + high) // 2räknar ut mittenpositionen i det aktuella sökområdet.- Om
lst[mid] == targetär värdet hittat och funktionen returnerar indexetmid. - Om
lst[mid] < targetligger målet till höger, eftersom listan är sorterad. Då flyttaslowtillmid + 1. - Annars ligger målet till vänster. Då flyttas
hightillmid - 1. - Om sökområdet tar slut utan träff returneras
-1.
I exemplet söker programmet efter 12. Först tittar det på mittenvärdet
9. Eftersom 12 är större än 9 behöver programmet bara söka i
högra delen av listan. Där hittar det 12 på index 3.
När ska du använda vilken sökning?
- Använd linjär sökning när listan är liten eller inte sorterad.
- Använd binär sökning när listan redan är sorterad och du behöver söka snabbt.
- I vanliga Pythonprogram använder du ofta inbyggda verktyg först, men egna algoritmer hjälper dig att förstå vad som händer bakom kulisserna.
Sortering av listor
Inbyggd sortering
Python gör det enkelt att sortera listor:
sort() och sorted() använder Pythons inbyggda sortering. Den är snabb,
stabil och optimerad för många vanliga typer av data. I riktiga program ska du därför nästan alltid
använda sort() eller sorted() i stället för att skriva en egen
sorteringsalgoritm från grunden. Läs mer i
Pythons Sorting HOWTO.
Skillnaden är att sort() ändrar listan direkt, medan sorted() skapar en ny
sorterad lista och lämnar originalet oförändrat.
numbers = [5, 3, 9, 1]
numbers.sort() # Ändrar listan direkt
print(numbers) # [1, 3, 5, 9]
names = ["Zara", "Adam", "Lilly"]
sorted_names = sorted(names) # Skapar ny lista
print(sorted_names)
Interaktiv övning: inbyggd sortering
Testa skillnaden mellan sort() och sorted(). Den ena ändrar listan
direkt, den andra skapar en ny sorterad lista.
Prova till exempel att:
- sortera namn som
Zara, Adam, Lilly - sortera tal som
5, 3, 9, 1 - växla mellan
sort()ochsorted()och jämför originalet
Egen sortering: bubble sort
Bubble sort används mest i undervisning. Den visar principen för jämförelse och byte, som återkommer i många sorteringsalgoritmer.
I riktiga projekt använder du nästan alltid Pythons inbyggda
sort() eller sorted(). Bubble sort är med här för att visa hur en
sorteringsalgoritm kan byggas upp steg för steg.
def bubble_sort(lst):
for i in range(len(lst)):
for j in range(0, len(lst) - i - 1):
if lst[j] > lst[j + 1]:
lst[j], lst[j + 1] = lst[j + 1], lst[j]
return lst
print(bubble_sort([9, 3, 7, 1])) # [1, 3, 7, 9]
Interaktiv övning: bubble sort
Skriv en lista med tal och kör sorteringen. Resultatet visar jämförelser och byten i ordning.
Prova till exempel att:
- använda
9, 3, 7, 1och följa varje byte - använda en nästan sorterad lista, till exempel
1, 3, 2, 4 - jämföra med Pythons inbyggda
sort()
Öva själv
Övning 1: Sortera användarnamn med sort()
Skapa en lista med minst fem användarnamn i blandad ordning. Skriv ut listan, sortera den med
sort() och skriv ut den igen.
Kontrollera programmet
- Den första utskriften ska visa den ursprungliga ordningen.
- Den andra utskriften ska visa namnen i sorterad ordning.
- Testa även med en lista som redan är sorterad.
Fundera: Vad har hänt med originallistan efter
sort()?
När du har försökt själv: visa lösningsförslaget till övning 1 på GitHub.
Övning 2: Skapa en sorterad kopia
Skapa en lista med tal i blandad ordning. Använd sorted() för att skapa en ny
sorterad lista. Skriv ut både originallistan och den sorterade listan.
Testa programmet med
[8, 2, 10, 4].- en lista som redan är sorterad.
- en lista som ligger i omvänd ordning.
Fundera: Varför kan sorted() passa bättre
än sort() när du behöver behålla den ursprungliga ordningen?
När du har försökt själv: visa lösningsförslaget till övning 2 på GitHub.
Övning 3: Linjär sökning efter ett namn
Skriv funktionen linear_search(names, target). Funktionen ska gå igenom listans
index och returnera indexet där namnet finns. Om namnet saknas ska funktionen returnera
-1.
Testa funktionen med
- ett namn som ligger först i listan.
- ett namn som ligger sist i listan.
- ett namn som inte finns.
Fundera: Varför ligger return -1 efter
loopen och inte inuti den?
När du har försökt själv: visa lösningsförslaget till övning 3 på GitHub.
Övning 4: Sortera före binär sökning
Använd funktionen binary_search() från kapitlets exempel. Skapa först en osorterad
lista med tal och gör en sorterad kopia med sorted(). Sök sedan efter ett tal i den
sorterade kopian och skriv ut det returnerade indexet.
Testa programmet med
- ett tal som ligger först i den sorterade listan.
- ett tal som ligger sist i den sorterade listan.
- ett tal som inte finns.
Fundera: Varför ska du inte skicka den osorterade
listan direkt till binary_search()?
När du har försökt själv: visa lösningsförslaget till övning 4 på GitHub.
Övning 5: Läs in, sortera och sök
Svårare övning: Här kombinerar du funktioner, listor, säker inmatning, sortering och linjär sökning.
Skapa ett program som frågar efter fem heltal och lägger dem i en lista. Felaktig inmatning ska
hanteras så att användaren får försöka igen. Skapa därefter en sorterad kopia med
sorted(), fråga vilket tal användaren vill söka efter och använd en funktion för
linjär sökning. Skriv ut det hittade indexet eller ett meddelande om talet saknas.
Testa programmet genom att
- skriva text när programmet frågar efter ett tal.
- söka efter ett tal som finns i listan.
- köra programmet igen och söka efter ett tal som saknas.
Fundera: Söker programmet i originallistan eller den sorterade kopian, och hur påverkar det indexet som returneras?
När du har försökt själv: visa lösningsförslaget till övning 5 på GitHub.
Övning 6: Meny för användarnamn
Svårare övning: Här kombinerar du en lista med funktioner, en meny, sortering och sökning.
Skapa ett menyprogram med alternativen 1. Lägg till användarnamn,
2. Visa sorterade användarnamn, 3. Sök efter användarnamn och
4. Avsluta. Namnen ska sparas i en lista. Den sorterade utskriften ska göras från
en kopia så att originallistan inte ändras. Sökningen ska använda en egen funktion för linjär
sökning och skriva ut namnets index i originallistan eller att namnet saknas.
Testa programmet genom att
- visa listan innan något namn har lagts till.
- lägga till minst tre namn i blandad ordning.
- visa namnen i sorterad ordning.
- söka efter ett namn som finns och ett som saknas.
- göra ett ogiltigt menyval och därefter avsluta.
Fundera: Varför används en sorterad kopia när namnen visas men originallistan när indexet söks?
När du har försökt själv: visa lösningsförslaget till övning 6 på GitHub.
Reflektion
- Vilka fördelar har inbyggda metoder jämfört med att skriva egna algoritmer?
- När är det värt att använda binär sökning istället för linjär?
- Hur kan sortering göra andra delar av ett program mer effektiva?