第三节–排序算法
光栅处理的主要作用是将3D模型转换成能够被显示与屏幕的图像,并对图像进行修正和进一步美化处理,让展现在眼前的画面更为逼真与生动
一.认识排序
1.认识排序
“排序”(Sorting)就是指将一组数据,按特定规则调换位置,使数据具有某种顺序关系(递增或递减)。用以排序的依据被称为键(Key),它所含的值就称为"键值"。通常键值的数据类型有数值类型,中文字符串类型以及非中文字符串类型三种
在排序过程中,数据的移动方式可分为"直接移动"和"逻辑移动"两种。"直接移动"是直接交换存储数据的位置,而"逻辑移动"并不会移动数据存储的位置,仅改变指向这些数据的辅助指针的值
两者间的优劣在于直接移动会浪费许多时间进行数据的移动,而逻辑移动只要改变辅助指针指向的位置就能轻易达到排序的目的
二.冒泡排序法
1.过程简介
冒泡排序法又称为交换排序法,原理是从第一个元素开始比较相邻元素的大小,若大小顺序有误,则对调后再进行下一个元素的比较,仿佛气泡逐渐从水底冒升到上面上。如此扫描一次过后就可确保最后一个元素位于正确的顺序。接着再逐步进行第二次扫描,直到完成所有元素的排序关系为止
2.例子说明
下面使用55,23,87,62,16数列来演示排序过程
由此可知5个元素的冒泡排序法必须执行4(5-1)次扫描,第一次扫描需比较4(5-1)次,共比较了4+3+2+1=10次
3.程序说明
源程序:
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Author LQ6H
data = [16,25,39,27,12,8,45,63]
print("冒泡排序法 原始数据:")
for i in range(8):
print("%3d" %data[i],end=" ")
print()
for i in range(7,0,-1):
for j in range(i):
if data[j]>data[j+1]:
data[j],data[j+1] = data[j+1],data[j]
print("第 %d 次排序后的结果是:" %(8-i),end=" ")
for j in range(8):
print("%3d" %data[j],end=" ")
print()
print("排序后的结果为:")
for j in range(8):
print("%3d" %data[j],end=" ")
print()
运行结果:
冒泡排序法 原始数据:
16 25 39 27 12 8 45 63
第 1 次排序后的结果是: 16 25 27 12 8 39 45 63
第 2 次排序后的结果是: 16 25 12 8 27 39 45 63
第 3 次排序后的结果是: 16 12 8 25 27 39 45 63
第 4 次排序后的结果是: 12 8 16 25 27 39 45 63
第 5 次排序后的结果是: 8 12 16 25 27 39 45 63
第 6 次排序后的结果是: 8 12 16 25 27 39 45 63
第 7 次排序后的结果是: 8 12 16 25 27 39 45 63
排序后的结果为:
8 12 16 25 27 39 45 63
三.选择排序法
1.过程简介
选择排序法(Selection Sort)也算是枚举法的应用,就是反复从未排序的数列中取出最小的元素,加入到另一个数列中,最后的结果即为已排序的数列。选择排序法可使用两种方式排序,一种为在所有的数据中,从大到小排序,将最大值放入第一个位置;另一种是从小到大排序,将最大值放入最后一个位置
2.例子说明
3.程序说明
源程序:
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Author LQ6H
def showdata(data):
for i in range(8):
print("%3d" %data[i],end=" ")
print()
def select(data):
for i in range(7):
for j in range(i+1,8):
if data[i] > data[j]:
data[i],data[j] = data[j],data[i]
print()
data = [16,25,39,27,12,8,45,63]
print("原始数据为:")
for i in range(8):
print("%3d" %data[i],end=" ")
print("
-----------------------------")
select(data)
print("排序后的数据为:")
for i in range(8):
print("%3d" %data[i],end=" ")
运行结果:
原始数据为:
16 25 39 27 12 8 45 63
-----------------------------
排序后的数据为:
8 12 16 25 27 39 45 63
四.插入排序法
1.过程简介
插入排序法(Insert Sort)是将数组中的元素,逐一与已排序好的数据进行比较,前两个元素先排好,再将第三个元素插入适当的位置,所以这三个元素仍然是已排序好的,接着将第四个元素加入,重复此步骤,直到排序完成为止
2.例子说明
3.程序说明
源程序:
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Author LQ6H
SIZE = 8 #定义数组大小
def showdata(data):
for i in range(SIZE):
print("%3d" %data[i],end=" ")
print()
def insert(data):
for i in range(1,SIZE):
temp = data[i]
no = i - 1
while no>=0 and temp<data[no]:
data[no+1] = data[no]
no-=1
data[no+1] = temp
def main():
data = [16,25,39,27,12,8,45,63]
print("原始数组是:")
showdata(data)
insert(data)
print("排序后的数组是:")
showdata(data)
if __name__ == '__main__':
main()
运行结果:
原始数组是:
16 25 39 27 12 8 45 63
排序后的数组是:
8 12 16 25 27 39 45 63
五.希尔排序法
1.过程简介
"希尔排序法"是可以减少插入排序法中数据搬移的次数,以加速排序的进行。排序的原则是将数据区分成特定间隔的几个小区块,以插入排序法排完区块内的数据后再渐渐减少间隔的距离
2.例子说明
3.程序说明
源程序:
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Author LQ6H
SIZE = 8
def showdata(data):
for i in range(SIZE):
print("%3d" %data[i],end=" ")
print()
def shell(data,size):
k=1 # 打印计数
jmp=size//2
while jmp!=0:
for i in range(jmp,size): #i为扫描次数,jmp为设置间距的位移量
temp = data[i]
j=i-jmp #以j来定位比较的元素
while temp<data[j] and j>=0:
data[j+jmp]=data[j]
j=j-jmp
data[jmp+j]=temp
print("第%d次排序过程:" %k,end=" ")
k+=1
showdata(data)
print("---------------------------")
jmp=jmp//2 #控制循环的次数
def main():
data = [16,25,39,27,12,8,45,63]
print("原始数据是:")
showdata(data)
print("-------------------------------")
shell(data,SIZE)
main()
运行结果:
原始数据是:
16 25 39 27 12 8 45 63
-------------------------------
第1次排序过程: 12 8 39 27 16 25 45 63
---------------------------
第2次排序过程: 12 8 16 25 39 27 45 63
---------------------------
第3次排序过程: 8 12 16 25 27 39 45 63
六.合并排序法
1.过程简介
合并排序法(Merge Sort)的工作原理是针对已排序好的两个或两个以上的数列(或数据文件),通过合并的方式,将其组合成一个大的且已排好序的数列(或数据文件)。步骤如下:
- 将N个长度为1的键值,成对地合并成1/2个长度为2的键值组
- 将N/2个长度为2的键值组,成对地合并成N/4个长度为4的键值组
- 将键值组不断地合并,直到合并成一组长度为N的键值组为止
2.例子说明
3.程序说明
源程序:
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Author LQ6H
# 9999为数列1的结束数字不列入排序
list1 = [20,45,51,88,9999]
# 9999为数列1的结束数字不列入排序
list2 = [98,10,23,15,9999]
list3 = []
def merge_sort():
global list1
global list2
global list3
# 先使用选择排序将两个数列排序,在进行合并
select_sort(list1,len(list1)-1)
select_sort(list2,len(list2)-1)
print("
第1个数列的排序结果为:",end=" ")
for i in range(len(list1)-1):
print(list1[i]," ",end=" ")
print("
第2个数列的排序结果为:", end=" ")
for i in range(len(list2) - 1):
print(list2[i], " ", end=" ")
print()
print("----------------------------------------------------------")
My_Merge(len(list1)-1,len(list2)-1)
print("----------------------------------------------------------")
print("
合并排序法的最终结果为:",end=" ")
for i in range(len(list1)+len(list2)-2):
print("%d" %list3[i],end=" ")
def select_sort(data,size):
for base in range(size-1):
small = base
for j in range(base+1,size):
if data[j]<data[small]:
small = j
data[small],data[base] = data[base],data[small]
def My_Merge(size1,size2):
global list1
global list2
global list3
index1 = 0
index2 = 0
for index3 in range(len(list1)+len(list2)-2):
if list1[index1]<list2[index2]: # 比较两个数列,其中数小的先存储到合并后的数列中
list3.append(list1[index1])
index1+=1
print("此数字%d取自于第1个数列" %list3[index3])
else:
list3.append(list2[index2])
index2+=1
print("此数字%d取自于第2个数列" %list3[index3])
print("目前的合并排序结果为:",end=" ")
for i in range(index3+1):
print(list3[i]," ",end=" ")
print("
")
merge_sort()
运行结果:
第1个数列的排序结果为: 20 45 51 88
第2个数列的排序结果为: 10 15 23 98
----------------------------------------------------------
此数字10取自于第2个数列
目前的合并排序结果为: 10
此数字15取自于第2个数列
目前的合并排序结果为: 10 15
此数字20取自于第1个数列
目前的合并排序结果为: 10 15 20
此数字23取自于第2个数列
目前的合并排序结果为: 10 15 20 23
此数字45取自于第1个数列
目前的合并排序结果为: 10 15 20 23 45
此数字51取自于第1个数列
目前的合并排序结果为: 10 15 20 23 45 51
此数字88取自于第1个数列
目前的合并排序结果为: 10 15 20 23 45 51 88
此数字98取自于第2个数列
目前的合并排序结果为: 10 15 20 23 45 51 88 98
----------------------------------------------------------
合并排序法的最终结果为: 10 15 20 23 45 51 88 98
七.快速排序法
1.过程简介
快速排序又称分割交换排序法,是目前公认最佳的排序法,也是使用"分而治之"(Divide and Conquer)的方式,先在数据中找到一个虚拟的中间值,并按此中间值将所有打算排序的数据分为两部分。其中,小于中间值的数据放在左边,大于中间值的数据放在右边,再以同样的方式分别处理左,右两边的数据,直到排序完成为止。
操作与分割步骤如下:
假设有n项记录R,R,R…R其键值为KKKK
- 先假设K的值为第一个键值
- 从左向右找出键值K使得K>K
- 从右向左找出键值K使得K<K
- 如果i<j,那么K与K互换,并回到步骤2
- 若i>=j则将K与K交换,并以j为基准点分割成左右部分。然后针对左右两边进行步骤1至5,直到左半边键值等于右半边键值
2.例子说明
3.程序说明
源程序:
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Author LQ6H
import random
def inputarr(data,size):
for i in range(size):
data[i] = random.randint(1,100)
def showdata(data,size):
for i in range(size):
print("%3d" %data[i],end=" ")
print()
def quick(d,size,lf,rg):
# 第一项键值为d[lf]
if lf<rg:
lf_idx = lf+1
while d[lf_idx]<d[lf]:
if lf_idx+1 >size:
break
lf_idx+=1
rg_idx = rg
while d[rg_idx]>d[lf]:
rg_idx-=1
while lf_idx<rg_idx:
d[lf_idx],d[rg_idx] = d[rg_idx],d[lf_idx]
lf_idx+=1
while d[lf_idx]<d[lf]:
lf_idx+=1
rg_idx-=1
while d[rg_idx]>d[lf]:
rg_idx-=1
d[lf],d[rg_idx] = d[rg_idx],d[lf]
for i in range(size):
print("%3d" %d[i],end=" ")
print()
quick(d,size,lf,rg_idx-1) # 以rg_idx为基准点分成左右两半以递归方式
quick(d,size,rg_idx+1,rg) # 分别为左右两半进行排序直至完成排序
def main():
data = [0]*100
size = int(input("请输入数列的大小(100以下):"))
inputarr(data,size)
print("你输入的原始数据是:")
showdata(data,size)
print("排序的过程如下:")
quick(data,size,0,size-1)
print("最终的排序结果为:")
showdata(data,size)
main()
运行结果:
请输入数列的大小(100以下):10
你输入的原始数据是:
51 61 92 11 12 5 15 56 63 24
排序的过程如下:
5 24 15 11 12 51 92 56 63 61
5 24 15 11 12 51 92 56 63 61
5 12 15 11 24 51 92 56 63 61
5 11 12 15 24 51 92 56 63 61
5 11 12 15 24 51 61 56 63 92
5 11 12 15 24 51 56 61 63 92
最终的排序结果为:
5 11 12 15 24 51 56 61 63 92
八.基数排序法
1.过程简介
基数排序法按比较的方向可分为最高位有先(Most Significant Digit First,MSD)和最低位优先(Least Significant Digit First,LSD)两种。MSD法是从最左边的位数开始比较,而LSD则是从最右边的位数开始比较
2.例子说明
3.程序说明
源程序:
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Author LQ6H
import random
def inputarr(data,size):
for i in range(size):
data[i] = random.randint(0,999)
def showdata(data,size):
for i in range(size):
print("%3d" %data[i],end=" ")
print()
def radix(data,size):
n = 1 # n为基数,从个位数开始排序
while n<=100:
temp = [[0]*100 for row in range(10)]
for i in range(size):
m = (data[i]//n)%10
temp[m][i]=data[i]
k=0
for i in range(10):
for j in range(size):
if temp[i][j]!=0:
data[k] = temp[i][j]
k+=1
print("经过%3d位数排序后:" %n,end=" ")
showdata(data,size)
n=10*n
def main():
data = [0]*100
size = int(input("请输入数列的大小(100以下):"))
print("你输入的原始数据是:")
inputarr(data,size)
showdata(data,size)
radix(data,size)
main()
运行结果:
请输入数列的大小(100以下):10
你输入的原始数据是:
518 278 781 726 52 589 490 764 662 142
经过 1位数排序后: 490 781 52 662 142 764 726 518 278 589
经过 10位数排序后: 518 726 142 52 662 764 278 781 589 490
经过100位数排序后: 52 142 278 490 518 589 662 726 764 781