Skip to content

Commit 88b6c66

Browse files
author
shawn
committed
algorithm daily
0 parents  commit 88b6c66

File tree

3 files changed

+221
-0
lines changed

3 files changed

+221
-0
lines changed

BinarySearch.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
2+
3+
def binary_search(arr, target):
4+
left, right = 0, len(arr) - 1
5+
while left <= right:
6+
mid = left + (right - left) // 2
7+
if arr[mid] == target:
8+
return mid
9+
elif arr[mid] < target:
10+
left = mid + 1
11+
else:
12+
right = mid - 1
13+
return -1 # 未找到
14+
15+
if __name__ == "__main__":
16+
data = [1, 3, 5, 7, 9, 11, 13, 15]
17+
target1 = 7
18+
target2 = 4
19+
20+
index1 = binary_search(data, target1)
21+
index2 = binary_search(data, target2)
22+
23+
print(f"查找 {target1} 的结果: {index1}")
24+
print(f"查找 {target2} 的结果: {index2}")

DynamicProgramming.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
2+
3+
4+
def fibonacci(n):
5+
# This function calculates the nth Fibonacci number using dynamic programming.
6+
# It builds up a table of results for all numbers up to n, so we don't repeat work.
7+
if n <= 0:
8+
# If n is 0 or negative, return 0 (base case)
9+
return 0
10+
if n == 1:
11+
# If n is 1, return 1 (base case)
12+
return 1
13+
# Create a list to store Fibonacci numbers up to n
14+
dp = [0] * (n + 1)
15+
dp[0], dp[1] = 0, 1 # Set the first two Fibonacci numbers
16+
for i in range(2, n + 1):
17+
# For each number from 2 to n, calculate its Fibonacci value
18+
# by adding the two previous Fibonacci numbers
19+
dp[i] = dp[i - 1] + dp[i - 2]
20+
# Return the nth Fibonacci number
21+
return dp[n]
22+
23+
if __name__ == "__main__":
24+
# This block will only run if the script is executed directly (not imported)
25+
# We'll print the first 10 Fibonacci numbers to show how our function works.
26+
for i in range(10):
27+
# For each number from 0 to 9, calculate and print its Fibonacci number
28+
print(f"F({i}) = {fibonacci(i)}")

