本大白最近带一只小白入手编程,想法是在练习中学习,所以弄了几个题目。其中不少是经典的练习题,在很多编程入门书籍中都有出现;有的题涉及到一点数据结构的理念。在这里分享出来,刚接触编程的同学可以和我们一起做一做(无论学的是哪种语言都可以看一看,思路是通用的。这里我们学的是python),也欢迎大家指正。
1. 选择排序
设数据列表长度为n, 第一轮将0位置的数据不断与1至n-1位置的数据进行比较,这个过程中不断将较小的数放于0位置,这样经第一轮比较后最小的数放在了0位置; 第二轮类似地将1位置的数据不断与2至n-1位置的数据进行比较,这样第二小的数放在了1位置;依此进行n-1轮,完成排序。
def choose_sort(number_list):
n = len(number_list)
for i in range(n-1):
for j in range(i+1, n):
if number_list[j] < number_list[i]:
temp = number_list[i]
number_list[i] = number_list[j]
number_list[j] = temp
x = [20, 20, 2, 3, 2, 5, 6, 1, -2, 3, 14, 12, 3, -1, -1]
choose_sort(x)
print(x)
选择排序也可以用递归的方法完成
def choose_sort_recursive(number_list, low=0, high=0):
high = len(number_list) - 1
if low < high:
index_of_min = low
min = number_list[low]
for i in range(low+1, high+1):
if number_list[i] < min:
index_of_min = i
min = number_list[i]
number_list[index_of_min] = number_list[low]
number_list[low] = min
choose_sort_recursive(number_list, low+1, high)
x = [20, 20, 2, 3, 2, 5, 6, 1, -2, 3, 14, 12, 3, -1, -1]
choose_sort_recursive(x)
print(x)
2. 插入排序
第一轮排好前1个数(即0位置的数, 当然此时只有一个数,无需比较即完成),第二轮排好前2个数(即0-1位置的数),第三轮排好前3个数(即0-2位置的数);依此进行n轮,完成排序。
def insert_sort(number_list):
n = len(number_list)
for i in range(n):
current = number_list[i]
for j in range(i-1, -1, -1):
if current < number_list[j]:
number_list[j + 1] = number_list[j]
number_list[j] = current
x = [20, 20, 2, 3, 2, 5, 6, 1, -2, 3, 14, 12, 3, -1, -1]
insert_sort(x)
print(x)
3. 冒泡排序
第一轮最大的数放到底(即放在n-1位置),第二轮次大的数放在n-2位置;依此进行n-1轮,完成排序。就像泡泡不断冒出一样,故称为冒泡排序。
def bubble_sort(number_list):
n = len(number_list)
for i in range(n - 1):
for j in range(n - i - 1):
if number_list[j] > number_list[j + 1]:
temp = number_list[j]
number_list[j] = number_list[j + 1]
number_list[j + 1] = temp
x = [20, 20, 2, 3, 2, 5, 6, 1, -2, 3, 14, 12, 3, -1, -1]
bubble_sort(x)
print(x)
可对冒泡排序进行改进,若在某一轮中已完成排序,即无数据位置的变动,那么不需要再进行其余轮次的比较了。
def bubble_sort_improve(number_list):
n = len(number_list)
nextRound = True
if nextRound:
for i in range(n - 1):
nextRound = False
for j in range(n - i - 1):
if number_list[j] > number_list[j + 1]:
temp = number_list[j]
number_list[j] = number_list[j + 1]
number_list[j + 1] = temp
nextRound = True
x = [20, 20, 2, 3, 2, 5, 6, 1, -2, 3, 14, 12, 3, -1, -1]
bubble_sort_improve(x)
print(x)
关于选择排序、插入排序、冒泡排序,可以参考java实现一个选择、冒泡、插入排序的简单演示器,我在那里编写了一个简单的动态演示器。
4. 归并排序*
这是一个递归的过程。将n个数分为左、右两部分,每个部分分别进行排序,再将已排好序的左右两部分进行“整合排序”,就完成了最终的排序。这样分割的部分排序呢?使用同样的方法,将其分割、分别排序、整合排序,即一个递归的过程。
# 递归过程
def merge_sort(number_list):
if len(number_list) > 1:
mid = int(len(number_list) / 2)
left = number_list[:mid]
right = number_list[mid:]
merge_sort(left)
merge_sort(right)
merge(left, right, number_list)
# 整合排序
def merge(left, right, list):
index_left = 0
index_right = 0
index_list = 0
while index_left < len(left) and index_right < len(right):
if left[index_left] < right[index_right]:
list[index_list] = left[index_left]
index_list += 1
index_left += 1
else:
list[index_list] = right[index_right]
index_list += 1
index_right += 1
while index_left < len(left):
list[index_list] = left[index_left]
index_list += 1
index_left += 1
while index_right < len(right):
list[index_list] = right[index_right]
index_list += 1
index_right += 1
x = [20, 20, 2, 3, 2, 5, 6, 1, -2, 3, 14, 12, 3, -1, -1]
merge_sort(x)
print(x)
这里我的例子是二路归并,即每次分割为两部分,当然也可进行多路归并,每次分割成多部分。
5. 快速排序*
这是一个递归的过程。选择某个数作为关键数(pivot),这里我们选取第一个数作为关键数,然后将其放在它“应该在的位置”,即该位置左边的数都不大于它,该位置右边的数都不小于它。这样列表分为三个部分:左部分、已放好的关键数、右部分。对左部分即右部分,使用同样的方法排序,即选关键数,并将其放在应该在的位置,即一个递归过程。
def quick_sort(number_list, low, high):
if low < high:
pivot_index = divide(number_list, low, high)
quick_sort(number_list, low, pivot_index-1)
quick_sort(number_list, pivot_index+1, high)
def divide(number_list, low, high):
pivot = number_list[low]
pivot_index = low + 1
while pivot_index <= high:
if number_list[pivot_index] < pivot:
pivot_index += 1
else:
if number_list[high] >= pivot:
high -= 1
else:
temp = number_list[pivot_index]
number_list[pivot_index] = number_list[high]
number_list[high] = temp
pivot_index += 1
high -= 1
number_list[low] = number_list[pivot_index-1]
number_list[pivot_index-1] = pivot
return pivot_index-1
x = [20, 20, 2, 3, 2, 5, 6, 1, -2, 3, 14, 12, 3, -1, -1]
quick_sort(x, 0, len(x)-1)
print(x)
6. 堆排序*
我们定义这样的一个二叉树结构:,每个结点的数都不小于它的子树中的数;不是最后一次层的层必须铺满,最后一层可以不铺满但必须“向左对齐”;
我们向树中添加或者删除数时,都必须进行调整以保证树的结构满足要求。这样的树中,顶点的数是最大的,因此我们将一组数添加到这样的树结构中后,不断地获取顶点的数。由于每次获取后,树的结构都将进行调整,所以我们获取的数即是由大到小排序的了。
我们可以用列表(数组)表示这样的二叉树:0位置表示第一层,1-2位置表示第二层,3-6位置表示第三层……。这样i位置的数在树结构中的左右孩子(如果存在的话)分别位于2*i+1和2*i+2位置;j位置的数在树结构中的父结点位于(j-1)/2位置。
我们定义一个类,类中的列表用来表示树,并定义相应的函数用于向树中添加或者移除数。
class Heap():
def __init__(self, number_list):
self.number_list = []
for num in number_list:
self.add(num)
def add(self, num):
self.number_list.append(num)
current = self.get_size() - 1
while current > 0:
parent = int((current - 1) / 2)
if (self.number_list[current]
> self.number_list[parent]):
temp = self.number_list[current]
self.number_list[current] = self.number_list[parent]
self.number_list[parent] = temp
current = parent
else:
break
def remove(self):
if self.get_size() == 0:
return
max = self.number_list[0]
if self.get_size() > 1:
self.number_list[0] = self.number_list.pop()
elif self.get_size() == 1:
self.number_list.pop()
current = 0
while current < self.get_size():
left = 2 * current + 1
right = 2 * current + 2
if left >= self.get_size():
break
index_max = left
if right < self.get_size():
if self.number_list[right] > self.number_list[left]:
index_max = right
if self.number_list[current] < self.number_list[index_max]:
temp = self.number_list[current]
self.number_list[current] = self.number_list[index_max]
self.number_list[index_max] = temp
current =index_max
else:
break
return max
def get_size(self):
return len(self.number_list)
def get_list(self):
return self.number_list
x = [20, 20, 2, 3, 2, 5, 6, 1, -2, 3, 14, 12, 3, -1, -1]
x_heap = Heap(x)
for i in range(len(x) - 1, -1, -1):
x[i] = x_heap.remove()
x
7. 桶排序*
桶排序可用来对非负整数进行排序。设一组非负整数中最大的值为k,我们建立k+1个桶并按序编号。遍历这组非负整数,若数大小为i,则将其放入i号桶中。最后按序从桶中依次取出所有的数,即完成排序。
def bucket_sort(number_list):
bucket = [[]]
size = max(number_list)
for i in range(size):
bucket.append([])
for integer in number_list:
bucket[integer].append(integer)
for i in range(len(number_list) - 1):
number_list[i] = -1
count = 0
for i in bucket:
for j in i:
number_list[count] = j
count += 1
x = [25, 25, 7, 8, 7, 10, 11, 6, 3, 8, 19, 17, 8, 4, 4]
bucket_sort(x)
x
我们可以比较不同算法的排序时间,以及python列表自带排序函数的排序时间。
####### 比较不同算法的效率
import random
import time
NUMBER = 10000
large_list = []
for i in range(NUMBER):
large_list.append(int(random.uniform(0, 1)*100000)
)
# 选择排序
choose_list = large_list[:]
start_time = int(round(time.time()))
choose_sort(choose_list)
end_time = int(round(time.time()))
choose_sort_time = end_time - start_time
# 插入排序
insert_list = large_list[:]
start_time = int(round(time.time()))
insert_sort(insert_list)
end_time = int(round(time.time()))
insert_sort_time = end_time - start_time
# 冒泡排序
bubble_list = large_list[:]
start_time = int(round(time.time()))
bubble_sort(bubble_list)
end_time = int(round(time.time()))
bubble_sort_time = end_time - start_time
# 改进的冒泡排序
bubble_improve_list = large_list[:]
start_time = int(round(time.time()))
bubble_sort_improve(bubble_improve_list)
end_time = int(round(time.time()))
bubble_sort_improve_time = end_time - start_time
# 归并排序
NUMBER = 100000
large_list = []
for i in range(NUMBER):
large_list.append(int(random.uniform(0, 1)*100000)
)
merge_list = large_list[:]
start_time = int(round(time.time()) * 1000)
merge_sort(merge_list)
end_time = int(round(time.time()) * 1000)
merge_sort_time = end_time - start_time
# 快速排序
quick_list = large_list[:]
start_time = int(round(time.time()) * 1000)
quick_sort(quick_list, 0, len(merge_list)-1)
end_time = int(round(time.time()) * 1000)
quick_sort_time = end_time - start_time
# 堆排序
heap_list = large_list[:]
start_time = int(round(time.time()) * 1000)
list_heap = heap.Heap(heap_list)
for i in range(len(heap_list) - 1, -1, -1):
heap_list[i] = list_heap.remove()
end_time = int(round(time.time()) * 1000)
heap_sort_time = end_time - start_time
# 自带排序
list2 = large_list[:]
start_time = int(round(time.time()) * 1000)
list2.sort()
end_time = int(round(time.time()) * 1000)
self_sort_time = end_time - start_time
print("choose_sort: " + str(choose_sort_time) + " seconds")
print("insert_sort: " + str(insert_sort_time) + " seconds")
print("bubble_sort: " + str(bubble_sort_time) + " seconds")
print("bubble_sort_imporove: " + str(bubble_sort_improve_time) + " seconds")
print("merge_sort: " + str(merge_sort_time) + " milliseconds")
print("quick_sort: " + str(quick_sort_time) + " milliseconds")
print("heap_sort: " + str(heap_sort_time) + " milliseconds")
print("self_sort: " + str(self_sort_time) + " milliseconds")
后续部分请见 刚接触编程的同学可以看看的几个编程练习(python实现)(六)