• 第三节--排序算法


    第三节–排序算法

    光栅处理的主要作用是将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("
    -----------------------------")
    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("
    第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   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 
    
  • 相关阅读:
    [ZZ]终极期望
    推荐一部好电影
    读书笔记:《Java2 教程》(五)
    波音飞机的消息
    雪景
    [ZZ]候捷谈Java反射机制
    关于J2ME开发的感想(20060505更新)
    读书笔记:《Java2 教程》(七)
    读书笔记:《Java2 教程》(六)
    注册了Bloglines
  • 原文地址:https://www.cnblogs.com/LQ6H/p/10346668.html
Copyright © 2020-2023  润新知