刚接触编程的同学可以看看的几个编程练习(python实现)(五)

本大白最近带一只小白入手编程,想法是在练习中学习,所以弄了几个题目。其中不少是经典的练习题,在很多编程入门书籍中都有出现;有的题涉及到一点数据结构的理念。在这里分享出来,刚接触编程的同学可以和我们一起做一做(无论学的是哪种语言都可以看一看,思路是通用的。这里我们学的是python),也欢迎大家指正。

24. 排序

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实现)(六)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值