第三节--排序算法

第三节–排序算法

光栅处理的主要作用是将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  631 次排序后的结果是:  16  25  27  12   8  39  45  632 次排序后的结果是:  16  25  12   8  27  39  45  633 次排序后的结果是:  16  12   8  25  27  39  45  634 次排序后的结果是:  12   8  16  25  27  39  45  635 次排序后的结果是:   8  12  16  25  27  39  45  636 次排序后的结果是:   8  12  16  25  27  39  45  637 次排序后的结果是:   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("\n-----------------------------")
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)的工作原理是针对已排序好的两个或两个以上的数列(或数据文件),通过合并的方式,将其组合成一个大的且已排好序的数列(或数据文件)。步骤如下:

  1. 将N个长度为1的键值,成对地合并成1/2个长度为2的键值组
  2. 将N/2个长度为2的键值组,成对地合并成N/4个长度为4的键值组
  3. 将键值组不断地合并,直到合并成一组长度为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("\n第1个数列的排序结果为:",end=" ")
    for i in range(len(list1)-1):
        print(list1[i]," ",end=" ")

    print("\n第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("\n合并排序法的最终结果为:",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("\n")

merge_sort()

运行结果:

1个数列的排序结果为: 20   45   51   882个数列的排序结果为: 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

  1. 先假设K的值为第一个键值
  2. 从左向右找出键值K使得K>K
  3. 从右向左找出键值K使得K<K
  4. 如果i<j,那么K与K互换,并回到步骤2
  5. 若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 
posted @ 2019-02-01 18:32  LQ6H  阅读(310)  评论(0编辑  收藏  举报