PythonPython · Chapterبەش 11 · Lectureوانە 11.3
Bubble Sort, Insertion Sort and How Fast Sorting Isڕیزکردنی بڵقی، ڕیزکردن بە تێخستن و خێرایی ڕیزکردن
Why sorted data matters, bubble sort pass by pass with an early exit, insertion sort like cards in your hand, counting comparisons and swaps, best and worst cases, constant, linear and quadratic time, and why Python's own stable sort is the one to use in real programs.
بۆچی ڕیزکراو گرنگن، جار بە جار لەگەڵ وەستانی زوو، وەک کارت لە دەستدا، ژماردنی بەراورد و ئاڵوگۆڕ، و ، ، و ، هەروەها بۆچی خودی ئەوەیە کە لە ڕاستەقینەدا بەکار دێت.
What you will learnچی فێر دەبیت
- Explain why sorted data is worth the time that sorting costs.
- Trace bubble sort pass by pass, stop it early with a swapped flag and write it in Python.
- Trace and write insertion sort, also for names that arrive one at a time.
- Count comparisons and swaps, and tell the best case from the worst case.
- Recognise constant, linear and quadratic time from the loops, and explain why real programs call Python's sort().
- ڕوون بکەیتەوە بۆچی ڕیزکراو بەهای ئەو کاتە دەهێنن کە دەیبات.
- جار بە جار بەدواداچوون بۆ بکەیت، بە ئاڵای
swappedزوو بیوەستێنیت و بە بینووسیت. - بەدواداچوون بۆ بکەیت و بینووسیت، تەنانەت بۆ ئەو ناوانەی یەک یەک دێن.
- بەراورد و ئاڵوگۆڕەکان بژمێریت و لە جیا بکەیتەوە.
- ، و لە بناسیتەوە و ڕوون بکەیتەوە بۆچی ڕاستەقینە
sort()ـی بەکار دەهێنن.
Why sort?بۆچی ڕیزکردن؟
Sorting means putting items in an order: numbers from the smallest to the largest or the other way round, names in alphabetical order. Sorted data is much easier to search. A dictionary lists its words alphabetically, so you open it near the right page at once. An exam hall seats students by their exam number, so everyone finds a seat quickly. The Kurdistan football league table is sorted by points, so the leader is always on top.
واتە دانانی شتەکان بە ڕیزبەندییەک: ژمارەکان لە بچووکترینەوە بۆ گەورەترین یان بە پێچەوانەوە، ناوەکان بە ڕیزی ئەلفوبێ. گەڕان لە ڕیزکراودا زۆر ئاسانترە. فەرهەنگی وشە، وشەکانی بە ڕیزی ئەلفوبێ دادەنێت، بۆیە یەکسەر نزیک لاپەڕە دروستەکە دەیکەیتەوە. لە هۆڵی تاقیکردنەوەدا قوتابیان بە ژمارەی تاقیکردنەوەکەیان دادەنیشن، بۆیە هەموو کەس بە خێرایی کورسییەکەی دەدۆزێتەوە. خشتەی لیگی تۆپی پێی کوردستان بە خاڵ ڕیزکراوە، بۆیە یەکەمی لیگ هەمیشە لە سەرەوەیە.
Sorting costs time, so why bother? Because you sort once and then search many times. A shop that keeps its 5000 product codes sorted spends a little time sorting them in the evening, and then every code is found quickly all day. Many sorting algorithms exist. They all give the same sorted list, but some need far more work, so programmers compare them.
کاتی دەوێت، کەواتە بۆچی ئەم ماندووبوونە؟ چونکە یەک جار ڕیز دەکەیت و پاشان زۆر جار دەگەڕێیت. دوکانێک کە 5000 کۆدی کاڵاکانی بە ڕیزکراوی هەڵدەگرێت، ئێواران کەمێک کات بۆ سەرف دەکات و پاشان بە درێژایی ڕۆژ هەر کۆدێک بە خێرایی دەدۆزرێتەوە. زۆر هەن. هەموویان هەمان ڕیزکراو دەدەن، بەڵام هەندێکیان کاری زۆر زیاتریان دەوێت، بۆیە بەراوردیان دەکەن.
Think before you read on: where else does a computer sort for you?
پێش ئەوەی بەردەوام بیت بیر بکەرەوە: لە کوێی تر شتەکانت بۆ ڕیز دەکات؟
- Your phone contacts, from A to Z.
- An online shop's products, cheapest first.
- Files in a folder, newest first.
- Search results, the most useful first.
- A game's leaderboard, the highest score first.
- ناوەکانی ناو مۆبایلەکەت، بە ڕیزی ئەلفوبێ.
- کاڵاکانی دوکانێکی ئۆنلاین، هەرزانترین لە سەرەتادا.
- ناو ، نوێترین لە سەرەتادا.
- ئەنجامەکانی گەڕان، بەسوودترین لە سەرەتادا.
- خشتەی براوەکانی یارییەک، بەرزترین خاڵ لە سەرەتادا.
What you already knowئەوەی پێشتر دەیزانیت
You have already sorted in this course. In real programs you call sorted(values), which returns a new sorted list, or values.sort(), which sorts the list itself; reverse=True puts the largest first and key= sorts by a rule. See sort() and sorted(), largest first and sorting by a rule. You also traced one algorithm by hand: selection sort finds the smallest value of the unsorted part and swaps it to the front (selection sort). Tables are sorted row by row in Sorting the rows of a table.
پێشتر لەم کۆرسەدا ڕیزت کردووە. لە ڕاستەقینەدا sorted(values) بەکار دەهێنیت کە ڕیزکراوی نوێ دەگەڕێنێتەوە، یان values.sort() کە خودی ڕیز دەکات؛ reverse=True گەورەترین دەخاتە سەرەتا و key= بەپێی یاسایەک ڕیز دەکات. بڕوانە sort() و sorted()، گەورەترین لە سەرەتادا و ڕیزکردن بەپێی یاسایەک. هەروەها بەدواداچوونت بۆ بە دەست کردووە: بچووکترین بەشی ڕیزنەکراو دەدۆزێتەوە و دەیگوازێتەوە بۆ سەرەتا (ڕیزکردن بە هەڵبژاردن). ڕیزەکانی خشتە لە ڕیزکردنی ڕیزەکانی خشتەیەک ڕیز دەکرێن.
| Tool or algorithmئامراز یان | The ideaبیرۆکەکە | Whereلە کوێ |
|---|---|---|
sorted() / list.sort() | Python's own sort: use it in real programs خودی : لە ڕاستەقینەدا بەکاری بهێنە | Lists: sortingوانەی لیستەکان: ڕیزکردن |
| selection sort | pick the smallest, swap it to the frontبچووکترین هەڵبژێرە و بیگوازەرەوە بۆ پێشەوە | Selection sortهەمان وانە: ڕیزکردن بە هەڵبژاردن |
| bubble sort | swap neighbours that are in the wrong orderئاڵوگۆڕی دوو دراوسێ کە بە هەڵە ڕیز بوون | this lessonئەم وانەیە |
| insertion sort | insert each value into the sorted partهەر بخەرە ناو بەشە ڕیزکراوەکە | this lessonئەم وانەیە |
This lesson adds two algorithms and then asks the real question: how much work does each one do, and what happens when the list gets big?
ئەم وانەیە دوو زیاد دەکات و پاشان پرسیارە ڕاستەقینەکە دەکات: هەر یەکەیان چەند کار دەکات و کاتێک گەورە دەبێت چی ڕوو دەدات؟
Bubble sort: swap the neighboursڕیزکردنی بڵقی: ئاڵوگۆڕی دراوسێکان
Bubble sort walks along the list and looks at neighbours: positions 0 and 1, then 1 and 2, and so on. Whenever the left value is bigger than the right one, it swaps them. One walk from the start to the end is called a pass. During a pass the largest value is carried along to the end, like a bubble rising in a glass of water, which gives the algorithm its name.
بە دەڕوات و سەیری دراوسێکان دەکات: شوێنی 0 و 1، پاشان 1 و 2 و بەم شێوەیە. هەر کاتێک چەپ لە ڕاست گەورەتر بوو، ئاڵوگۆڕیان پێ دەکات. یەک ڕۆیشتن لە سەرەتاوە بۆ کۆتایی پێی دەوترێت جار (pass). لە هەر جارێکدا گەورەترین بەرەو کۆتایی دەبرێت، وەک بڵقێک کە لە پەرداخێک ئاودا بەرز دەبێتەوە، هەر بۆیە ناوی لێ نراوە.
A simple that walks through a list comparing neighbours and swapping every pair that is in the wrong order. After each pass the largest remaining value has "bubbled" to the end, so n values need at most n − 1 passes.
سادەی کە بە دەڕوات، هەر دوو دراوسێیەک بەراورد دەکات و هەر جووتێک بە هەڵە ڕیز بووبێت ئاڵوگۆڕیان پێ دەکات. دوای هەر جارێک گەورەترین لەوانەی ماون وەک بڵق دەگاتە کۆتایی، بۆیە n لانیزۆر n − 1 جاری پێویستە.


