1593831600
Odd-Even Sort is a headstrong little girl.
The middle daughter of Heap Sort and Cocktail Shaker Sort, she has recently discovered she a particular skill, a skill that makes her a nightmare to people like her parents. This skill has allowed her to get extra dessert, more screen time, even less chores; in short, everything a ten-year-old middle child could ever dream of.
That skill? Getting one parent to say yes when the other already said no.
She’s sneaky about it. She will wait minutes, hours even, just to strike the unsuspecting parent at exactly the right moment. She knows just when her opportunity arises: when mom gets home from work, when dad is dealing with her baby brother Bogosort, when her elder sister Counting Sort needs to get to soccer practice. All her life she’s been perfecting this skill, and now she’s a master.
Here’s hoping she uses her powers for good. Or at least extra ice cream.
Plus my eBook “The Daily Design Pattern”, early access, new posts in your inbox, and more for becoming a paid subscriber.
Go!
I will not spam, sell your email, etc.
The base visualization from Wikipedia is cool to look at but doesn’t help me understand this algorithm at all. So let’s demonstrate the algorithm with a simple set of numbers. Here’s our unsorted collection:
{ 15, 62, 42, 29, 17 }
On the first pass of the algorithm, in the first step, we compare the element in position 1 against the element in position 2. Position 1 is 15, position 3 is 62, so these are in order.
The next comparison is between position 3 (42) and position 4 (29). Those elements are out of order, so the algorithm swaps them, resulting in:
{ 15, 62, 29, 42, 17 }
The next move would compare the element in position 5 against the one in position 6, but since there isn’t one in position six, the algorithm instead switches to doing the even-numbered comparison.
The first even comparison (position 2 to position 3) results in:
{ 15, 29, 62, 42, 17 }
The second even comparison results in:
{ 15, 29, 62, 17, 42 }
Now we go back to the odd-numbered comparisons:
{ 15, 29, 17, 62, 42 }
Now back to even-numbered:
{ 15, 17, 29, 62, 42 }
{ 15, 17, 29, 42, 62 }
And now the array is sorted! It took us four passes to do this, and if you’re thinking that seems pretty inefficient, you are not wrong.
#exchange sorts #algorithms
1593831600
Odd-Even Sort is a headstrong little girl.
The middle daughter of Heap Sort and Cocktail Shaker Sort, she has recently discovered she a particular skill, a skill that makes her a nightmare to people like her parents. This skill has allowed her to get extra dessert, more screen time, even less chores; in short, everything a ten-year-old middle child could ever dream of.
That skill? Getting one parent to say yes when the other already said no.
She’s sneaky about it. She will wait minutes, hours even, just to strike the unsuspecting parent at exactly the right moment. She knows just when her opportunity arises: when mom gets home from work, when dad is dealing with her baby brother Bogosort, when her elder sister Counting Sort needs to get to soccer practice. All her life she’s been perfecting this skill, and now she’s a master.
Here’s hoping she uses her powers for good. Or at least extra ice cream.
Plus my eBook “The Daily Design Pattern”, early access, new posts in your inbox, and more for becoming a paid subscriber.
Go!
I will not spam, sell your email, etc.
The base visualization from Wikipedia is cool to look at but doesn’t help me understand this algorithm at all. So let’s demonstrate the algorithm with a simple set of numbers. Here’s our unsorted collection:
{ 15, 62, 42, 29, 17 }
On the first pass of the algorithm, in the first step, we compare the element in position 1 against the element in position 2. Position 1 is 15, position 3 is 62, so these are in order.
The next comparison is between position 3 (42) and position 4 (29). Those elements are out of order, so the algorithm swaps them, resulting in:
{ 15, 62, 29, 42, 17 }
The next move would compare the element in position 5 against the one in position 6, but since there isn’t one in position six, the algorithm instead switches to doing the even-numbered comparison.
The first even comparison (position 2 to position 3) results in:
{ 15, 29, 62, 42, 17 }
The second even comparison results in:
{ 15, 29, 62, 17, 42 }
Now we go back to the odd-numbered comparisons:
{ 15, 29, 17, 62, 42 }
Now back to even-numbered:
{ 15, 17, 29, 62, 42 }
{ 15, 17, 29, 42, 62 }
And now the array is sorted! It took us four passes to do this, and if you’re thinking that seems pretty inefficient, you are not wrong.
#exchange sorts #algorithms
1646796864
Trong bài viết này, bạn sẽ học cách sử dụng phương pháp danh sách của Python sort()
.
Bạn cũng sẽ tìm hiểu một cách khác để thực hiện sắp xếp trong Python bằng cách sử dụng sorted()
hàm để bạn có thể thấy nó khác với nó như thế nào sort()
.
Cuối cùng, bạn sẽ biết những điều cơ bản về sắp xếp danh sách bằng Python và biết cách tùy chỉnh việc sắp xếp để phù hợp với nhu cầu của bạn.
sort()
- Tổng quan về cú phápPhương pháp sort()
này là một trong những cách bạn có thể sắp xếp danh sách trong Python.
Khi sử dụng sort()
, bạn sắp xếp một danh sách tại chỗ . Điều này có nghĩa là danh sách ban đầu được sửa đổi trực tiếp. Cụ thể, thứ tự ban đầu của các phần tử bị thay đổi.
Cú pháp chung cho phương thức sort()
này trông giống như sau:
list_name.sort(reverse=..., key=... )
Hãy chia nhỏ nó:
list_name
là tên của danh sách bạn đang làm việc.sort()
là một trong những phương pháp danh sách của Python để sắp xếp và thay đổi danh sách. Nó sắp xếp các phần tử danh sách theo thứ tự tăng dần hoặc giảm dần .sort()
chấp nhận hai tham số tùy chọn .reverse
là tham số tùy chọn đầu tiên. Nó chỉ định liệu danh sách sẽ được sắp xếp theo thứ tự tăng dần hay giảm dần. Nó nhận một giá trị Boolean, nghĩa là giá trị đó là True hoặc False. Giá trị mặc định là False , nghĩa là danh sách được sắp xếp theo thứ tự tăng dần. Đặt nó thành True sẽ sắp xếp danh sách ngược lại, theo thứ tự giảm dần.key
là tham số tùy chọn thứ hai. Nó có một hàm hoặc phương pháp được sử dụng để chỉ định bất kỳ tiêu chí sắp xếp chi tiết nào mà bạn có thể có.Phương sort()
thức trả về None
, có nghĩa là không có giá trị trả về vì nó chỉ sửa đổi danh sách ban đầu. Nó không trả về một danh sách mới.
sort()
Như đã đề cập trước đó, theo mặc định, sort()
sắp xếp các mục trong danh sách theo thứ tự tăng dần.
Thứ tự tăng dần (hoặc tăng dần) có nghĩa là các mặt hàng được sắp xếp từ giá trị thấp nhất đến cao nhất.
Giá trị thấp nhất ở bên trái và giá trị cao nhất ở bên phải.
Cú pháp chung để thực hiện việc này sẽ giống như sau:
list_name.sort()
Hãy xem ví dụ sau đây cho thấy cách sắp xếp danh sách các số nguyên:
# a list of numbers
my_numbers = [10, 8, 3, 22, 33, 7, 11, 100, 54]
#sort list in-place in ascending order
my_numbers.sort()
#print modified list
print(my_numbers)
#output
#[3, 7, 8, 10, 11, 22, 33, 54, 100]
Trong ví dụ trên, các số được sắp xếp từ nhỏ nhất đến lớn nhất.
Bạn cũng có thể đạt được điều tương tự khi làm việc với danh sách các chuỗi:
# a list of strings
programming_languages = ["Python", "Swift","Java", "C++", "Go", "Rust"]
#sort list in-place in alphabetical order
programming_languages.sort()
#print modified list
print(programming_languages)
#output
#['C++', 'Go', 'Java', 'Python', 'Rust', 'Swift']
Trong trường hợp này, mỗi chuỗi có trong danh sách được sắp xếp theo thứ tự không tuân theo.
Như bạn đã thấy trong cả hai ví dụ, danh sách ban đầu đã được thay đổi trực tiếp.
sort()
Thứ tự giảm dần (hoặc giảm dần) ngược lại với thứ tự tăng dần - các phần tử được sắp xếp từ giá trị cao nhất đến thấp nhất.
Để sắp xếp các mục trong danh sách theo thứ tự giảm dần, bạn cần sử dụng reverse
tham số tùy chọn với phương thức sort()
và đặt giá trị của nó thành True
.
Cú pháp chung để thực hiện việc này sẽ giống như sau:
list_name.sort(reverse=True)
Hãy sử dụng lại cùng một ví dụ từ phần trước, nhưng lần này làm cho nó để các số được sắp xếp theo thứ tự ngược lại:
# a list of numbers
my_numbers = [10, 8, 3, 22, 33, 7, 11, 100, 54]
#sort list in-place in descending order
my_numbers.sort(reverse=True)
#print modified list
print(my_numbers)
#output
#[100, 54, 33, 22, 11, 10, 8, 7, 3]
Bây giờ tất cả các số được sắp xếp ngược lại, với giá trị lớn nhất ở bên tay trái và giá trị nhỏ nhất ở bên phải.
Bạn cũng có thể đạt được điều tương tự khi làm việc với danh sách các chuỗi.
# a list of strings
programming_languages = ["Python", "Swift","Java", "C++", "Go", "Rust"]
#sort list in-place in reverse alphabetical order
programming_languages.sort(reverse=True)
#print modified list
print(programming_languages)
#output
#['Swift', 'Rust', 'Python', 'Java', 'Go', 'C++']
Các mục danh sách hiện được sắp xếp theo thứ tự bảng chữ cái ngược lại.
key
tham số với phương thức sort()
Bạn có thể sử dụng key
tham số để thực hiện các thao tác sắp xếp tùy chỉnh hơn.
Giá trị được gán cho key
tham số cần phải là thứ có thể gọi được.
Callable là thứ có thể được gọi, có nghĩa là nó có thể được gọi và tham chiếu.
Một số ví dụ về các đối tượng có thể gọi là các phương thức và hàm.
Phương thức hoặc hàm được gán cho key
này sẽ được áp dụng cho tất cả các phần tử trong danh sách trước khi bất kỳ quá trình sắp xếp nào xảy ra và sẽ chỉ định logic cho tiêu chí sắp xếp.
Giả sử bạn muốn sắp xếp danh sách các chuỗi dựa trên độ dài của chúng.
Đối với điều đó, bạn chỉ định len()
hàm tích hợp cho key
tham số.
Hàm len()
sẽ đếm độ dài của từng phần tử được lưu trong danh sách bằng cách đếm các ký tự có trong phần tử đó.
programming_languages = ["Python", "Swift","Java", "C++", "Go", "Rust"]
programming_languages.sort(key=len)
print(programming_languages)
#output
#['Go', 'C++', 'Java', 'Rust', 'Swift', 'Python']
Trong ví dụ trên, các chuỗi được sắp xếp theo thứ tự tăng dần mặc định, nhưng lần này việc sắp xếp xảy ra dựa trên độ dài của chúng.
Chuỗi ngắn nhất ở bên trái và dài nhất ở bên phải.
Các key
và reverse
tham số cũng có thể được kết hợp.
Ví dụ: bạn có thể sắp xếp các mục trong danh sách dựa trên độ dài của chúng nhưng theo thứ tự giảm dần.
programming_languages = ["Python", "Swift","Java", "C++", "Go", "Rust"]
programming_languages.sort(key=len, reverse=True)
print(programming_languages)
#output
#['Python', 'Swift', 'Java', 'Rust', 'C++', 'Go']
Trong ví dụ trên, các chuỗi đi từ dài nhất đến ngắn nhất.
Một điều cần lưu ý nữa là bạn có thể tạo một chức năng sắp xếp tùy chỉnh của riêng mình, để tạo các tiêu chí sắp xếp rõ ràng hơn.
Ví dụ: bạn có thể tạo một hàm cụ thể và sau đó sắp xếp danh sách theo giá trị trả về của hàm đó.
Giả sử bạn có một danh sách các từ điển với các ngôn ngữ lập trình và năm mà mỗi ngôn ngữ lập trình được tạo ra.
programming_languages = [{'language':'Python','year':1991},
{'language':'Swift','year':2014},
{'language':'Java', 'year':1995},
{'language':'C++','year':1985},
{'language':'Go','year':2007},
{'language':'Rust','year':2010},
]
Bạn có thể xác định một hàm tùy chỉnh nhận giá trị của một khóa cụ thể từ từ điển.
💡 Hãy nhớ rằng khóa từ điển và key
tham số sort()
chấp nhận là hai thứ khác nhau!
Cụ thể, hàm sẽ lấy và trả về giá trị của year
khóa trong danh sách từ điển, chỉ định năm mà mọi ngôn ngữ trong từ điển được tạo.
Giá trị trả về sau đó sẽ được áp dụng làm tiêu chí sắp xếp cho danh sách.
programming_languages = [{'language':'Python','year':1991},
{'language':'Swift','year':2014},
{'language':'Java', 'year':1995},
{'language':'C++','year':1985},
{'language':'Go','year':2007},
{'language':'Rust','year':2010},
]
def get_year(element):
return element['year']
Sau đó, bạn có thể sắp xếp theo giá trị trả về của hàm bạn đã tạo trước đó bằng cách gán nó cho key
tham số và sắp xếp theo thứ tự thời gian tăng dần mặc định:
programming_languages = [{'language':'Python','year':1991},
{'language':'Swift','year':2014},
{'language':'Java', 'year':1995},
{'language':'C++','year':1985},
{'language':'Go','year':2007},
{'language':'Rust','year':2010},
]
def get_year(element):
return element['year']
programming_languages.sort(key=get_year)
print(programming_languages)
Đầu ra:
[{'language': 'C++', 'year': 1985}, {'language': 'Python', 'year': 1991}, {'language': 'Java', 'year': 1995}, {'language': 'Go', 'year': 2007}, {'language': 'Rust', 'year': 2010}, {'language': 'Swift', 'year': 2014}]
Nếu bạn muốn sắp xếp từ ngôn ngữ được tạo gần đây nhất đến ngôn ngữ cũ nhất hoặc theo thứ tự giảm dần, thì bạn sử dụng reverse=True
tham số:
programming_languages = [{'language':'Python','year':1991},
{'language':'Swift','year':2014},
{'language':'Java', 'year':1995},
{'language':'C++','year':1985},
{'language':'Go','year':2007},
{'language':'Rust','year':2010},
]
def get_year(element):
return element['year']
programming_languages.sort(key=get_year, reverse=True)
print(programming_languages)
Đầu ra:
[{'language': 'Swift', 'year': 2014}, {'language': 'Rust', 'year': 2010}, {'language': 'Go', 'year': 2007}, {'language': 'Java', 'year': 1995}, {'language': 'Python', 'year': 1991}, {'language': 'C++', 'year': 1985}]
Để đạt được kết quả chính xác, bạn có thể tạo một hàm lambda.
Thay vì sử dụng hàm tùy chỉnh thông thường mà bạn đã xác định bằng def
từ khóa, bạn có thể:
def
hàm. Các hàm lambda còn được gọi là các hàm ẩn danh .programming_languages = [{'language':'Python','year':1991},
{'language':'Swift','year':2014},
{'language':'Java', 'year':1995},
{'language':'C++','year':1985},
{'language':'Go','year':2007},
{'language':'Rust','year':2010},
]
programming_languages.sort(key=lambda element: element['year'])
print(programming_languages)
Hàm lambda được chỉ định với dòng key=lambda element: element['year']
sắp xếp các ngôn ngữ lập trình này từ cũ nhất đến mới nhất.
sort()
và sorted()
Phương sort()
thức hoạt động theo cách tương tự như sorted()
hàm.
Cú pháp chung của sorted()
hàm trông như sau:
sorted(list_name,reverse=...,key=...)
Hãy chia nhỏ nó:
sorted()
là một hàm tích hợp chấp nhận một có thể lặp lại. Sau đó, nó sắp xếp nó theo thứ tự tăng dần hoặc giảm dần.sorted()
chấp nhận ba tham số. Một tham số là bắt buộc và hai tham số còn lại là tùy chọn.list_name
là tham số bắt buộc . Trong trường hợp này, tham số là danh sách, nhưng sorted()
chấp nhận bất kỳ đối tượng có thể lặp lại nào khác.sorted()
cũng chấp nhận các tham số tùy chọn reverse
và key
, đó là các tham số tùy chọn tương tự mà phương thức sort()
chấp nhận.Sự khác biệt chính giữa sort()
và sorted()
là sorted()
hàm nhận một danh sách và trả về một bản sao được sắp xếp mới của nó.
Bản sao mới chứa các phần tử của danh sách ban đầu theo thứ tự được sắp xếp.
Các phần tử trong danh sách ban đầu không bị ảnh hưởng và không thay đổi.
Vì vậy, để tóm tắt sự khác biệt:
sort()
thức không có giá trị trả về và trực tiếp sửa đổi danh sách ban đầu, thay đổi thứ tự của các phần tử chứa trong nó.sorted()
hàm có giá trị trả về, là một bản sao đã được sắp xếp của danh sách ban đầu. Bản sao đó chứa các mục danh sách của danh sách ban đầu theo thứ tự được sắp xếp. Cuối cùng, danh sách ban đầu vẫn còn nguyên vẹn.Hãy xem ví dụ sau để xem nó hoạt động như thế nào:
#original list of numbers
my_numbers = [10, 8, 3, 22, 33, 7, 11, 100, 54]
#sort original list in default ascending order
my_numbers_sorted = sorted(my_numbers)
#print original list
print(my_numbers)
#print the copy of the original list that was created
print(my_numbers_sorted)
#output
#[10, 8, 3, 22, 33, 7, 11, 100, 54]
#[3, 7, 8, 10, 11, 22, 33, 54, 100]
Vì không có đối số bổ sung nào được cung cấp sorted()
, nó đã sắp xếp bản sao của danh sách ban đầu theo thứ tự tăng dần mặc định, từ giá trị nhỏ nhất đến giá trị lớn nhất.
Và khi in danh sách ban đầu, bạn thấy rằng nó vẫn được giữ nguyên và các mục có thứ tự ban đầu.
Như bạn đã thấy trong ví dụ trên, bản sao của danh sách đã được gán cho một biến mới my_numbers_sorted
,.
Một cái gì đó như vậy không thể được thực hiện với sort()
.
Hãy xem ví dụ sau để xem điều gì sẽ xảy ra nếu điều đó được thực hiện với phương thức sort()
.
my_numbers = [10, 8, 3, 22, 33, 7, 11, 100, 54]
my_numbers_sorted = my_numbers.sort()
print(my_numbers)
print(my_numbers_sorted)
#output
#[3, 7, 8, 10, 11, 22, 33, 54, 100]
#None
Bạn thấy rằng giá trị trả về của sort()
là None
.
Cuối cùng, một điều khác cần lưu ý là các reverse
và key
tham số mà sorted()
hàm chấp nhận hoạt động giống hệt như cách chúng thực hiện với phương thức sort()
bạn đã thấy trong các phần trước.
sort()
vàsorted()
Dưới đây là một số điều bạn có thể muốn xem xét khi quyết định có nên sử dụng sort()
vs. sorted()
Trước tiên, hãy xem xét loại dữ liệu bạn đang làm việc:
sort()
phương pháp này vì sort()
chỉ được gọi trong danh sách.sorted()
. Hàm sorted()
chấp nhận và sắp xếp mọi thứ có thể lặp lại (như từ điển, bộ giá trị và bộ) chứ không chỉ danh sách.Tiếp theo, một điều khác cần xem xét là liệu bạn có giữ được thứ tự ban đầu của danh sách mà bạn đang làm việc hay không:
sort()
, danh sách ban đầu sẽ bị thay đổi và mất thứ tự ban đầu. Bạn sẽ không thể truy xuất vị trí ban đầu của các phần tử danh sách. Sử dụng sort()
khi bạn chắc chắn muốn thay đổi danh sách đang làm việc và chắc chắn rằng bạn không muốn giữ lại thứ tự đã có.sorted()
nó hữu ích khi bạn muốn tạo một danh sách mới nhưng bạn vẫn muốn giữ lại danh sách bạn đang làm việc. Hàm sorted()
sẽ tạo một danh sách được sắp xếp mới với các phần tử danh sách được sắp xếp theo thứ tự mong muốn.Cuối cùng, một điều khác mà bạn có thể muốn xem xét khi làm việc với các tập dữ liệu lớn hơn, đó là hiệu quả về thời gian và bộ nhớ:
sort()
pháp này chiếm dụng và tiêu tốn ít bộ nhớ hơn vì nó chỉ sắp xếp danh sách tại chỗ và không tạo ra danh sách mới không cần thiết mà bạn không cần. Vì lý do tương tự, nó cũng nhanh hơn một chút vì nó không tạo ra một bản sao. Điều này có thể hữu ích khi bạn đang làm việc với danh sách lớn hơn chứa nhiều phần tử hơn.Và bạn có nó rồi đấy! Bây giờ bạn đã biết cách sắp xếp một danh sách trong Python bằng sort()
phương pháp này.
Bạn cũng đã xem xét sự khác biệt chính giữa sắp xếp danh sách bằng cách sử dụng sort()
và sorted()
.
Tôi hy vọng bạn thấy bài viết này hữu ích.
Để tìm hiểu thêm về ngôn ngữ lập trình Python, hãy xem Chứng chỉ Máy tính Khoa học với Python của freeCodeCamp .
Bạn sẽ bắt đầu từ những điều cơ bản và học theo cách tương tác và thân thiện với người mới bắt đầu. Bạn cũng sẽ xây dựng năm dự án vào cuối để áp dụng vào thực tế và giúp củng cố những gì bạn đã học được.
Nguồn: https://www.freecodecamp.org/news/python-sort-how-to-sort-a-list-in-python/
1593887160
Shell Sort is the unassuming, quiet type. The late-teens son of high-achieving Insertion Sort and Quick Sort, Shell Sort would much rather just curl up alone with a good sci-fi/fantasy book and sip hot cocoa.
He’s a straight-A high school senior who really doesn’t understand why he has to be at this stupid family reunion thing. In fact, he’d much rather be home right now, reading the latest N.K. Jemisin book.
Although, Auntie Heapy’s cooking is pretty good. And the family football game isn’t the worst thing in the universe. And as much as he’s annoyed by younger brother Comb Sort, it’s really nice to have him on the same team. So it isn’t all bad. Just mostly bad.
Plus my eBook “The Daily Design Pattern”, early access, new posts in your inbox, and more for becoming a paid subscriber.
Go!
I will not spam, sell your email, etc.
This is one of the visualizations I found for Shell Sort, but it’s not very clear (at least to me) what’s actually happening here, so let’s see if we can break it down.
The first thing you need to know is that the goal of Shell Sort is to reduce the number of moves that must be made when gap size h = 1. In that situation, Shell Sort becomes Insertion Sort, and Insertion Sort does very poorly if the numbers to be sorted are far away from where they should be.
Imagine we have the following data:
A0A1A2A3A4A5A6A7A8A9A10A114318916296230817952751
Let’s also say that our gap size h will be 5 for the first round of sorting. That means that Shell Sort will create the following theoretical subarrays:
{ a0, a5, a10 }
{ a1, a6, a11 }
{ a2, a7 }
{ a3, a8 }
{ a4, a9 }
Each of those subarrays will be sorted independently of one another, resulting in a collection that looks like this:
A0A1A2A3A4A5A6A7A8A9A10A117188162943309179526251
See how the 7 moved to the front of the array, much closer to where it should be when fully sorted?
Now let’s shrink the gap size h to 3. Shell Sort will now use the following theoretical subarrays:
{ a0, a3, a6, a9 }
{ a1, a4, a7, a10 }
{ a2, a5, a8, a11 }
Sorting those subarrays results in a collection that looks like this:
A0A1A2A3A4A5A6A7A8A9A10A116184372951306279529181
Now the 6 is in front of the 7, and is in fact where it should be when the array is fully sorted. Remember that the goal here is not to fully sort the array, but to reduce the number of moves Insertion Sort must make in order to sort the array when h = 1. Speaking of, a pass through of this data during Insertion Sort results in, of course:
A0A1A2A3A4A5A6A7A8A9A10A116718293043515262798191
UPDATE (1 Aug 2019): Reader James Curran created another visualization of Shell Sort, and here it is:
Finally, take a look at this “audibilization” of Shell Sort from YouTube:
class ShellSort
{
static int Sort(int[] array)
{
int length = array.Length;
for (int h = length / 2; h > 0; h /= 2)
{
for (int i = h; i < length; i += 1)
{
int temp = array[i];
int j;
for (j = i; j >= h && array[j - h] > temp; j -= h)
{
array[j] = array[j - h];
}
array[j] = temp;
}
}
return 0;
}
public static void Main()
{
int[] array = { 53, 19, 71, 3, 66, 62, 20, 84 };
Console.WriteLine("Shell Sort");
CommonFunctions.PrintInitial(array);
Sort(array);
CommonFunctions.PrintFinal(array);
Console.ReadKey();
}
}
At first glance, it appears that Shell Sort actually performs worse than Insertion Sort, given that Insertion Sort’s best case is O(n) and Shell Sort’s best case is O(n log n). But in the real world the only time Insertion Sort performs in O(n) time is if the list is already sorted.
As stated earlier, Shell Sort’s purpose is to minimize the distance items have to move when they are being sorted by the final stage where h = 1. The problem when trying to determine Shell Sort’s time complexity is that such complexity depends entirely on what the implementation chooses for the values of h.
A final note: the implementation above actually has a time complexity of O(n2), and is used for simplicity and not fit for production.
#exchange sorts #algorithms
1593795960
Gnome Sort is brand new to the family.
The girlfriend of Pigeonhole Sort and a hopeless romantic, she is eager to meet his parents and siblings and make good impressions on them. She can’t wait for a chance to show off the bounty of her vegetable garden, and has brought squash, carrots, and fresh spinach to the reunion in the hopes of impressing her (maybe, potentially, hopefully) soon-to-be in-laws.
Photo by Kenan Kitchen / Unsplash
She might be out of luck, though. Pigeon has done this before, and the girlfriends he brings to the reunion aren’t seen at the next one. Nevertheless, Gnome Sort hopes her gifts of food and joy help tell Pigeon’s family that maybe she really is the real deal.
Even if she isn’t, the family figures, they still get free fresh veggies. That’s a good deal.
Plus my eBook “The Daily Design Pattern”, early access, new posts in your inbox, and more for becoming a paid subscriber.
Go!
I will not spam, sell your email, etc.
The nice thing about this visualization is that it makes it obvious what the “gnome” is doing. It also makes it very clear that this is a terribly inefficient algorithm.
The part that the visualization is skipping is that when a number is place into it’s final sorted position, the “gnome” needs to step back up the sorted items to find the next unsorted item. Even if it does this quickly, it’s doing many more accesses than other algorithms.
This one also has an “audibilization”; it sounded kind of like a police siren on speed to me. What do you think?
class GnomeSort
{
static void Sort(int[] arr, int length)
{
int index = 0;
while (index < length)//If there is no pot next to the gnome, he is done.
{
if (index == 0) //If the gnome is at the start of the line...
{
index++;//he steps forward
}
if (arr[index] >= arr[index - 1])//If the pots next to the gnome are in the correct order...
{
index++;//he goes to the next pot
}
else //If the pots are in the wrong order, he switches them.
{
int temp = 0;
temp = arr[index];
arr[index] = arr[index - 1];
arr[index - 1] = temp;
index--;
}
}
return;
}
public static void Main()
{
int[] array = { 84, 61, 15, 2, 7, 55, 19, 40, 78, 33 };
CommonFunctions.PrintInitial(array);
Sort(array, array.Length);
CommonFunctions.PrintFinal(array);
Console.ReadKey();
}
}
#exchange sorts #algorithms
1593861780
Comb Sort is the poster boy for the all-American child.
Unlike his elder brother Shell Sort, Comb Sort is a star athlete. He started as the quarterback for his high school football team when he was a sophomore. But more than that, he has everything he thought he could ever want, at least until recently. He’s the junior prom king, the one voted “best athlete” in the yearbook, everything. Life has been easy for him so far.
Yet, something is bothering him. Something that, until recently, he couldn’t describe.
He’s not the smartest guy, and he knows this. His grades are mostly Cs and Ds, and he understands that that doesn’t bode well for his future. His p
rents are high-achievers, his brother is a straight-A student, and he’s… what? A star athlete? That won’t last forever. What happens when he can no longer get by on physical prowess?
So, he reads. He studies. He’s putting more time into making good test scores and less time into sports. It’s not working yet (his last test was a C+), but he’s hopeful that it will, and soon. He can’t get through life on athletic skills alone. He’s sorting out his life, one piece at a time.
Plus my eBook “The Daily Design Pattern”, early access, new posts in your inbox, and more for becoming a paid subscriber.
Go!
I will not spam, sell your email, etc.
You can see from this animation why this algorithm got the name “Comb Sort”: the comparison distance look like two prongs in a comb. You can also see that this is a not-very-effective sort: it has to do many passes through all elements in order to fully sort this list. In fact, we would most likely consider Comb Sort to be a “naive” sort, on the same level as Selection Sort.
Also check out the “audibilization” of this sort from YouTube:
Finally, reader James Curran kindly created a visualization for this sort; it looks like this:
Implementation
class CombSort
{
static int GetNextGap(int gap)
{
//The “shrink factor”, empirically shown to be 1.3
gap = (gap * 10) / 13;
if (gap < 1)
{
return 1;
}
return gap;
}
static void Sort(int[] array)
{
int length = array.Length;
int gap = length;
//We initialize this as true to enter the while loop.
bool swapped = true;
while (gap != 1 || swapped == true)
{
gap = GetNextGap(gap);
//Set swapped as false. Will go to true when two values are swapped.
swapped = false;
//Compare all elements with current gap
for (int i = 0; i < length - gap; i++)
{
if (array[i] > array[i + gap])
{
//Swap
int temp = array[i];
array[i] = array[i + gap];
array[i + gap] = temp;
swapped = true;
}
}
}
}
public static void Main()
{
int[] array = { 10, 28, 1, 55, 6, 21, 36, 3, 45, 15, 0 };
Console.WriteLine("Comb Sort");
CommonFunctions.PrintInitial(array);
Sort(array);
CommonFunctions.PrintFinal(array);
Console.ReadLine();
}
}
### Time and Space Complexity
The worst case of _O(n2) _make intuitive sense, at least to me. Given that comb sort is based on bubble sort, we would expect poor time complexities for it. But the average case is interesting because it introduces a form of notation I hadn't seen before: big-omega.
Remember that the average time complexity for this algorithm is _Ω(n2/2p). _This is read aloud as "big-omega of n-squared over 2 to the power of p". But what does big-omega mean? In short, big-omega represents the best possible case of the complexity. On average, comb sort has been shown to perform no better than n2/2p, where _n_ is the length of the unsorted array and _p_ is the number of times we have to decrement the gap.
This is not a great time, and because it's the best possible case on average, we can conclude that Comb Sort is not an efficient sorting algorithm.
#exchange sorts #algorithms