实验----排序算法(十大排序之插入、选择、冒泡、归并)的实现
1.题目描述
生成 300 个 n 长排列:100 个 n 长的随机排列,100 个逆序数>n(n-1)/3 的 n 长随机排
列,100 个逆序数<n(n-1)/5 的 n 长随机排列。(注:n 分别等于 1000,10000,100000)。分别
用冒泡排序、插入排序、选择排序、归并排序算法对其排序,并比较其性能度量(时间或者
步数)。
2.实施思路
对于一个给定的数列,对其实现排序较易实现。多个序列也只需要对其分别排序就可以。
这里关键问题在于“如何生成逆序数满足一定要求的数列”。在这里我认为,其实这样的数列
要生成,或多或少都会需要进行一些“人工干预”,即不可能完全随机的直接生成此种序列。
对于逆序数偏大的数列,思路是先构建一个完全逆序的排列,再交换小部分数字顺序,这样
就可以认为该排列满足“逆序数偏大”的请求。对于逆序数偏小的数列,我们生成一个完全顺
序的数列,再交换小部分数字顺序,即可使得逆序数足够小从而满足给定要求。
3.Python 源 demo(基于PyCharm实现)
import random
import numpy
import time
import math
l = [[] for i in range(100)] # 先创建一个100行的空列表
#----createlist1函数----创建100个**n**长的**随机**排列(n为参数:100 1000 10000 20000)
def createlist1(n): # 100个n长的随机排列
for i in range(100):
for j in range(n):
l[i].append(0) #全部赋值为0
for row in range(100):
for col in range(n):
l[row][col] = random.randint(1,n) #到这里就完成了100个1000长随机数列的生成
print(l) #打印生成的列表
print(numpy.array(l).shape) #查看列表维度
#----createlist2函数----创建100个**n**长度的**逆序数>n(n-1)/3**的排列(n为参数:100 1000 10000 20000)
def createlist2(n):
for i in range(100):
for j in range(n):
l[i].append(0)
for row in range(100):
for col in range(n):
l[row][col] = n-col #先使得列表的每一行分别是一个完全倒序,这时候每个序列的逆序数均位于最大值
for i in range(100):
for j in range(n//2-150*n//1000+1,n//2-150*n//1000+1+300*n//1000):
l[i][j] = random.randint(n-(n//2-150*n//1000+1+300*n//1000),n-(n//2-150*n//1000+1))
#----createlist3函数----创建100个**n**长度的**逆序数<n(n-1)/5**的排列(n为参数:100 1000 10000 20000)
def createlist3(n):
for i in range(100):
for j in range(n):
l[i].append(0)
for row in range(100):
for col in range(n):
l[row][col] = col+1 #先使得列表的每一行分别是一个完全顺序,这时候每个序列的逆序数均位于最小值
for i in range(100):
for j in range(n//2-150*n//1000+1,n//2-150*n//1000+1+300*n//1000):
l[i][j] = random.randint(n-(n//2-150*n//1000+1+300*n//1000),n-(n//2-150*n//1000+1))
#----插入排序--insert_sort函数----
def insert_sort(l):
for i in range(100): # i下标是为了对每一行进行排序
for j in range(1,len(l[0])):
key = l[i][j]
k = j - 1
while k >= 0 and l[i][k] > key:
l[i][k + 1] = l[i][k]
k = k - 1
l[i][k + 1] = key
print(l[i]) # 打印排序好的每一行
print(l) # 打印排序好的整体
#----选择排序--selection_sort函数----
def selection_sort(l):
for i in range(100):
for j in range(len(l[0])):
min = l[i][j]
minindex = j
for k in range(j+1,len(l[0])):
if l[i][k] < min:
min = l[i][k]
minindex = k
if k == len(l[0]) - 1: #表示一轮结束后,将当前最小者放到当前未排序数列最前面
l[i][j] = l[i][minindex]
l[i][minindex] = l[i][j]
print(l[i])
print(l)
#----冒泡排序----bubble_sort函数----
def bubble_sort(l):
for i in range(100):
for j in range(1,len(l[0])):
for k in range(len(l[0]) - j):
if l[i][k] > l[i][k+1]:
l[i][k],l[i][k+1] = l[i][k+1],l[i][k]
print(l[i])
print(l)
#----归并排序----merger_sort函数----
def merger_sort(l):
for i in range(100):
for j in range(int(math.log(len(l[0]) * 2))):
indexlist = range(1,len(l[0]),2**j)
for num in indexlist:
sorted(l[num:num + 2**j])
print(l[i])
print(l)
def test1(n):
createlist1(n)
# ----插入排序----
inserttime1 = time.time()
insert_sort(l)
inserttime2 = time.time()
#----选择排序----
selecttime1 = time.time()
selection_sort(l)
selecttime2 = time.time()
#----冒泡排序----
bubbletime1 = time.time()
bubble_sort(l)
bubbletime2 = time.time()
#----归并排序----
mergertime1 = time.time()
merger_sort(l)
mergertime2 = time.time()
print('插入排序花费时间为{0}'.format(float(inserttime2 - inserttime1)))
print('选择排序花费时间为{0}'.format(float(selecttime2 - selecttime1)))
print('冒泡排序花费时间为{0}'.format(float(bubbletime2 - bubbletime1)))
print('归并排序花费时间为{0}'.format(float(mergertime2 - mergertime1)))
def test2(n):
createlist2(n)
# ----插入排序----
inserttime1 = time.time()
insert_sort(l)
inserttime2 = time.time()
#----选择排序----
selecttime1 = time.time()
selection_sort(l)
selecttime2 = time.time()
#----冒泡排序----
bubbletime1 = time.time()
bubble_sort(l)
bubbletime2 = time.time()
#----归并排序----
mergertime1 = time.time()
merger_sort(l)
mergertime2 = time.time()
print('插入排序花费时间为{0}'.format(float(inserttime2 - inserttime1)))
print('选择排序花费时间为{0}'.format(float(selecttime2 - selecttime1)))
print('冒泡排序花费时间为{0}'.format(float(bubbletime2 - bubbletime1)))
print('归并排序花费时间为{0}'.format(float(mergertime2 - mergertime1)))
def test3(n):
createlist3(n)
# ----插入排序----
inserttime1 = time.time()
insert_sort(l)
inserttime2 = time.time()
#----选择排序----
selecttime1 = time.time()
selection_sort(l)
selecttime2 = time.time()
#----冒泡排序----
bubbletime1 = time.time()
bubble_sort(l)
bubbletime2 = time.time()
#----归并排序----
mergertime1 = time.time()
merger_sort(l)
mergertime2 = time.time()
print('插入排序花费时间为{0}'.format(float(inserttime2 - inserttime1)))
print('选择排序花费时间为{0}'.format(float(selecttime2 - selecttime1)))
print('冒泡排序花费时间为{0}'.format(float(bubbletime2 - bubbletime1)))
print('归并排序花费时间为{0}'.format(float(mergertime2 - mergertime1)))
test3(20000)
4.结果截图
<1>随机序列(以 100、1000、10000、20000 依次呈现)
<2>逆序数偏大
<3>逆序数偏小
5.结果分析
在数据量较小,可能会出现理论分析上的时间复杂度较为大的算法反而运行时间较短的
情况。但是在数据量稍大时候,理论分析上的时间复杂度(准确的说,是时间复杂度数量级)小的算法就凸显出巨大优势(用大 O 记法进行分析时间复杂度,加上明显的一个结果是 n^2 > n*logn > n > logn,而且系数仅会在一定界限内起作用)。这时候我们发现归并排序最优,这与二分查找有关(与我们小时候玩过的猜数字游戏类似,复杂度应为 logn,我们知道,这已经相当不错了)。插入排序其次。选择排序则优于冒泡排序。这个结果也符合理论分析。