Bubble sort step by step: compare neighbours, swap them when they are in the wrong order, then the same in Python code.
هەنگاو بە هەنگاو: دوو دراوسێ بەراورد بکە و ئەگەر ڕیزبەندییان هەڵە بوو جێیان بگۆڕە؛ پاشان هەمان کار بە کۆدی .
Whole video (4:53): the idea of bubble sort and its Python code.
هەموو ڤیدیۆکە (4:53): بیرۆکەی و کۆدەکەی بە .
Bubble sort: swap the neighboursڕیزکردنی بڵقی: ئاڵوگۆڕی دراوسێکان
How many passes?چەند جار؟
After pass 1 the largest value is in its final place, so pass 2 can stop one pair earlier. After pass 2 the two largest values are in place, and so on. A list of values needs at most passes, and each pass makes one comparison fewer than the one before: , then , down to 1.
دوای جاری یەکەم گەورەترین لە شوێنی کۆتایی خۆیدایە، بۆیە جاری دووەم دەتوانێت یەک جووت زووتر بوەستێت. دوای جاری دووەم دوو گەورەترینەکە لە شوێنی خۆیانن و بەم شێوەیە. بە لانیزۆر پێویستی بە جار هەیە و هەر جارێک یەک بەراورد کەمتر لە جاری پێشوو دەکات: ، پاشان ، تا دەگاتە 1.
Students stand in a line for the class photo. The photographer walks from the left end to the right end and swaps any two neighbours where the left one is taller. After one walk the tallest student has reached the right end; after the next walk the second tallest is next to them.
قوتابیان بۆ وێنەی پۆلەکە لە ڕیزێکدا دەوەستن. وێنەگرەکە لە سەری چەپەوە بۆ سەری ڕاست دەڕوات و هەر دوو دراوسێیەک کە چەپەکەیان باڵا بەرزتر بێت جێگۆڕکێیان پێ دەکات. دوای یەک ڕۆیشتن باڵابەرزترین قوتابی گەیشتووەتە سەری ڕاست؛ دوای ڕۆیشتنی دووەم، دووەمین باڵابەرزترین لە تەنیشتیەوەیە.
Where the analogy stops workingسنووری ئەم نموونەیە
The photographer can see the whole line and could simply pick the tallest student. Bubble sort cannot: it only ever compares two neighbours.
وێنەگرەکە هەموو ڕیزەکە دەبینێت و دەتوانێت ڕاستەوخۆ باڵابەرزترین هەڵبژێرێت. ناتوانێت: هەمیشە تەنها دوو دراوسێ بەراورد دەکات.
Bubble sort: swap the neighboursڕیزکردنی بڵقی: ئاڵوگۆڕی دراوسێکان
A full trace, pass by passبەدواداچوونی تەواو، جار بە جار
Six January mornings in Penjwen gave these temperatures in °C: [4, -2, 9, -6, 1, 7]. The table follows bubble sort on them. Each pass compares the pairs in the second column from left to right.
شەش بەیانیی مانگی کانوونی دووەم لە پێنجوێن ئەم پلە گەرمییانەیان (°C) دا: [4, -2, 9, -6, 1, 7]. خشتەکە هەنگاوەکانی لەسەر ئەم پلە گەرمییانە پیشان دەدات. هەر جارێک جووتەکانی ستوونی دووەم لە چەپەوە بۆ ڕاست بەراورد دەکات.
| Passجار | Pairs comparedجووتە بەراوردکراوەکان | Swapsئاڵوگۆڕ | List after the pass دوای ئەو جارە |
|---|---|---|---|
| 1 | 4 | [-2, 4, -6, 1, 7, 9] | |
| 2 | 2 | [-2, -6, 1, 4, 7, 9] | |
| 3 | 1 | [-6, -2, 1, 4, 7, 9] | |
| 4 | 0 | [-6, -2, 1, 4, 7, 9] | |
| 5 | 0 | [-6, -2, 1, 4, 7, 9] |
Look at the passes: 5, 4, 3, 2 and 1 comparisons. The list is already sorted after pass 3, but this plain version of bubble sort cannot know that, so it still makes passes 4 and 5. The program below prints every comparison, so you can check the table.
سەیری جارەکان بکە: 5، 4، 3، 2 و 1 بەراورد. دوای جاری سێیەم ڕیزکراوە، بەڵام ئەم وەشانە سادەیەی ناتوانێت ئەوە بزانێت، بۆیە هێشتا جاری چوارەم و پێنجەم دەکات. خوارەوە هەموو بەراوردێک چاپ دەکات، بۆیە دەتوانیت خشتەکە بپشکنیت.
temps = [4, -2, 9, -6, 1, 7]
n = len(temps)
for i in range(n - 1):
print(f"pass {i + 1}")
for j in range(n - i - 1):
a, b = temps[j], temps[j + 1]
if a > b:
temps[j], temps[j + 1] = b, a
print(f" compare {a:>2} and {b:>2}: swap -> {temps}")
else:
print(f" compare {a:>2} and {b:>2}: keep -> {temps}")pass 1 compare 4 and -2: swap -> [-2, 4, 9, -6, 1, 7] compare 4 and 9: keep -> [-2, 4, 9, -6, 1, 7] compare 9 and -6: swap -> [-2, 4, -6, 9, 1, 7] compare 9 and 1: swap -> [-2, 4, -6, 1, 9, 7] compare 9 and 7: swap -> [-2, 4, -6, 1, 7, 9] pass 2 compare -2 and 4: keep -> [-2, 4, -6, 1, 7, 9] compare 4 and -6: swap -> [-2, -6, 4, 1, 7, 9] compare 4 and 1: swap -> [-2, -6, 1, 4, 7, 9] compare 4 and 7: keep -> [-2, -6, 1, 4, 7, 9] pass 3 compare -2 and -6: swap -> [-6, -2, 1, 4, 7, 9] compare -2 and 1: keep -> [-6, -2, 1, 4, 7, 9] compare 1 and 4: keep -> [-6, -2, 1, 4, 7, 9] pass 4 compare -6 and -2: keep -> [-6, -2, 1, 4, 7, 9] compare -2 and 1: keep -> [-6, -2, 1, 4, 7, 9] pass 5 compare -6 and -2: keep -> [-6, -2, 1, 4, 7, 9]
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 3
n - 1passes fornvalues.بۆ
n،n - 1جار.- Lineدێڕی 5
Pass
i + 1makesn - i - 1comparisons.جاری
i + 1،n - i - 1بەراورد دەکات.
Bubble sort: swap the neighboursڕیزکردنی بڵقی: ئاڵوگۆڕی دراوسێکان
Bubble sort in Pythonڕیزکردنی بڵقی لە Pythonـدا
Repeat for the passes .
بۆ جارەکانی دووبارە بکەرەوە.
In each pass, compare every neighbour pair from position 0 up to position and the one after it.
لە هەر جارێکدا هەموو جووتە دراوسێیەک بەراورد بکە، لە شوێنی 0 تا شوێنی لەگەڵ ئەوەی دوای خۆی.
If the left value is bigger than the right one, swap them.
ئەگەر چەپ لە ڕاست گەورەتر بوو، ئاڵوگۆڕیان پێ بکە.
The steps become two loops, one inside the other (nested loops): the outer loop counts the passes, the inner loop walks along the pairs.
هەنگاوەکان دەبنە دوو ، یەکێکیان لە ناو ئەوی تردا (خولە ناوەکییەکان): دەرەوە جارەکان دەژمێرێت و ناوەوە بە جووتەکاندا دەڕوات.
def bubble_sort(values):
n = len(values)
for i in range(n - 1): # passes 1 to n - 1
for j in range(n - i - 1): # each pass is one comparison shorter
if values[j] > values[j + 1]: # neighbours in the wrong order?
values[j], values[j + 1] = values[j + 1], values[j] # swap them
print(f"after pass {i + 1}: {values}")
temps = [4, -2, 9, -6, 1, 7] # morning temperatures in Penjwen, °C
bubble_sort(temps)
print("sorted:", temps)after pass 1: [-2, 4, -6, 1, 7, 9] after pass 2: [-2, -6, 1, 4, 7, 9] after pass 3: [-6, -2, 1, 4, 7, 9] after pass 4: [-6, -2, 1, 4, 7, 9] after pass 5: [-6, -2, 1, 4, 7, 9] sorted: [-6, -2, 1, 4, 7, 9]
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 3
The outer loop: one turn per pass.
دەرەوە: هەر سووڕێک یەک جارە.
- Lineدێڕی 4
The last
ivalues are already in place, so the inner loop stops earlier each pass.دوایین
iپێشتر لە شوێنی خۆیانن، بۆیە ناوەوە لە هەر جارێکدا زووتر دەوەستێت.- Lineدێڕی 6
Python swaps two values in one line; other languages need a temporary variable.
دوو لە یەک دێڕدا ئاڵوگۆڕ دەکات؛ زمانەکانی تر پێویستیان بە کاتی هەیە.
To put the largest first, change one character: swap when the left value is smaller than the right one.
بۆ ئەوەی گەورەترین لە سەرەتا بێت، تەنها یەک بگۆڕە: کاتێک چەپ لە ڕاست بچووکتر بوو ئاڵوگۆڕیان پێ بکە.
def bubble_sort_desc(values):
n = len(values)
for i in range(n - 1):
for j in range(n - i - 1):
if values[j] < values[j + 1]: # the only change: < instead of >
values[j], values[j + 1] = values[j + 1], values[j]
temps = [4, -2, 9, -6, 1, 7]
bubble_sort_desc(temps)
print(temps)[9, 7, 4, 1, -2, -6]
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 5
<instead of>: smaller values bubble to the end.<لەبری>: بچووکترینەکان دەچنە کۆتایی.
Stop early: the swapped flagزوو وەستان: ئاڵای swapped
In the trace the list was sorted after pass 3, yet passes 4 and 5 still ran. A pass that makes no swap at all proves that the list is sorted: every pair of neighbours is already in order. So keep a flag. Set swapped = False at the start of each pass, set it to True whenever you swap, and leave the outer loop with break if it is still False at the end of the pass (break).
لە بەدواداچوونەکەدا دوای جاری سێیەم ڕیزکرابوو، بەڵام هێشتا جاری چوارەم و پێنجەم کران. جارێک کە هیچ ئاڵوگۆڕێک نەکات دەیسەلمێنێت کە ڕیزکراوە: هەموو جووتە دراوسێیەک پێشتر بە ڕیزن. کەواتە ئاڵایەک هەڵبگرە. لە سەرەتای هەر جارێکدا swapped = False دابنێ، هەر کاتێک ئاڵوگۆڕت کرد بیکە بە True و ئەگەر لە کۆتایی جارەکەدا هێشتا False بوو، بە break دەرەوە جێبهێڵە (break).
def bubble_sort(values):
n = len(values)
for i in range(n - 1):
swapped = False # no swap in this pass yet
for j in range(n - i - 1):
if values[j] > values[j + 1]:
values[j], values[j + 1] = values[j + 1], values[j]
swapped = True
print(f"pass {i + 1}: {values} swapped={swapped}")
if not swapped: # a pass with no swap: already sorted
break
bubble_sort([4, -2, 9, -6, 1, 7])
print("---")
bubble_sort([-6, -2, 1, 4, 7, 9]) # already sortedpass 1: [-2, 4, -6, 1, 7, 9] swapped=True pass 2: [-2, -6, 1, 4, 7, 9] swapped=True pass 3: [-6, -2, 1, 4, 7, 9] swapped=True pass 4: [-6, -2, 1, 4, 7, 9] swapped=False --- pass 1: [-6, -2, 1, 4, 7, 9] swapped=False
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 4
No swap yet in this pass.
هێشتا لەم جارەدا هیچ ئاڵوگۆڕێک نەکراوە.
- Lineدێڕی 8
Remember that this pass changed something.
لەبیر بێت کە ئەم جارە شتێکی گۆڕی.
- Lineدێڕی 10-11
A pass without a swap: the list is sorted, stop.
جارێک بەبێ ئاڵوگۆڕ: ڕیزکراوە، بوەستە.
On the temperatures the flag saves only pass 5: 14 comparisons instead of 15. Pass 4 is still needed, because it is the pass that finds no swap. On a list that is already sorted the saving is large: one pass of 5 comparisons instead of 15 comparisons in 5 passes.
لەسەر پلە گەرمییەکان ئاڵاکە تەنها جاری پێنجەم پاشەکەوت دەکات: 14 بەراورد لەبری 15. جاری چوارەم هێشتا پێویستە، چونکە ئەو جارەیە کە هیچ ئاڵوگۆڕێک نادۆزێتەوە. لەسەر کە پێشتر ڕیزکراوە پاشەکەوتەکە گەورەیە: یەک جار بە 5 بەراورد لەبری 15 بەراورد لە 5 جاردا.
Insertion sort: cards in your handڕیزکردن بە تێخستن: کارت لە دەستتدا
Think of how you sort playing cards. You pick up one card at a time. The cards already in your hand are in order, and each new card slides left past the bigger ones until it drops into its place. Insertion sort does exactly this. The left part of the list is the sorted hand. Each pass takes the next value, the current value, shifts every bigger value of the sorted part one place to the right, and drops the current value into the gap.
بیر لەوە بکەرەوە چۆن کارتی یاری ڕیز دەکەیت. هەر جارە یەک کارت هەڵدەگریت. ئەو کارتانەی پێشتر لە دەستتدان بە ڕیزن و هەر کارتێکی نوێ بەرەو چەپ بە تەنیشت کارتە گەورەترەکاندا دەخزێت تا لە شوێنی خۆیدا دادەنرێت. ڕێک ئەمە دەکات. بەشی چەپی دەستە ڕیزکراوەکەیە. هەر جارێک داهاتوو هەڵدەگرێت، واتە ئێستا، هەموو گەورەتری بەشە ڕیزکراوەکە یەک شوێن بەرەو ڕاست دەجووڵێنێت و ئێستا دەخاتە ناو بۆشاییەکە.
A simple that works like sorting playing cards in your hand: take the next value, shift the bigger values of the sorted part one place right, and drop the value into the gap. It is fast on lists that are already almost sorted.
سادەی کە وەک ڕیزکردنی کارتی یاری لە دەستدا کار دەکات: داهاتوو هەڵدەگریت، گەورەترەکانی بەشی ڕیزکراو یەک شوێن بەرەو ڕاست دەجووڵێنیت و لە بۆشاییەکەدا دادەنێیت. لەسەر کە نزیکەی ڕیزکراون خێرایە.


