- 冒泡排序:
- 算法分析:
对一组数据两两进行比较, 如果左边小于右边,则交换,这样每次将最大的一个数放在最后,即将大数冒出。对于N个数,一共需要N-1轮, 每一轮次需要比较N-1-(轮数)次。这里我用到了一个优化,例如8, 2, 3, 5, 7这一组数,第一次排序过后将大数挪至最后,就变成:2, 3, 5, 7, 8;就已经排好序了,就无需在进行接下来的循环比较了, 所以在每一轮次循环比较的时候, 设置一个标识, 当没有可交换的数时, 即为排好了, 就退出,节省时间。
- 算法实现:
- 选择排序:
- 算法分析:
选择排序是每次在数组中选择一个最小的数放在对应位置上,即第一选择的是整个数组中最小的数,和第一位交换,第二次在剩下的数中选择一个最小的和第二位交换,以此类推,相比较冒泡排序,他少了很多比较交换的次数,因此比冒泡排序快。
- 算法实现:
- 插入排序:
- 算法分析:
插入排序的思想就是在已排好的序列中,将数插入到合适的位置,就跟理扑克牌一样。算法实现上,开始将数组划分为两个部分,第一个数作为已排好的的序列,第二个数往后为待插入的序列。每次选择出一个待插入数,依次向前面已排好的序列作比较,若待插入数与当前比较的数小,则将当前数后移,直到找到一个比他还小的数,就将当前数插入到该位置。
- 算法实现:
- 快速排序:
- 算法分析:
第一步,选择一个数作为基准,将所有比基准还小的数放在基准的左边,比基准大的数放在基准右边,这样就把数组划分为了两部分,第二步,对前一部分和后一部分进行递归划分,直到有序。
- 算法实现:
- 所有算法实现代码(python):
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File : BubbleSort.py
# @Author: deng
# @Date : 2018/11/29 10:30
# @Desc :
import time
import numpy as np
import psutil
import matplotlib.pyplot as plt
class Sort(object):
"""排序类的基类"""
def __init__(self, desc=False, show=True, name="Sort"):
self.arr = None # 待排序的数组
self.desc = desc # 是否按照降序
self.show = show # 是否显示排序结果及详细
self.arr_size = 0 # 数组大小
self.name = name # 排序名称
self.time = None # 所用时间
self.memory = None # 内存占用情况
def get_time(self):
return self.time
def sorted(self, arr):
pass
def descSort(self):
for i in range(self.arr_size // 2):
head, tail = 0, self.arr_size - 1
self.arr[head], self.arr[tail] = self.arr[tail], self.arr[head]
head += 1
tail -= 1
def describe(self):
# print("---排序结果---")
# print(self.arr)
descb = {"排序名称": self.name, "数据规模": self.arr_size, "耗时": self.time, "内存": self.memory}
print(descb)
class BubbleSort(Sort):
"""冒泡排序"""
def __init__(self, desc=False, show=True):
Sort.__init__(self, desc, show, "BubbleSort")
def sorted(self, arr):
self.arr = arr
self.arr_size = len(arr)
self.bubSort()
# 如果是降序
if self.desc:
self.descSort()
if self.show:
self.describe()
def bubSort(self):
"""排序的具体算法"""
start_time = time.time()
if self.arr_size > 0:
for i in range(1, self.arr_size):
"""需要比较的轮数, 10个数需要比较9次, 一次类推"""
# 标识有没有可交换的数,初始为False
exchange = False
for j in range(self.arr_size - i):
"""每一轮需要交换的次数"""
if self.arr[j] > self.arr[j + 1]:
# 交换
self.arr[j], self.arr[j + 1] = self.arr[j + 1], self.arr[j]
exchange = True
# 当没有可交换的数时,退出循环
if not exchange:
break
end_time = time.time()
self.time = end_time - start_time # 计算耗时
# 计算内存
self.memory = round(psutil.virtual_memory().used/1024/1024/1024, 3)
class SelectSort(Sort):
"""选择排序"""
def __init__(self, desc=False, show=True):
Sort.__init__(self, desc, show, name="SelectSort")
def sorted(self, arr):
"""具体算法"""
self.arr = arr
self.arr_size = len(arr)
start_time = time.time()
for i in range(0, self.arr_size):
# 每次假定当前值为最小值
index = i
for j in range(i+1, self.arr_size):
"""遍历找到一个最小的"""
if self.arr[j] < self.arr[index]:
index = j
# 交换
self.arr[i], self.arr[index] = self.arr[index], self.arr[i]
end_time = time.time()
self.time = end_time - start_time # 计算耗时
self.memory = round(psutil.virtual_memory().used / 1024 / 1024 / 1024, 3)
if self.desc:
self.descSort()
if self.show:
self.describe()
class InsertSort(Sort):
"""插入排序"""
def __init__(self, desc=False, show=True):
Sort.__init__(self, desc, show, name="InsertSort")
def sorted(self, arr):
self.arr = arr
self.arr_size = len(arr)
start_time = time.time()
# 从第二个数开始往前面的进行插入
for i in range(1, self.arr_size):
insert = self.arr[i] # 待插入的数
j = i - 1
# 在前面已排好的数中找到插入位置
while j >= 0 and self.arr[j] > insert:
self.arr[j+1] = self.arr[j]
j -= 1
self.arr[j+1] = insert
end_time = time.time()
self.time = end_time - start_time # 计算耗时
self.memory = round(psutil.virtual_memory().used / 1024 / 1024 / 1024, 3)
if self.desc:
self.descSort()
if self.show:
self.describe()
class QuickSort(Sort):
"""快速排序"""
def __init__(self, desc=False, show=True, name="QuickSort"):
Sort.__init__(self, desc, show, name)
# 划分区域
def partiton(self, low, high):
# 选择第一个数为基准
key = self.arr[low]
while low < high:
# 从后往前搜索,把所有比基准小的数放到基准的左边
while low < high and self.arr[high] >= key:
high -= 1
if low < high: # 交换
self.arr[low], self.arr[high] = self.arr[high], self.arr[low]
# 从前往后搜索,把所有比基准大的数放在基准右边
while low < high and self.arr[low] <= key:
low += 1
if low < high:
self.arr[high], self.arr[low] = self.arr[low], self.arr[high]
# 划分完成后就把数组分为了两部分,返回基准所在的位置, 即左边都是比基准小的数,右边都是比基准大的数
return low
def quickSort(self, low, high):
if low >= high:
return
# 划分区域后返回基准的位置
center = self.partiton(low, high)
# 递归对左边在进行划分
self.quickSort(low, center - 1)
# 递归对右边在进行划分
self.quickSort(center + 1, high)
def sorted(self, arr):
self.arr = arr
# 开始时间
self.arr_size = len(arr)
start_time = time.time()
self.quickSort(0, self.arr_size - 1)
# 结束时间
end_time = time.time()
self.time = end_time - start_time # 计算耗时
self.memory = round(psutil.virtual_memory().used / 1024 / 1024 / 1024, 3)
if self.desc:
self.descSort()
if self.show:
self.describe()
if __name__ == '__main__':
# 测试的数据规模
temp = [i for i in range(10, 1000, 10)]
size = [i for i in range(1000, 21000, 1000)]
size = temp+size
# 画图用的
color = ['r', 'g', 'c', 'b']
# 创建各个排序对象
bs = BubbleSort()
ss = SelectSort()
Is = InsertSort()
qs = QuickSort()
# 放到集合里
objs = [qs, ss, Is, bs]
# 测试排序
for obj, c in zip(objs, color):
times = []
for i in size:
# 初始随机数 i 为数据规模大小
num = np.random.randint(1, 100000, i)
obj.sorted(num)
times.append(obj.get_time())
# 删除随机数组,防止内存溢出
del num
# 标注坐标轴
plt.xlabel("size")
plt.ylabel("time")
# 画图
plt.plot(size, times, "-", color=c, label=str(obj.name))
plt.legend(loc="upper left")
plt.grid(True)
plt.show()
- 运行结果:
D:\Anaconda\python.exe E:/我的程序设计/Python/PythonProject/homework/Sort/Sort.py
{'排序名称': 'QuickSort', '数据规模': 10, '耗时': 0.0, '内存': 3.571}
{'排序名称': 'QuickSort', '数据规模': 100, '耗时': 0.0010030269622802734, '内存': 3.571}
{'排序名称': 'QuickSort', '数据规模': 1000, '耗时': 0.00601649284362793, '内存': 3.571}
{'排序名称': 'QuickSort', '数据规模': 10000, '耗时': 0.09826040267944336, '内存': 3.575}
{'排序名称': 'QuickSort', '数据规模': 20000, '耗时': 0.16748738288879395, '内存': 3.576}
{'排序名称': 'SelectSort', '数据规模': 10, '耗时': 0.0, '内存': 3.584}
{'排序名称': 'SelectSort', '数据规模': 100, '耗时': 0.001001596450805664, '内存': 3.584}
{'排序名称': 'SelectSort', '数据规模': 1000, '耗时': 0.14438295364379883, '内存': 3.584}
{'排序名称': 'SelectSort', '数据规模': 10000, '耗时': 14.381277799606323, '内存': 3.585}
{'排序名称': 'SelectSort', '数据规模': 20000, '耗时': 56.96345281600952, '内存': 3.562}
{'排序名称': 'InsertSort', '数据规模': 10, '耗时': 0.0, '内存': 3.562}
{'排序名称': 'InsertSort', '数据规模': 100, '耗时': 0.0010035037994384766, '内存': 3.562}
{'排序名称': 'InsertSort', '数据规模': 1000, '耗时': 0.11129498481750488, '内存': 3.562}
{'排序名称': 'InsertSort', '数据规模': 10000, '耗时': 11.534623622894287, '内存': 3.561}
{'排序名称': 'InsertSort', '数据规模': 20000, '耗时': 47.08919715881348, '内存': 3.557}
{'排序名称': 'BubbleSort', '数据规模': 10, '耗时': 0.0, '内存': 3.557}
{'排序名称': 'BubbleSort', '数据规模': 100, '耗时': 0.00200653076171875, '内存': 3.557}
{'排序名称': 'BubbleSort', '数据规模': 1000, '耗时': 0.2827944755554199, '内存': 3.557}
{'排序名称': 'BubbleSort', '数据规模': 10000, '耗时': 28.376445531845093, '内存': 3.555}
{'排序名称': 'BubbleSort', '数据规模': 20000, '耗时': 114.53751921653748, '内存': 3.548}
- 时间对比:
横轴:数据规模大小
纵轴:耗时(单位:s)