Python - Sorting
Sorting
Sorting Algorithm | Best | Avg | Worst |
---|---|---|---|
Bubble Sort | \(O(n)\) | \(O(n^2)\) | \(O(n^2)\) |
Quick Sort | \(O(n\log{n})\) | \(O(n\log{n})\) | \(O(n^2)\) |
Merge Sort | \(O(n\log{n})\) | \(O(n\log{n})\) | \(O(n\log{n})\) |
Heapsort | \(O(n\log{n})\) | \(O(n\log{n})\) | \(O(n\log{n})\) |
Insertion Sort | \(O(n)\) | \(O(n^2)\) | \(O(n^2)\) |
Selection Sort | \(O(n^2)\) | \(O(n^2)\) | \(O(n^2)\) |
Bubble Sort
"""
1. adjacent elements ๋ผ๋ฆฌ ๋น๊ตํ๋ค.
2. ์ด๋ป๊ฒ sorted๊ฐ ๋์๋์ง ํ๋จํ๋๊ฐ(์ข
๋ฃ์กฐ๊ฑด)
2-1. ์ฒซ pass๋ฅผ ํต๊ณผํ๋ฉด ๋ง์ง๋ง ์์๋ ๋ฌด์กฐ๊ฑด ๊ฐ์ฅ ํฐ ์์๊ฐ ๋จ
2-2. ๋ฐ๋ผ์ pass ํ ๋๋ง๋ค ๋ค์์๋ถํฐ ์ ๋ ฌ์ด ๋๋ ์๊ณ ๋ฆฌ์ฆ
2-3. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์, pass ํ์ range๋ ๋ค์์๋ถํฐ 1์ฉ ์ค์ด๋ค๊ฒ ํ๋ฉด ๋๋ค. (์ด๊ฒ ํฌ์ธํธ โ)
2-4. ๋ฐ๋ผ์ ์ด์ค ๋ฐ๋ณต๋ฌธ ์ํํ์๋ ์ข
๋ฃ๊ฐ ๋๋ค. (์์ 2๊ฐ์ฉ ๋น๊ตํ๊ธฐ ๋๋ฌธ์)
2-5. ์์ชฝ ๋ฐ๋ณต๋ฌธ์ index 1๋ถํฐ ์์ํด์ range end ์ง์ ์ด 1์ฉ ์ค์ด์ผ ํ๋ค.
2-6. ๋น๊ตํ index๋ฅผ ํ๋ฆฐํธ ํด๋ณด๋ฉด ์ด๋ ๊ฒ ๋์์ผ ํ๋ค.
(0, 1) (1, 2) (2, 3) (3, 4)
(0, 1) (1, 2) (2, 3)
(0, 1) (1, 2)
(0, 1)
==========
index ์ค์ ์คํจ
์ด์ : i,j ๋๊ฐ๋ฅผ ๋์์ ํด์ผ๋๋ค๊ณ ์๊ฐํ๋ค.
ํ๋๋ง ํด์ผ๋๋ ์ด์ : ์ด์ฐจํผ adjacent์ด๊ธฐ ๋๋ฌธ์ ํ๋๋ฅผ ๊ธฐ์ค์ผ๋ก +1 ํด์ฃผ๋ฉด ๋๊ธฐ ๋๋ฌธ์ด๋ค.
=========
์ฌ์ค i์ ์ฉ๋๋ j๋ฅผ ๊ตฌํ๊ธฐ ์ํด ํ์ํ๋ ๊ฒ ์ด๋ค.
j๋ฅผ -1 ํด์ฃผ๋ ์ด์ ๋ adjacent์ด๊ธฐ ๋๋ฌธ์ j, j+1์์ ์ธ๋ฑ์ค๊ฐ ๋์ด๊ฐ ๋ฒ๋ฆฌ๊ธฐ ๋๋ฌธ์ด๋ค.
i๋ ์ํด์ ์๊ธฐํ ๋งจ ๋ง์ง๋ง ์์๋ค์ ํ๋์ฉ ์ค์ด๊ธฐ ์ํด ์ฌ์ฉ
==========
arr๋ก ๋์ด๊ฐ๊ธฐ ์ ์ ์ฌ๋ฐ๋ฅธ index ์์น๋ฅผ ๊ตํํ๋์ง ํ์ธํด ๋ณผ ๊ฒ.
"""
myList = list(map(int, input().split()))
# print(myList)
for i in range(len(myList)):
for j in range(len(myList)-i-1):
print((j, j+1))
if myList[j] > myList[j+1]: # need swap since the former is larger.
myList[j], myList[j+1] = myList[j+1], myList[j]
print(myList)
Quick Sort
- Divide and Conquer
"""
๊ธฐ์ค์ (pivot)์ ์ ํ๋ค.
---------------------------------------------------------------
๊ธฐ์ค์ ์ ํ๋ ๊ธฐ์ค
- Always pick first element as pivot.
- Always pick last element as pivot (implemented below)
- Pick a random element as pivot.
- Pick median as pivot.
์๋ง random์ด ์ ์ผ ์ข์ง ์์๊น?
---------------------------------------------------------------
๊ธฐ์ค์ ๋ณด๋ค ์์ ๋ฐ์ดํฐ๋ ์ผ์ชฝ, ํฐ ๋ฐ์ดํฐ๋ ์ค๋ฅธ์ชฝ์ผ๋ก
์ฌ๊ทํจ์๋ฅผ ์ฌ์ฉ(iterative ๋ฐฉ๋ฒ์?)
์ข
๋ฃ์กฐ๊ฑด: list์ ๊ธธ์ด๊ฐ 2๋ณด๋ค ์์ ๊ฒฝ์ฐ
=======================================================
random element ๋ฅผ pivot์ผ๋ก ํด์ ๊ตฌํํ ๊ฒฝ์ฐ
index error ๋ฐ์
random ์ผ๋ก ๊ตฌํํ ๊ฒฝ์ฐ ์ฒซ๋ฒ์งธ๋ ๋ง์ง๋ง ์์์ pivot ์์๋ฅผ ๊ตํํ ํ ๋๊ฐ์ด ์งํ
=======================================================
list๋ฅผ ์ฌ์ฉํด์ ์ฌ๊ทํธ์ถ์ ํ๋ ํํ์ ๊ตฌํ์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ ์ธก๋ฉด์์ ๋นํจ์จ์ ์
ํฐ ์ฌ์ด์ฆ์ ์
๋ ฅ์ด ๋ค์ด์์ ๊ฒฝ์ฐ ๋จ์ ์ด ํฌ๊ฒ ๋ถ๊ฐ๋จ
๋ฐ๋ผ์ in-place ์ ๋ ฌ์ด ์ ํธ๋๋ ์ด์ ์ด๋ค.
https://www.daleseo.com/sort-quick/
----------- list quick sort --------------
def quick_sort(arr):
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
lesser_arr, equal_arr, greater_arr = [], [], []
for num in arr:
if num < pivot:
lesser_arr.append(num)
elif num > pivot:
greater_arr.append(num)
else:
equal_arr.append(num)
return quick_sort(lesser_arr) + equal_arr + quick_sort(greater_arr)
===================================
optimized quick sort in-place implementation
https://www.geeksforgeeks.org/quick-sort/
=============================
Python QuickSort ์ต์ ํ์ ๋ฐ๋ฅธ ์๋
https://choiseokwon.tistory.com/233
"""
# This Function handles sorting part of quick sort
# start and end points to first and last element of
# an array respectively
import sys
sys.setrecursionlimit(2000)
def partition(start, end, array):
# Initializing pivot's index to start
pivot_idx = start
# This loop runs till start pointer crosses
# end pointer, and when it does we swap the
# pivot with element on end pointer
while start < end:
# Increment the start pointer till it finds an
# element greater than pivot
while start < len(array) and array[start] <= array[pivot_idx]:
start += 1
# Decrement the end pointer till it finds an
# element less than pivot
while array[end] > array[pivot_idx]:
end -= 1
# If start and end have not crossed each other,
# swap the numbers on start and end
if start < end:
array[start], array[end] = array[end], array[start]
# Swap pivot element with element on end pointer.
# This puts pivot on its correct sorted place.
# Returning end pointer to divide the array into 2
array[end], array[pivot_idx] = array[pivot_idx], array[end]
return end
# The main function that implements QuickSort
def quick_sort(start, end, array):
# if start and end is not overlapped, proceed.
if (start < end):
# p is partitioning index, array[p]
# is at right place
p = partition(start, end, array)
# Sort elements before partition
# and after partition
quick_sort(start, p-1, array)
quick_sort(p+1, end, array)
N = int(input())
array = [int(input()) for _ in range(N)]
# print(array)
# print(quick_sort(array))
quick_sort(0, len(array)-1, array)
# print(array)
for e in array:
print(e)
Merge Sort
"""
slice notation
slice ์ ๋ฐฐ์ด์ ๋ณต์ ๊ฐ ์ผ์ด๋๋ฏ๋ก ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ ํจ์จ ๋์จ
-------------------
1. ์๋์ฝ๋๋ณด๊ณ ๊ตฌํ
2. ์คํจ์, ์ฝ๋๋ณด๊ณ ์ฝ๋ฉํธ ๋ฌ๊ณ ์์ฑํด๋ณด๊ธฐ
3. ์ฌ๊ท๋ก ๊ตฌํ ์์ฑ
4. iterative version ๊ตฌํํ๊ธฐ
"""
"""
MergeSort(arr[], l, r)
If r > l
1. Find the middle point to divide the array into two halves:
middle m = l+ (r-l)/2
2. Call mergeSort for first half:
Call mergeSort(arr, l, m)
3. Call mergeSort for second half:
Call mergeSort(arr, m+1, r)
4. Merge the two halves sorted in step 2 and 3:
Call merge(arr, l, m, r)
# In-Place Merge Sort
<https://www.geeksforgeeks.org/in-place-merge-sort/>
# Iterative Merge Sort
<https://www.geeksforgeeks.org/iterative-merge-sort/>
"""
N = int(input())
array = [int(input()) for _ in range(N)]
# def mergeSort(arr):
# if len(arr) < 2:
# return arr
# mid = len(arr) // 2
# low_arr = mergeSort(arr[:mid])
# high_arr = mergeSort(arr[mid:])
# print(low_arr, high_arr, "######")
# merged_arr = []
# l = h = 0
# while l < len(low_arr) and h < len(high_arr):
# if low_arr[l] < high_arr[h]:
# merged_arr.append(low_arr[l])
# l += 1
# else:
# merged_arr.append(high_arr[h])
# h += 1
# merged_arr += low_arr[l:]
# merged_arr += high_arr[h:]
# print(merged_arr,' merged arr')
# return merged_arr
def mergeSort(arr):
if len(arr) > 1:
# Finding the mid of the array
mid = len(arr)//2
# Dividing the array elements
# into 2 halves
L = arr[:mid]
R = arr[mid:]
# Sorting the first half
mergeSort(L)
# Sorting the second half
mergeSort(R)
# Copy data to temp arrays L[] and R[]
i = j = k = 0
while i < len(L) and j < len(R):
if L[i] < R[j]:
arr[k] = L[i]
i += 1
else:
arr[k] = R[j]
j += 1
k += 1
# Checking if any element was left
while i < len(L):
arr[k] = L[i]
i += 1
k += 1
while j < len(R):
arr[k] = R[j]
j += 1
k += 1
mergeSort(array)
print(array)
"""
In-place Merge Sort
-------------------
* l is for left index and r is right index of
the sub-array of arr to be sorted
"""
def merge(arr, start, mid, end):
start2 = mid + 1
# If the direct merge is already sorted
if (arr[mid] <= arr[start2]):
return
# Two pointers to maintain start
# of both arrays to merge
while (start <= mid and start2 <= end):
# If element 1 is in right place
if (arr[start] <= arr[start2]):
start += 1
else:
value = arr[start2]
index = start2
# Shift all the elements between element 1
# element 2, right by 1.
while (index != start):
arr[index] = arr[index - 1]
index -= 1
arr[start] = value
# Update all the pointers
start += 1
mid += 1
start2 += 1
def mergeSort(arr, l, r):
if (l < r):
# Same as (l + r) / 2, but avoids overflow
# for large l and r
m = l + (r - l) // 2
# Sort first and second halves
mergeSort(arr, l, m)
mergeSort(arr, m + 1, r)
merge(arr, l, m, r)
"""
Iterative Merge Sort
"""
def merge(left, right):
if not len(left) or not len(right):
return left or right
result = []
i, j = 0, 0
while (len(result) < len(left) + len(right)):
if left[i] < right[j]:
result.append(left[i])
i+= 1
else:
result.append(right[j])
j+= 1
if i == len(left) or j == len(right):
result.extend(left[i:] or right[j:])
break
return result
def mergesort(list):
if len(list) < 2:
return list
middle = int(len(list)/2)
left = mergesort(list[:middle])
right = mergesort(list[middle:])
return merge(left, right)
Heap Sort
"""
1. ์๋์ฝ๋๋ณด๊ณ ๊ตฌํ
2. ์คํจ์, ์ฝ๋๋ณด๊ณ ์ฝ๋ฉํธ ๋ฌ๊ณ ์์ฑํด๋ณด๊ธฐ
3. ์ฌ๊ท๋ก ๊ตฌํ ์์ฑ
4. iterative version ๊ตฌํํ๊ธฐ
----------------------------------------
https://www.geeksforgeeks.org/heap-sort/
----------------------------------------
__author__ = 'Minsuk Heo'
#=======================================================================
# Title: Heapsort
#
# Statement:
# Given a disordered list of integers (or any other items),
# rearrange the integers in natural order.
#
# Sample Input: [8,5,3,1,9,6,0,7,4,2,5]
# Sample Output: [0,1,2,3,4,5,5,6,7,8,9]
#
# Time Complexity of Solution:
# Best O(nlog(n)); Average O(nlog(n)); Worst O(nlog(n)).
#
# Approach:
# Heap sort happens in two phases. In the first phase, the array
# is transformed into a heap. A heap is a binary tree where
# 1) each node is greater than each of its children
# 2) the tree is perfectly balanced
# 3) all leaves are in the leftmost position available.
# In phase two the heap is continuously reduced to a sorted array:
# 1) while the heap is not empty
# - remove the top of the head into an array
# - fix the heap.
# Heap sort was invented by John Williams not by B. R. Heap.
#
# MoveDown:
# The movedown method checks and verifies that the structure is a heap.
#
# Technical Details:
# A heap is based on an array just as a hashmap is based on an
# array. For a heap, the children of an element n are at index
# 2n+1 for the left child and 2n+2 for the right child.
#
# The movedown function checks that an element is greater than its
# children. If not the values of element and child are swapped. The
# function continues to check and swap until the element is at a
# position where it is greater than its children.
#=======================================================================
# ๋ง์ง๋ง์ ์๋ ๋
ธ๋๋ถํฐ ์ํํ๋ฉด์ swapํ๋ฉด ๋๋๋ฐ,
# leaf ๋
ธ๋(์์๋
ธ๋๊ฐ ์๋)์ ๊ฒฝ์ฐ๋ ํ์์๊ธฐ ๋๋ฌธ์,
# p์ ๊ฐ์ ์๋์ ๊ฐ์ด ์ค์ ํจ์ผ๋ก์จ(์ด์งํธ๋ฆฌ์ ํน์ง์ ํ์ฉ)
# leaf ๋
ธ๋์ parent ๋
ธ๋ ์ค์์ ๋ง์ง๋ง index๋ถํฐ ์์์ ํ๋ค.
# p๋ฅผ ๊ตฌํ์ผ๋ ์ด์ siftdown์ ์ํํ๋ค.
# ----------------------------------
# "siftdown"
# 1. ํ์ฌ ๋
ธ๋์ child node ์ ๊ฐ์ด ํ์ฌ node์ ๊ฐ๋ณด๋ค ํฌ๋ค๋ฉด SWAP
# 1-1. swap ํ์ ๋ถ๋ชจ ๋
ธ๋์๋ค๊ฐ ์์๋
ธ๋๋ก ๋ฐ๋ ๋
ธ๋์ ๋ํด ์์๋
ธ๋๋ฅผ ๋ค์ ํ์ธํ๋ ๊ฒ์ ๋ฐ๋ณต.
"""
def heapsort(a):
def siftdown(a, i, size):
l = 2*i + 1
r = 2*i + 2
largest = i
if l <= size-1 and a[l] > a[i]:
largest = l
if r <= size-1 and a[r] > a[largest]: # ์์๋
ธ๋ 2๊ฐ์ค ํฐ ๊ฒ์ largest ๋ณ์์ ๋ฃ์ด์ผ ํ๊ธฐ ๋๋ฌธ์, r์์๋ largest์ r์ ๋น๊ต
largest = r
if largest != i: # largest๊ฐ i์ ๋ค๋ฅด๋ค๋ฉด, ์ฆ, largest๊ฐ ๋ณ๊ฒฝ๋์๋ค๋ฉด, swap์ ํด์ฃผ๊ณ siftdown
# SWAP
a[i], a[largest] = a[largest], a[i]
siftdown(a, largest, size)
def heapify(a, size):
p = (size//2)-1
while p>=0:
siftdown(a, p, size)
p -= 1
size = len(a)
heapify(a, size) # MAX HEAP
end = size-1
while(end > 0):
# root์ end๋ฅผ swap ํด์ค ํ
# root๋ฅผ siftdown ํด์ฃผ๋ฉด ์ ๋ ฌ์ด ๋๋ค.
# (swap๋ ๋
ธ๋(root์์ swapํ์ผ๋ฏ๋ก ํ์ฌ๋ end๋
ธ๋)๋ siftdown์์ ๋ฐฐ์ ๋ ์ํ๋ก siftdown ์งํ๋๋ค.)
# (root๋ heapify๋ ํ ์ด๋ฏ๋ก ์ต๊ณ ํน์ ์ต์์ด๊ธฐ ๋๋ฌธ์)
a[0], a[end] = a[end], a[0]
siftdown(a, 0, end) # root node ๋ถํฐ siftdown์ ์งํ
end -= 1
arr = [1,3,2,4,9,7]
heapsort(arr)
print(arr)
Leave a comment