In the school library the books on a shelf are in alphabetical order. To put a returned book back, the librarian starts at the right end, slides each book that should come after it one place along, and puts the returned book into the gap that opens.
لە کتێبخانەی قوتابخانەدا کتێبەکانی سەر ڕەفێک بە ڕیزی ئەلفوبێن. بۆ گەڕاندنەوەی کتێبێکی گەڕاوە، کتێبدارەکە لە سەری ڕاستەوە دەست پێ دەکات، هەر کتێبێک کە دەبێت لە دوای ئەو بێت یەک شوێن دەخزێنێت و کتێبە گەڕاوەکە دەخاتە ئەو بۆشاییەی دروست دەبێت.
Where the analogy stops workingسنووری ئەم نموونەیە
The librarian can see at a glance where the book belongs. The algorithm cannot: it compares one value at a time, from right to left.
کتێبدارەکە بە یەک سەیرکردن دەزانێت کتێبەکە دەچێتە کوێ. ناتوانێت: هەر جارە یەک بەراورد دەکات، لە ڕاستەوە بۆ چەپ.
Insertion sort: each new value slides left past the bigger ones until it reaches its place, then the same in Python.
: هەر نوێ بەرەو چەپ دەخزێت و بە لای گەورەترەکاندا تێدەپەڕێت تا دەگاتە شوێنی خۆی؛ پاشان هەمان کار بە .
Whole video (5:50): the algorithm (0:14) and the Python code (1:45).
هەموو ڤیدیۆکە (5:50): (0:14) و کۆدی (1:45).
Insertion sort: cards in your handڕیزکردن بە تێخستن: کارت لە دەستتدا
A full traceبەدواداچوونی تەواو
The same temperatures, [4, -2, 9, -6, 1, 7], sorted by insertion sort. Pass 1 starts with the second value, because one value on its own is already a sorted hand.
هەمان پلە گەرمییەکان، [4, -2, 9, -6, 1, 7]، بە ڕیز دەکرێن. جاری یەکەم بە دووەم دەست پێ دەکات، چونکە یەک بە تەنها خۆی دەستێکی ڕیزکراوە.
| Passجار | Current value ئێستا | Moved one place rightبەرەو ڕاست جووڵێنران | Comparisonsبەراورد | List after the pass دوای ئەو جارە |
|---|---|---|---|---|
| 1 | 4 | 1 | [-2, 4, 9, -6, 1, 7] | |
| 2 | 9 | — | 1 | [-2, 4, 9, -6, 1, 7] |
| 3 | 3 | [-6, -2, 4, 9, 1, 7] | ||
| 4 | 1 | 3 | [-6, -2, 1, 4, 9, 7] | |
| 5 | 7 | 9 | 2 | [-6, -2, 1, 4, 7, 9] |
Pass 2 is cheap: 9 is bigger than the last card of the sorted part, so one comparison shows that it is already in place. Pass 4 stops at , because is not bigger than 1: everything further left is even smaller.
جاری دووەم هەرزانە: 9 لە دوایین کارتی بەشە ڕیزکراوەکە گەورەترە، بۆیە یەک بەراورد پیشانی دەدات کە پێشتر لە شوێنی خۆیدایە. جاری چوارەم لە دا دەوەستێت، چونکە لە 1 گەورەتر نییە: هەموو ئەوانەی زیاتر لە چەپن لەوەش بچووکترن.
Insertion sort: cards in your handڕیزکردن بە تێخستن: کارت لە دەستتدا
Insertion sort in Pythonڕیزکردن بە تێخستن لە Pythonـدا
For each position from 1 to , save the value there as
current.بۆ هەر شوێنێکی لە 1 تا ، ئەو شوێنە وەک
currentهەڵبگرە.Start with , the last position of the sorted part.
بە دەست پێ بکە، دوایین شوێنی بەشە ڕیزکراوەکە.
While is still a position () and the value at is bigger than
current: copy it one place right, to , and move one place left.تا هێشتا شوێنێکە () و شوێنی لە
currentگەورەترە: یەک شوێن بەرەو ڕاست کۆپیی بکە (بۆ ) و یەک شوێن بەرەو چەپ ببە.Put
currentinto the gap at .currentبخەرە ناو بۆشاییەکەی شوێنی .
def insertion_sort(values):
for i in range(1, len(values)): # values[0] alone is already "sorted"
current = values[i] # the card we pick up
j = i - 1
while j >= 0 and values[j] > current:
values[j + 1] = values[j] # shift the bigger value one place right
j -= 1
values[j + 1] = current # drop the card into the gap
print(f"after pass {i}: {values}")
temps = [4, -2, 9, -6, 1, 7]
insertion_sort(temps)
print("sorted:", temps)after pass 1: [-2, 4, 9, -6, 1, 7] after pass 2: [-2, 4, 9, -6, 1, 7] after pass 3: [-6, -2, 4, 9, 1, 7] after pass 4: [-6, -2, 1, 4, 9, 7] after pass 5: [-6, -2, 1, 4, 7, 9] sorted: [-6, -2, 1, 4, 7, 9]
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 2
Start at 1: the first value alone is a sorted part.
لە 1ەوە دەست پێ بکە: یەکەم بە تەنها بەشێکی ڕیزکراوە.
- Lineدێڕی 5
j >= 0stops the loop at the left end. Without it,jwould become andvalues[-1]would read the last element (negative indexes). Because it comes first,values[j]is only read for a real position.j >= 0لە سەری چەپدا دەوەستێنێت. بەبێ ئەو،jدەبووە وvalues[-1]دوایین دەخوێندەوە (ئیندێکسە سالبەکان). چونکە یەکەمە،values[j]تەنها بۆ شوێنێکی ڕاستەقینە دەخوێنرێتەوە.- Lineدێڕی 6
A shift copies; nothing is lost, because
currentkeeps the picked value.جووڵاندن کۆپی دەکات؛ هیچ شتێک ون نابێت، چونکە
currentئەو هەڵگیراوە دەپارێزێت.- Lineدێڕی 8
j + 1is the gap: one place right of the last value that was not bigger.j + 1بۆشاییەکەیە: یەک شوێن لە ڕاستی دوایین کە گەورەتر نەبوو.
For the largest first, again flip one comparison: shift while the value on the left is smaller than current.
بۆ گەورەترین لە سەرەتادا، دیسان یەک بەراورد پێچەوانە بکەرەوە: تا لای چەپ لە current بچووکتر بێت بیجووڵێنە.
def insertion_sort_desc(values):
for i in range(1, len(values)):
current = values[i]
j = i - 1
while j >= 0 and values[j] < current: # the only change: < instead of >
values[j + 1] = values[j]
j -= 1
values[j + 1] = current
temps = [4, -2, 9, -6, 1, 7]
insertion_sort_desc(temps)
print(temps)[9, 7, 4, 1, -2, -6]
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 5
<instead of>.<لەبری>.
Insertion sort: cards in your handڕیزکردن بە تێخستن: کارت لە دەستتدا
Sorting while the names arriveڕیزکردن لە کاتی هاتنی ناوەکاندا
At registration, students' names arrive one at a time, and the list must stay in alphabetical order the whole time. Which technique fits? Insertion sort: each new name is inserted into a list that is already sorted, which is exactly one pass of insertion sort. Insertion sort can sort a list while it is still arriving, something bubble and selection sort cannot do.
لە کاتی ناونووسیندا ناوی قوتابیان یەک یەک دێن و دەبێت هەمیشە بە ڕیزی ئەلفوبێ بمێنێتەوە. کام ڕێگا گونجاوە؟ : هەر ناوێکی نوێ دەخرێتە ناو کە پێشتر ڕیزکراوە، کە ڕێک یەک جاری . دەتوانێت ڕیز بکات لە کاتێکدا هێشتا دێت، شتێک کە و ناتوانن.
def insert_in_order(names, new_name):
"""Put new_name into the already sorted list names, at its alphabetical place."""
names.append(new_name) # make room at the end
j = len(names) - 2
while j >= 0 and names[j].lower() > new_name.lower():
names[j + 1] = names[j] # shift a later name one place right
j -= 1
names[j + 1] = new_name
students = []
while True:
name = input("Name (empty to stop): ").strip()
if name == "":
break
insert_in_order(students, name)
print(" list now:", students)
print("Final list:", students)Name (empty to stop): Shilan list now: ['Shilan'] Name (empty to stop): Aram list now: ['Aram', 'Shilan'] Name (empty to stop): Rezan list now: ['Aram', 'Rezan', 'Shilan'] Name (empty to stop): Dilan list now: ['Aram', 'Dilan', 'Rezan', 'Shilan'] Name (empty to stop): Karwan list now: ['Aram', 'Dilan', 'Karwan', 'Rezan', 'Shilan'] Name (empty to stop): Final list: ['Aram', 'Dilan', 'Karwan', 'Rezan', 'Shilan']
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 3
Add the new name at the end to make room.
ناوە نوێیەکە لە کۆتاییدا زیاد بکە بۆ ئەوەی شوێن دروست بێت.
- Lineدێڕی 5
.lower()compares without caring about capital letters..lower()بەبێ گرنگیدان بە پیتی گەورە بەراورد دەکات.- Lineدێڕی 16
insert_in_order()is called once for every name typed.insert_in_order()بۆ هەر ناوێک کە دەنووسرێت یەک جار بانگ دەکرێت.
Counting the workژماردنی کارەکە
Which algorithm does the least work? A stopwatch depends on the computer, so we count instead: the number of comparisons, and the number of swaps (in insertion sort, shifts). The program adds counters to all three algorithms and runs them on the same three lists. Each function sorts a copy, so every algorithm gets exactly the same input.
کام کەمترین کار دەکات؟ پێوانی کات بە کاتژمێر پشت بە دەبەستێت، بۆیە لەبری ئەوە دەژمێرین: ژمارەی بەراوردەکان و ژمارەی ئاڵوگۆڕەکان (لە ، جووڵاندنەکان). بۆ هەر سێ زیاد دەکات و لەسەر هەمان سێ کاریان پێ دەکات. هەر کۆپییەک ڕیز دەکات، بۆیە هەموو ڕێک هەمان وەردەگرێت.
def bubble_count(values):
values = values[:] # work on a copy
comparisons = swaps = 0
n = len(values)
for i in range(n - 1):
swapped = False
for j in range(n - i - 1):
comparisons += 1
if values[j] > values[j + 1]:
values[j], values[j + 1] = values[j + 1], values[j]
swaps += 1
swapped = True
if not swapped:
break
return comparisons, swaps
def selection_count(values):
values = values[:]
comparisons = swaps = 0
n = len(values)
for start in range(n - 1):
smallest = start
for j in range(start + 1, n):
comparisons += 1
if values[j] < values[smallest]:
smallest = j
if smallest != start: # count only swaps that move values
values[start], values[smallest] = values[smallest], values[start]
swaps += 1
return comparisons, swaps
def insertion_count(values):
values = values[:]
comparisons = shifts = 0
for i in range(1, len(values)):
current = values[i]
j = i - 1
while j >= 0:
comparisons += 1
if values[j] > current:
values[j + 1] = values[j]
shifts += 1
j -= 1
else:
break
values[j + 1] = current
return comparisons, shifts
lists = {
"temperatures": [4, -2, 9, -6, 1, 7],
"already sorted": [-6, -2, 1, 4, 7, 9],
"reversed": [9, 7, 4, 1, -2, -6],
}
print("comparisons / swaps (insertion sort: shifts)")
print(f"{'list':15} {'bubble':>9} {'selection':>10} {'insertion':>10}")
for name, data in lists.items():
b = bubble_count(data)
s = selection_count(data)
k = insertion_count(data)
print(f"{name:15} {b[0]:>4} / {b[1]:<2} {s[0]:>5} / {s[1]:<2} {k[0]:>5} / {k[1]:<2}")comparisons / swaps (insertion sort: shifts) list bubble selection insertion temperatures 14 / 7 15 / 3 10 / 7 already sorted 5 / 0 15 / 0 5 / 0 reversed 15 / 15 15 / 3 15 / 15
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 2
Work on a copy, so the caller's list is not changed.
لەسەر کۆپییەک کار بکە، بۆ ئەوەی نەگۆڕێت.
- Lineدێڕی 8
Count every comparison, whether it swaps or not.
هەموو بەراوردێک بژمێرە، چ ئاڵوگۆڕ بکات چ نا.
- Lineدێڕی 28-30
Selection sort: count only the swaps that really move two values.
: تەنها ئەو ئاڵوگۆڕانە بژمێرە کە بە ڕاستی دوو دەجووڵێنن.
- Lineدێڕی 40-47
Insertion sort: one comparison per turn of the inner loop;
breakwhen the place is found.: لە هەر سووڕێکی ناوەوەدا یەک بەراورد؛
breakکاتێک شوێنەکە دۆزرایەوە.
Bubble sort's 7 swaps and insertion sort's 7 shifts are no accident. Each swap or shift fixes exactly one pair of values that stood in the wrong order, and the temperatures have exactly 7 such pairs. Selection sort always makes 15 comparisons, but at most one swap per pass, which helps when moving data is slow.
7 ئاڵوگۆڕی و 7 جووڵاندنی ڕێکەوت نین. هەر ئاڵوگۆڕ یان جووڵاندنێک ڕێک یەک جووت چاک دەکات کە بە ڕیزبەندیی هەڵە وەستابوون و پلە گەرمییەکان ڕێک 7 جووتی وایان هەیە. هەمیشە 15 بەراورد دەکات، بەڵام لە هەر جارێکدا لانیزۆر یەک ئاڵوگۆڕ، کە یارمەتیدەرە کاتێک جووڵاندنی هێواشە.
Best case and worst caseباشترین بار و خراپترین بار
The same algorithm can be quick or slow, depending on the input. The best case is the input of size that needs the least work; the worst case is the one that needs the most (worst and average case). For sorting, the best case is a list that is already sorted, and the worst case is a list in reverse order. The counting program above gives, for six values:
هەمان دەکرێت خێرا یان هێواش بێت، بەپێی . لە (بە قەبارەی ) کەمترین کاری دەوێت؛ لە زۆرترین کاری دەوێت (خراپترین بار و باری مامناوەند). بۆ ، کە پێشتر ڕیزکراوە و بە ڕیزبەندیی پێچەوانە. ژماردنی سەرەوە بۆ شەش ئەمە دەدات:
| Input () () | Bubble sort with flag بە ئاڵاوە | Selection sort | Insertion sort |
|---|---|---|---|
| already sortedپێشتر ڕیزکراو | 5 / 0 | 15 / 0 | 5 / 0 |
| reversedپێچەوانە | 15 / 15 | 15 / 3 | 15 / 15 |
In general, for values: in the best case bubble sort with the flag and insertion sort make only comparisons. In the worst case every pass compares as much as it can:
بە گشتی، بۆ : لە بە ئاڵاوە و تەنها بەراورد دەکەن. لە هەر جارێک هەموو ئەو بەراوردانە دەکات کە دەتوانێت:
comparisons in total. Selection sort makes this number every time, even on a sorted list, because it never notices that a list is already sorted.
بەراورد بە گشتی. هەموو جارێک ئەم ژمارەیە بەراورد دەکات، تەنانەت لەسەر ڕیزکراویش، چونکە هەرگیز تێبینی ناکات کە پێشتر ڕیزکراوە.
Best case and worst caseباشترین بار و خراپترین بار
The same count on 1,000 numbersهەمان ژماردن لەسەر ژمارە
With six values every algorithm finishes at once. Count again with 1,000 numbers, in random order, already sorted and reversed, and the difference between the best and the worst case becomes huge:
لەگەڵ شەش هەموو یەکسەر تەواو دەبێت. دووبارە لەگەڵ ژمارە بژمێرە، بە ڕیزبەندیی هەڕەمەکی، پێشتر ڕیزکراو و پێچەوانە، ئەوکاتە جیاوازیی نێوان و زۆر گەورە دەبێت:
| 1,000 numbers1000 ژمارە | Bubble sort with flag بە ئاڵاوە | Selection sort | Insertion sort |
|---|---|---|---|
| random orderڕیزبەندیی هەڕەمەکی | 499,455 | 499,500 | 250,067 |
| already sortedپێشتر ڕیزکراو | 999 | 499,500 | 999 |
| reversedپێچەوانە | 499,500 | 499,500 | 499,500 |
How fast is fast? Constant, linear and quadratic timeخێرا چەندە خێرایە؟ کاتی نەگۆڕ، کاتی هێڵی و کاتی پلەدوو
Time complexity describes how the work of an algorithm grows when its input grows. With six temperatures every algorithm finishes at once. With a million records, the difference decides whether a program answers in a second or in hours, so programmers think about it before they use an algorithm on real data. Three rules of thumb cover most beginner programs:
باس لەوە دەکات کە کاری چۆن گەورە دەبێت کاتێک گەورە دەبێت. لەگەڵ شەش پلەی گەرمیدا هەموو یەکسەر تەواو دەبێت. لەگەڵ ملیۆنێک ، جیاوازییەکە بڕیار دەدات کە لە چرکەیەکدا وەڵام دەداتەوە یان لە چەند کاتژمێرێکدا، بۆیە پێش بەکارهێنانی لەسەر ڕاستەقینە بیری لێ دەکەنەوە. سێ یاسای سادە زۆربەی سەرەتایی دەگرنەوە:
| Shape of the codeشێوەی کۆدەکە | Nameناو | Work for itemsکار بۆ | Exampleنموونە |
|---|---|---|---|
| no loopبێ | constant time | the same for any بۆ هەر ـێک هەمانە | first = values[0] |
| one loop over the itemsیەک بەسەر | linear time | about نزیکەی | max(values) looks at every item oncemax(values) یەک جار سەیری هەموو دەکات |
| a loop inside a loop over them لە ناو بەسەریاندا | quadratic time | about نزیکەی | bubble, selection and insertion sort، و |
| one loop, then a nested loopیەک ، پاشان | the nested loop decides: quadratic بڕیار دەدات: پلەدوو | , about ، نزیکەی | print a list, then bubble-sort itچاپکردنی ، پاشان لەسەری |
Big-O in short: drop constants, keep the fastest-growing term, and use the worst case, with constant, linear and quadratic examples.
بە کورتی: ژمارە جێگیرەکان لابدە، تەنها ئەو بەشەی خێراتر گەورە دەبێت بهێڵەرەوە و حساب بۆ بکە، لەگەڵ نموونەی کاتی جێگیر، هێڵی و دووجایی.
Whole video (5:12): constant time (1:54), linear time (2:36), quadratic time (3:22) and the worst case (4:10).
هەموو ڤیدیۆکە (5:12): (1:54)، (2:36)، (3:22) و (4:10).
How fast is fast? Constant, linear and quadratic timeخێرا چەندە خێرایە؟ کاتی نەگۆڕ، کاتی هێڵی و کاتی پلەدوو
Twice the data: twice or four times the workدوو هێندە دراوە: دوو یان چوار هێندە کار
| قەبارە () | (linear)هەنگاو بە () | (quadratic)هەنگاو بە () |
|---|---|---|
| 10 | 10 | 100 |
| 100 | 100 | 10,000 |
| 1,000 | 1,000 | 1,000,000 |
| 1,000,000 | 1,000,000 | 1,000,000,000,000 |
All three sorting algorithms of this lesson have a loop inside a loop, so all three are quadratic. Programmers write this as , read "order n squared"; the notation is explained in Big-O notation in one screen, and Comparing algorithms compares four algorithms for the same problem in the same way.
هەر سێ ئەم وانەیە لە ناو هەیە، بۆیە هەر سێکیان پلەدوون. ئەمە وەک دەنووسن؛ ئەم نیشانەیە لە نیشانەی O-ی گەورە لە یەک پەڕەدا ڕوون کراوەتەوە و بەراوردکردنی ئەلگۆریزمەکان بە هەمان شێوە چوار بۆ هەمان کێشە بەراورد دەکات.
How fast is fast? Constant, linear and quadratic timeخێرا چەندە خێرایە؟ کاتی نەگۆڕ، کاتی هێڵی و کاتی پلەدوو
Measured on a real computerپێوانە لەسەر کۆمپیوتەرێکی ڕاستەقینە
Counting is the fair way to compare algorithms, but it is also interesting to time them. The program sorts the same random numbers with bubble sort, insertion sort and Python's list.sort(), and measures the seconds with time.perf_counter(). These times come from the computer this lesson was written on (an Apple M1 laptop with Python 3.12). Your numbers will differ, and even two runs on the same computer differ a little.
ژماردن ڕێگای دادپەروەرانەی بەراوردکردنی ، بەڵام کاتگرتنیشیان سەرنجڕاکێشە. هەمان بە ، و list.sort()ـی ڕیز دەکات و چرکەکان بە time.perf_counter() دەپێوێت. ئەم کاتانە لەو هاتوون کە ئەم وانەیەی لەسەر نووسراوە (لاپتۆپێکی Apple M1 بە Python 3.12). ژمارەکانی تۆ جیاواز دەبن و تەنانەت دوو جار کارپێکردن لەسەر هەمان کەمێک جیاوازن.
import random
import time
def bubble_sort(values):
n = len(values)
for i in range(n - 1):
swapped = False
for j in range(n - i - 1):
if values[j] > values[j + 1]:
values[j], values[j + 1] = values[j + 1], values[j]
swapped = True
if not swapped:
break
def insertion_sort(values):
for i in range(1, len(values)):
current = values[i]
j = i - 1
while j >= 0 and values[j] > current:
values[j + 1] = values[j]
j -= 1
values[j + 1] = current
def seconds(sort_function, data):
copy = data[:] # every method gets the same numbers
start = time.perf_counter()
sort_function(copy)
return time.perf_counter() - start
random.seed(1)
print(f"{'n':>6} {'bubble':>9} {'insertion':>10} {'list.sort':>10}")
for n in [1_000, 2_000, 4_000]:
data = [random.randint(1, 1_000_000) for _ in range(n)]
b = seconds(bubble_sort, data)
i = seconds(insertion_sort, data)
s = seconds(list.sort, data)
print(f"{n:>6} {b:>8.3f}s {i:>9.3f}s {s:>9.5f}s")n bubble insertion list.sort 1000 0.027s 0.012s 0.00007s 2000 0.110s 0.046s 0.00015s 4000 0.448s 0.186s 0.00033s
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 28
data[:]: every method sorts its own copy of the same numbers.data[:]: هەر ڕێگایەک کۆپیی خۆی لە هەمان ژمارەکان ڕیز دەکات.- Lineدێڕی 29
time.perf_counter()is a clock made for measuring short times.time.perf_counter()کاتژمێرێکە بۆ پێوانی کاتی کورت دروست کراوە.- Lineدێڕی 40
list.sortwithout brackets: the method itself is passed, like the two functions.list.sortبەبێ کەوانە: خودی دەنێردرێت، وەک دوو .
Each time doubles, bubble sort and insertion sort take about four times as long: that is quadratic growth. list.sort() takes only about twice as long, and it starts out hundreds of times faster. If bubble sort kept growing like , a million numbers (250 times 4,000) would take times as long as 4,000 numbers: about 28,000 seconds, nearly 8 hours. That is an estimate, not a measurement. On the same computer list.sort() really sorts a million numbers in 0.14 seconds:
هەر جارێک دوو هێندە دەبێت، و نزیکەی چوار هێندە کات دەبەن: ئەمە گەشەی پلەدووە. list.sort() تەنها نزیکەی دوو هێندە کات دەبات و لە سەرەتاوە سەدان جار خێراترە. ئەگەر بەردەوام وەک گەورە ببوایە، ملیۆنێک ژمارە (250 هێندەی 4000) هێندەی 4000 ژمارە کاتی دەبرد: نزیکەی 28000 چرکە، نزیکەی 8 کاتژمێر. ئەمە خەمڵاندنە، نەک پێوانە. لەسەر هەمان list.sort() بە ڕاستی ملیۆنێک ژمارە لە 0.14 چرکەدا ڕیز دەکات:
import random
import time
random.seed(1)
data = [random.randint(1, 1_000_000) for _ in range(1_000_000)]
start = time.perf_counter()
data.sort()
print(f"list.sort() of 1,000,000 numbers: {time.perf_counter() - start:.2f} s")
start = time.perf_counter()
data.sort() # sort the already sorted list again
print(f"sorting it again (already sorted): {time.perf_counter() - start:.3f} s")list.sort() of 1,000,000 numbers: 0.14 s sorting it again (already sorted): 0.018 s
Why Python's sort() is betterبۆچی sort()ـی Python باشترە
Python's sort() and sorted() use Timsort, a much cleverer algorithm built from insertion sort and merging. It needs about comparisons instead of , which is why it sorted a million numbers in a fraction of a second (the logarithm is explained in the next lesson, How many steps?). It is also adaptive: on a list that is already sorted, or sorted backwards, it needs only about comparisons, which is why sorting the sorted million again took 0.018 s.
sort() و sorted()ـی Timsort بەکار دەهێنن، زۆر زیرەکتر کە لە و تێکەڵکردن دروست کراوە. لەبری نزیکەی بەراوردی پێویستە، هەر بۆیە ملیۆنێک ژمارەی لە بەشێکی چرکەیەکدا ڕیز کرد ( لە وانەی داهاتوودا ڕوون دەکرێتەوە: چەند هەنگاو؟). هەروەها خۆگونجێنە: لەسەر کە پێشتر ڕیزکراوە یان بە پێچەوانە ڕیزکراوە، تەنها نزیکەی بەراوردی پێویستە، هەر بۆیە دووبارە ملیۆنە ڕیزکراوەکە 0.018 چرکەی برد.
It is also stable: values that compare as equal keep the order they had before the sort. Sort exam results by mark, and two students with the same mark stay in the order of the original list.
هەروەها جێگیرە (): ئەو لە بەراورددا یەکسانن هەمان ڕیزبەندیی پێش دەپارێزن. ئەنجامی تاقیکردنەوە بە نمرە ڕیز بکە، دوو قوتابی بە هەمان نمرە بە ڕیزبەندیی سەرەتایی دەمێننەوە.
def mark_of(pair):
return pair[1]
results = [("Aram", 85), ("Shilan", 92), ("Karwan", 78), ("Dilan", 92), ("Rezan", 85)]
by_mark = sorted(results, key=mark_of, reverse=True)
for name, mark in by_mark:
print(name, mark)Shilan 92 Dilan 92 Aram 85 Rezan 85 Karwan 78
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 1-2
A key function returns the mark of a (name, mark) pair (sorting by a rule).
key نمرەی جووتێکی (ناو، نمرە) دەگەڕێنێتەوە (ڕیزکردن بەپێی یاسایەک).
- Lineدێڕی 5-6
Shilan was before Dilan and Aram before Rezan; after sorting they still are.
Shilan لە پێش Dilan بوو و Aram لە پێش Rezan؛ دوای هێشتا وان.
Common mistakesهەڵە باوەکان
| Mistakeهەڵە | What happensچی ڕوو دەدات | Fixچارەسەر |
|---|---|---|
Inner loop for j in range(n - i): ناوەوە for j in range(n - i): | IndexError: list index out of range | range(n - i - 1): the last pair is j, j + 1 with j + 1 = n - i - 1range(n - i - 1): دوایین جووت j و j + 1ـە کە j + 1 = n - i - 1 |
Inner loop range(n - 1) in every pass (no - i) ناوەوە range(n - 1) لە هەموو جارێکدا (بێ - i) | still sorts, but compares the finished end again: 25 comparisons instead of 15 for six valuesهێشتا ڕیز دەکات، بەڵام کۆتایی تەواوبوو دووبارە بەراورد دەکات: بۆ شەش 25 بەراورد لەبری 15 | range(n - i - 1) |
Swapping in two lines: a[j] = a[j + 1] then a[j + 1] = a[j]ئاڵوگۆڕ لە دوو دێڕدا: a[j] = a[j + 1] پاشان a[j + 1] = a[j] | both places get the same value; [9, 4] becomes [4, 4] and the 9 is lostهەردوو شوێن هەمان وەردەگرن؛ [9, 4] دەبێتە [4, 4] و 9 ون دەبێت | a[j], a[j + 1] = a[j + 1], a[j], or a temporary variablea[j], a[j + 1] = a[j + 1], a[j]، یان کاتی |
Insertion sort without j >= 0 بەبێ j >= 0 | values[-1] is read, values are overwritten, then IndexError: list index out of rangevalues[-1] دەخوێنرێتەوە، دەسڕدرێنەوە، پاشان IndexError: list index out of range | while j >= 0 and values[j] > current: |
Forgetting the flag reset: swapped = False before the outer loopلەبیرچوونی سفرکردنەوەی ئاڵاکە: swapped = False پێش دەرەوە | after the first swap the flag stays True, so the sort never stops earlyدوای یەکەم ئاڵوگۆڕ ئاڵاکە بە True دەمێنێتەوە، بۆیە هەرگیز زوو ناوەستێت | set swapped = False at the start of each passلە سەرەتای هەر جارێکدا swapped = False دابنێ |
new = values.sort()new = values.sort() | new is None; values itself was sortednew دەبێتە None؛ خودی values ڕیزکرا | new = sorted(values)new = sorted(values) |
Sorting the caller's list inside a function such as median() لە ناو وەک median() | the caller's list is changed without warning بەبێ ئاگادارکردنەوە دەگۆڕێت | sort a copy: values = numbers[:]کۆپییەک ڕیز بکە: values = numbers[:] |
| Using your own bubble sort in a real programبەکارهێنانی خۆت لە ڕاستەقینەدا | hours instead of a fraction of a second for big listsبۆ گەورە کاتژمێرەها لەبری بەشێکی چرکەیەک | sort() or sorted()sort() یان sorted() |
Exercisesڕاهێنانەکان
Show the list [15, 4, 22, 9, 30, 1, 18, 7, 26, 12] after each of the first three complete passes of bubble sort. Which values are already in their final places?
[15, 4, 22, 9, 30, 1, 18, 7, 26, 12] دوای هەر یەک لە سێ جاری تەواوی یەکەمی پیشان بدە. کامیان پێشتر لە شوێنی کۆتایی خۆیانن؟
Hintئاماژە
Each pass carries the largest value of the unsorted part to the end.
هەر جارێک گەورەترین بەشە ڕیزنەکراوەکە دەباتە کۆتایی.
Show answerوەڵامەکە پیشان بدە
| After passدوای جاری | List |
|---|---|
| 1 | [4, 15, 9, 22, 1, 18, 7, 26, 12, 30] |
| 2 | [4, 9, 15, 1, 18, 7, 22, 12, 26, 30] |
| 3 | [4, 9, 1, 15, 7, 18, 12, 22, 26, 30] |
After three passes the three largest values, 22, 26 and 30, are in their final places at the end. The rest is not sorted yet.
دوای سێ جار سێ گەورەترین ، 22، 26 و 30، لە کۆتاییدا لە شوێنی کۆتایی خۆیانن. ئەوانی تر هێشتا ڕیز نەکراون.
values = [15, 4, 22, 9, 30, 1, 18, 7, 26, 12]
n = len(values)
for i in range(3): # only three passes
for j in range(n - i - 1):
if values[j] > values[j + 1]:
values[j], values[j + 1] = values[j + 1], values[j]
print(f"after pass {i + 1}: {values}")after pass 1: [4, 15, 9, 22, 1, 18, 7, 26, 12, 30] after pass 2: [4, 9, 15, 1, 18, 7, 22, 12, 26, 30] after pass 3: [4, 9, 1, 15, 7, 18, 12, 22, 26, 30]
Sort the prices [80, 55, 30, 10] (thousand IQD) by hand with selection sort and with bubble sort. Count the comparisons and the swaps of each. Which algorithm is better here?
قیمەتەکانی [80, 55, 30, 10] (هەزار دینار) بە دەست بە و بە ڕیز بکە. بەراورد و ئاڵوگۆڕی هەر یەکەیان بژمێرە. لێرەدا کام باشترە؟
Show answerوەڵامەکە پیشان بدە
| Algorithm | Passesجارەکان | Comparisonsبەراورد | Swapsئاڵوگۆڕ |
|---|---|---|---|
| selection sort | [10, 55, 30, 80] → [10, 30, 55, 80] → [10, 30, 55, 80] | 2 | |
| bubble sort | [55, 30, 10, 80] → [30, 10, 55, 80] → [10, 30, 55, 80] | 6 |
Both make 6 comparisons, so neither wins on comparisons. The list is in reverse order, so every bubble-sort comparison ends in a swap (and the flag never helps), while selection sort swaps at most once per pass and its last pass needs no swap at all. With fewer swaps, selection sort is better for this list.
هەردووکیان 6 بەراورد دەکەن، بۆیە لە بەراورددا هیچیان نابەنەوە. پێچەوانەیە، بۆیە هەموو بەراوردێکی بە ئاڵوگۆڕ کۆتایی دێت (و ئاڵاکە هەرگیز یارمەتی نادات)، لە کاتێکدا لە هەر جارێکدا لانیزۆر یەک ئاڵوگۆڕ دەکات و جاری کۆتایی هیچ ئاڵوگۆڕێکی ناوێت. بە ئاڵوگۆڕی کەمتر، بۆ ئەم باشترە.
bubble (comparisons, swaps): (6, 6) selection (comparisons, swaps): (6, 2)
Two lists are sorted with insertion sort: A = [3, 6, 8, 12, 20] and B = [20, 12, 8, 6, 3]. Which one needs fewer comparisons? Show each pass in a table.
دوو بە ڕیز دەکرێن: A = [3, 6, 8, 12, 20] و B = [20, 12, 8, 6, 3]. کامیان بەراوردی کەمتری دەوێت؟ هەر جارێک لە خشتەیەکدا پیشان بدە.
Show answerوەڵامەکە پیشان بدە
| Passجار | Currentئێستا | A: comparisonsA: بەراورد | B: comparisonsB: بەراورد | B after the passB دوای ئەو جارە |
|---|---|---|---|---|
| 1 | 6 / 12 | 1 | 1 | [12, 20, 8, 6, 3] |
| 2 | 8 / 8 | 1 | 2 | [8, 12, 20, 6, 3] |
| 3 | 12 / 6 | 1 | 3 | [6, 8, 12, 20, 3] |
| 4 | 20 / 3 | 1 | 4 | [3, 6, 8, 12, 20] |
| totalکۆ | 4 | 10 |
List A needs only 4 comparisons: it is the best case (already sorted), and each current value is compared once with its left neighbour. List B is the worst case (reversed): each current value is compared with every value of the sorted part, , and every comparison causes a shift.
A تەنها 4 بەراوردی دەوێت: (پێشتر ڕیزکراوە) و هەر ئێستا یەک جار لەگەڵ دراوسێی چەپی بەراورد دەکرێت. B (پێچەوانە): هەر ئێستا لەگەڵ هەموو بەشە ڕیزکراوەکە بەراورد دەکرێت، و هەموو بەراوردێک دەبێتە هۆی جووڵاندنێک.
[3, 6, 8, 12, 20]: (4, 0) [20, 12, 8, 6, 3]: (10, 10)
Write a function median(numbers) that sorts a copy of the list with bubble sort and returns the median: the middle value when the count is odd, and the mean of the two middle values when it is even (the median). Test it with [7, 3, 9, 1, 5], [12, 4, 8, 10] and [12, 4, 9, 10], and round the last answer to a whole number.
بنووسە بە ناوی median(numbers) کە کۆپییەکی بە ڕیز دەکات و دەگەڕێنێتەوە: ناوەڕاست کاتێک ژمارەکەیان تاکە و تێکڕای دوو ناوەڕاست کاتێک جووتە (ناوەڕاستە). بە [7, 3, 9, 1, 5]، [12, 4, 8, 10] و [12, 4, 9, 10] تاقی بکەرەوە و دوایین وەڵام بۆ نزیک بکەرەوە.
Hintئاماژە
Sort a copy first; then use n // 2 and n % 2.
سەرەتا کۆپییەک ڕیز بکە؛ پاشان n // 2 و n % 2 بەکار بهێنە.
Show answerوەڵامەکە پیشان بدە
def bubble_sort(values):
n = len(values)
for i in range(n - 1):
swapped = False
for j in range(n - i - 1):
if values[j] > values[j + 1]:
values[j], values[j + 1] = values[j + 1], values[j]
swapped = True
if not swapped:
break
def median(numbers):
values = numbers[:] # sort a copy: the caller's list stays as it was
bubble_sort(values)
n = len(values)
middle = n // 2
if n % 2 == 1: # odd: one middle value
return values[middle]
return (values[middle - 1] + values[middle]) / 2 # even: mean of the two middle values
marks = [7, 3, 9, 1, 5]
print(median(marks), marks)
print(median([12, 4, 8, 10]))
print(median([12, 4, 9, 10]), round(median([12, 4, 9, 10])))
print(round(8.5), round(9.5), round(2.5))5 [7, 3, 9, 1, 5] 9.0 9.5 10 8 10 2
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 14
Sort a copy: the caller's
marksstays unchanged, as the output shows.کۆپییەک ڕیز بکە:
marksـی وەک خۆی دەمێنێتەوە، وەک پیشانی دەدات.- Lineدێڕی 17
n // 2is the middle index for an odd count, the right one of the two middles for an even count.n // 2ناوەڕاستە بۆ ژمارەی تاک و ڕاستەکەی دوو ناوەڕاستەکەیە بۆ ژمارەی جووت.- Lineدێڕی 26-27
round()rounds a .5 to the even neighbour.round().5 بۆ دراوسێ جووتەکە نزیک دەکاتەوە.
Bubble sort with the swapped flag sorts a list of 10 values. What is the smallest possible number of passes, and what is the largest? Which lists give them?
بە ئاڵای swapped بە 10 ڕیز دەکات. کەمترین ژمارەی جارەکان چەندە و زۆرترینیان چەندە؟ چ جۆرە ئەمانە دەدات؟
Show answerوەڵامەکە پیشان بدە
At least 1 pass: a list that is already sorted, because pass 1 finds no swap and stops. At most 9 passes (): for example a reversed list, where every pass swaps; after pass 9 the outer loop has simply run out.
لانیکەم 1 جار: کە پێشتر ڕیزکراوە، چونکە جاری یەکەم هیچ ئاڵوگۆڕێک نادۆزێتەوە و دەوەستێت. لانیزۆر 9 جار (): بۆ نموونە پێچەوانە، کە هەموو جارێک ئاڵوگۆڕ دەکات؛ دوای جاری نۆیەم دەرەوە تەواو دەبێت.
def passes(values):
n = len(values)
count = 0
for i in range(n - 1):
swapped = False
count += 1
for j in range(n - i - 1):
if values[j] > values[j + 1]:
values[j], values[j + 1] = values[j + 1], values[j]
swapped = True
if not swapped:
break
return count
print(passes(list(range(1, 11))), passes(list(range(10, 0, -1))))1 9
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 6
Count every pass that starts.
هەموو جارێک کە دەست پێ دەکات بژمێرە.
Summaryپوختە
- Sorting puts data in order; it costs time once and makes every later search faster.
- Bubble sort swaps neighbours that are in the wrong order; each pass carries the largest value of the unsorted part to the end. A
swappedflag stops it after a pass without swaps. - Insertion sort takes the next value, shifts bigger ones right and drops it into the gap, like cards in a hand; it can sort a list while it arrives.
- Count comparisons and swaps to compare algorithms. Best case (already sorted): comparisons for bubble sort with the flag and for insertion sort. Worst case (reversed): . Selection sort always makes .
- No loop: constant time. One loop: linear time. A loop inside a loop: quadratic time, and it decides when both are present. All three sorts here are quadratic: double the list, four times the work.
- Python's
sort()(Timsort) is about , adaptive and stable: use it in real programs.
- ڕیز دەکات؛ یەک جار کات دەبات و هەموو گەڕانێکی دواتر خێراتر دەکات.
- دراوسێ هەڵە ڕیزبووەکان ئاڵوگۆڕ دەکات؛ هەر جارێک گەورەترین بەشە ڕیزنەکراوەکە دەباتە کۆتایی. ئاڵای
swappedدوای جارێکی بێ ئاڵوگۆڕ دەیوەستێنێت. - داهاتوو هەڵدەگرێت، گەورەترەکان بەرەو ڕاست دەجووڵێنێت و دەیخاتە بۆشاییەکە، وەک کارت لە دەستدا؛ دەتوانێت ڕیز بکات لە کاتێکدا دێت.
- بۆ بەراوردکردنی بەراورد و ئاڵوگۆڕەکان بژمێرە. (پێشتر ڕیزکراو): بەراورد بۆ بە ئاڵاوە و بۆ . (پێچەوانە): . هەمیشە بەراورد دەکات.
- بێ : . یەک : . : و کاتێک هەردووکیان هەبن ئەو بڕیار دەدات. هەر سێ ئێرە پلەدوون: دوو هێندە بکە، چوار هێندە کار.
sort()ـی (Timsort) نزیکەی ـە، خۆگونجێنە و جێگیرە: لە ڕاستەقینەدا بەکاری بهێنە.
Next: searching. Linear search, then binary search, which needs a sorted list and adds a fourth speed to the table: logarithmic time.
دواتر: گەڕان. ، پاشان ، کە ڕیزکراوی پێویستە و خێرایی چوارەم بۆ خشتەکە زیاد دەکات: .
What does one pass of bubble sort guarantee?یەک جاری ڕیزکردنی بڵقی چی گەرەنتی دەکات؟
The largest value not yet in place reaches its final place at the end.
گەورەترین ئەو هێشتا لە شوێنی خۆی نییە دەگاتە شوێنی کۆتایی خۆی لە کۆتاییدا.
When can bubble sort stop early?ڕیزکردنی بڵقی کەی دەتوانێت زوو بوەستێت؟
After a pass that makes no swap: then every neighbour pair is in order.
دوای جارێک کە هیچ ئاڵوگۆڕێک ناکات: ئەوکاتە هەموو جووتە دراوسێیەک بە ڕیزن.
Why is insertion sort fast on an almost sorted list?بۆچی ڕیزکردن بە تێخستن لەسەر لیستێک کە نزیکەی ڕیزکراوە خێرایە؟
Each value moves only a few places, so each pass stops after a few comparisons.
هەر تەنها چەند شوێنێک دەجووڵێت، بۆیە هەر جارێک دوای چەند بەراوردێک دەوەستێت.
Bubble sort takes 0.45 s for 4,000 numbers. Roughly how long for 8,000?ڕیزکردنی بڵقی بۆ 4000 ژمارە 0.45 چرکە دەبات. بۆ 8000 نزیکەی چەند؟
About 1.8 s: it is quadratic, so twice the data costs about four times the time.
نزیکەی 1.8 چرکە: پلەدووە، بۆیە دوو هێندە نزیکەی چوار هێندە کات دەبات.
Lesson complete!وانەکە تەواو بوو!
Well done. Review the key terms, then go on to the next lesson.دەستخۆش. سەیرێکی زاراوە سەرەکییەکان بکەرەوە، پاشان بڕۆ بۆ وانەی داهاتوو.
Key termsزاراوە سەرەکییەکان
Binary Search and Hashingگەڕانی دووانی و هاشکردن
Related lecturesوانە پەیوەندیدارەکان
- Binary Search and Hashingگەڕانی دووانی و هاشکردن
- Stacks: Last In, First Outستاکەکان: دوایین هاتوو، یەکەم دەرچوو
- Queues and Deques: First In, First Outکیووەکان و کیووە دووسەرەکان: یەکەم هاتوو، یەکەم دەرچوو
- Processing Two-Dimensional Listsکارکردن لەسەر لیستە دووڕەهەندەکان
- Agent Programs, Pseudocode and Algorithm Analysisبەرنامەکانی ئەیجێنت، نیمچەکۆد و شیکارکردنی ئەلگۆریزم
- Algorithms, Pseudocode and Flowchartsئەلگۆریزمەکان، نیمچەکۆد و هێڵکارییەکانی ڕەوت
- The Median and the Modeناوەڕاستە و باو
References and further readingسەرچاوەکان و خوێندنەوەی زیاتر
- Python documentation: Sorting Techniques (sort() and sorted(), key functions, stability, Timsort)
- Python documentation: Time complexity of built-in types (list.sort is O(n log n); sorted or reverse-sorted input takes O(n))
- Python documentation: round() (ties round to the even choice)
- Wikipedia: Bubble sort (passes, swapped flag, best and worst case, why it is rarely used)
- Wikipedia: Insertion sort (playing cards, best case on sorted input, worst case on reversed input, stable, online)
This lecture is a first edition. The Kurdish text and terminology are waiting for review by Kurdish IT teachers.ئەم وانەیە چاپی یەکەمە. دەقە کوردییەکە و زاراوەکانی چاوەڕێی پێداچوونەوەی مامۆستایانی کوردی بواری IT ن.