SortComparison.py

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
2+
3+
4+
"""
5+
Sorting comparison demo in Python.
6+
We benchmark several classic sorting algorithms on the same random data
7+
and print how long each one takes. Comments are intentionally informal
8+
to make the code easier to read.
9+
"""
10+
11+
import random
12+
import copy
13+
import time
14+
15+
#
16+
# Bubble Sort: This is mainly used for teaching purposes and is almost never used in real-world code.
17+
# It's very simple and easy to understand, but extremely slow for large datasets.
18+
# Only use this if you want to demonstrate how sorting works step by step.
19+
# It works by repeatedly swapping adjacent out-of-order elements until the whole list is sorted.
20+
def bubble_sort(arr):
21+
n = len(arr)
22+
# After each pass, the largest element "bubbles" to the end.
23+
for i in range(n):
24+
for j in range(0, n - i - 1):
25+
# If current item is bigger than the next one, swap them.
26+
if arr[j] > arr[j + 1]:
27+
arr[j], arr[j + 1] = arr[j + 1], arr[j]
28+
29+
#
30+
# Merge Sort: Use this when you need stable sorting and guaranteed O(n log n) performance, even in the worst case.
31+
# It's great for sorting large datasets, can be parallelized, and works well for external sorting (e.g., sorting data on disk).
32+
# Merge sort splits the list, sorts each half, then merges them back in order.
33+
def merge_sort(arr):
34+
if len(arr) > 1:
35+
mid = len(arr) // 2
36+
L = arr[:mid]
37+
R = arr[mid:]
38+
# Recursively sort the left and right halves.
39+
merge_sort(L)
40+
merge_sort(R)
41+
i = j = k = 0
42+
# Merge the two sorted halves back into arr.
43+
while i < len(L) and j < len(R):
44+
if L[i] < R[j]: # Take the smaller head element first
45+
arr[k] = L[i]
46+
i += 1
47+
else:
48+
arr[k] = R[j]
49+
j += 1
50+
k += 1
51+
# Copy any leftovers from L
52+
while i < len(L):
53+
arr[k] = L[i]
54+
i += 1
55+
k += 1
56+
# Copy any leftovers from R
57+
while j < len(R):
58+
arr[k] = R[j]
59+
j += 1
60+
k += 1
61+
62+
#
63+
# Quick Sort (in-place version): This is usually the fastest sorting algorithm on average for in-memory arrays.
64+
# This version sorts the array in place, which is more memory efficient and closer to how real-world quicksort is implemented.
65+
# It uses the Lomuto partition scheme.
66+
def partition(arr, low, high):
67+
# Lomuto partition: pick the last element as pivot
68+
pivot = arr[high]
69+
i = low - 1
70+
for j in range(low, high):
71+
if arr[j] < pivot:
72+
i += 1
73+
arr[i], arr[j] = arr[j], arr[i]
74+
arr[i + 1], arr[high] = arr[high], arr[i + 1]
75+
return i + 1
76+
77+
def quick_sort_inplace(arr, low, high):
78+
# Conversational: This is the in-place quick sort version, more memory efficient, and closer to what real-world libraries use.
79+
if low < high:
80+
pi = partition(arr, low, high)
81+
# Recursively sort elements before and after partition
82+
quick_sort_inplace(arr, low, pi - 1)
83+
quick_sort_inplace(arr, pi + 1, high)
84+
85+
#
86+
# Insertion Sort: This is a great choice for very small arrays or arrays that are already nearly sorted.
87+
# It's simple and has low overhead, so it's often used as a base case in hybrid sorting algorithms.
88+
# It works by taking the next item and inserting it into the sorted left side.
89+
def insertion_sort(arr):
90+
for i in range(1, len(arr)):
91+
key = arr[i]
92+
j = i - 1
93+
# Shift larger items on the left to the right
94+
while j >= 0 and arr[j] > key:
95+
arr[j + 1] = arr[j]
96+
j -= 1
97+
# Place the key in its correct spot
98+
arr[j + 1] = key
99+
100+
#
101+
# Heap Sort: Use this when you need guaranteed O(n log n) performance and want to sort in place with minimal extra memory.
102+
# It's good when memory is tight, but it's usually a bit slower than quick sort or merge sort in practice.
103+
# Heap sort builds a max-heap, then repeatedly moves the max element to the end.
104+
def heapify(arr, n, i):
105+
# Find the largest among root, left child, and right child
106+
largest = i
107+
l = 2 * i + 1 # Left child index
108+
r = 2 * i + 2 # Right child index
109+
if l < n and arr[l] > arr[largest]:
110+
largest = l
111+
if r < n and arr[r] > arr[largest]:
112+
largest = r
113+
# If the largest isn't the parent, swap and continue heapifying
114+
if largest != i:
115+
arr[i], arr[largest] = arr[largest], arr[i]
116+
heapify(arr, n, largest)
117+
118+
def heap_sort(arr):
119+
n = len(arr)
120+
# Build a max-heap (rearrange array)
121+
for i in range(n // 2 - 1, -1, -1):
122+
heapify(arr, n, i)
123+
# Extract elements one by one, moving max to the end
124+
for i in range(n - 1, 0, -1):
125+
arr[0], arr[i] = arr[i], arr[0]
126+
heapify(arr, i, 0)
127+
128+
if __name__ == "__main__":
129+
# Generate the same random data for all algorithms so it's a fair race.
130+
n = 20000
131+
data = [random.randint(0, 1000000) for _ in range(n)]
132+
133+
# Use deep copies so each algorithm gets identical input.
134+
arr1 = copy.deepcopy(data)
135+
arr2 = copy.deepcopy(data)
136+
arr3 = copy.deepcopy(data)
137+
arr4 = copy.deepcopy(data)
138+
arr5 = copy.deepcopy(data)
139+
140+
# Time bubble sort
141+
start = time.time()
142+
bubble_sort(arr1)
143+
end = time.time()
144+
# Convert seconds to milliseconds for easier reading.
145+
print("Bubble Sort time:", (end - start) * 1000, "ms")
146+
147+
# Time merge sort
148+
start = time.time()
149+
merge_sort(arr2)
150+
end = time.time()
151+
print("Merge Sort time:", (end - start) * 1000, "ms")
152+
153+
# Time quick sort (in-place version)
154+
start = time.time()
155+
quick_sort_inplace(arr3, 0, len(arr3) - 1)
156+
end = time.time()
157+
print("Quick Sort time:", (end - start) * 1000, "ms")
158+
159+
# Time insertion sort
160+
start = time.time()
161+
insertion_sort(arr4)
162+
end = time.time()
163+
print("Insertion Sort time:", (end - start) * 1000, "ms")
164+
165+
# Time heap sort
166+
start = time.time()
167+
heap_sort(arr5)
168+
end = time.time()
169+
print("Heap Sort time:", (end - start) * 1000, "ms")

0 commit comments

Comments
 (0)