天天看点

【算法笔记(五)】排序算法算法笔记(五)前言一、冒泡排序二、选择排序三.插入排序四.希尔排序五.快速排序六.归并排序总结

算法笔记(五)

排序算法

  • 算法笔记(五)
  • 前言
  • 一、冒泡排序
    • 1.什么是冒泡排序
    • 2.实际需求
    • 3.代码实现
  • 二、选择排序
    • 1.什么是选择排序
    • 2.需求规则
  • 三.插入排序
    • 1.了解插入排序
    • 2.需求规则
    • 3.代码实现
  • 四.希尔排序
    • 1.什么是希尔排序
    • 2.需求规则
    • 3.代码实现
  • 五.快速排序
    • 1.什么是快速排序
    • 2.需求规则
    • 3.代码演示
  • 六.归并排序
    • 1.什么是归并排序
    • 2.需求规则
    • 3.代码展示
  • 总结

前言

基础数据结构告一段落,现在开始一起学习排序算法

一、冒泡排序

1.什么是冒泡排序

冒泡排序(Bubble Sor)是把一组数据从左边开始进行两两比较交换,小的放前面,大的放后面,通过反复比较一直到没有数据需要交换为止。该排序方法由于很像水里的泡泡,从水底冒出的小泡泡升到水面变成大的,体现了从小到大的排序过程(如图所示)。

【算法笔记(五)】排序算法算法笔记(五)前言一、冒泡排序二、选择排序三.插入排序四.希尔排序五.快速排序六.归并排序总结

2.实际需求

(1)从队首开始,两两比较数值,把大的往后交换,一直到队尾,第一个最大值固定到最后。

(2)再从队首开始,依次两两比较,把次最大放到倒数第二位置。

(3)依次循环比较,直到完成所有数的比较和交换,完成冒泡排序。

人工图示演示

第一步,1=[9,0,6,5,3,10,36,2,1]列表传入自定义函数bubblesort(), n=9。

第二步,i=0, j=0, s:[0]=9, s[1]=0, s[0]>s[1]为真, 则把0放前面9放后面;然后,9与6进行比较,6放前面9放后面; 9与5比较,5放前面9放后面; 9与3比较,3放前面9放后面;9与10比较,无须交换; 10 与36比较,无须交换位置; 36 与2比较,2放前面36放后面; 36与1比较,1放前面36放最后。第一次循环比较结果如图4.2所示,最大的数36放到了最后。

第三步,i=1,j=0, s:[0]-0, s:[1]=6,0与6比较,无须交换位置: 6与5比较,5放前面6放后面: 6与3比较,3放前面6放后面; 6与9比较,无须交换位置: 9与10比较,无须交换位置:10与2比较,2放前面10放后面: 10与1比较,1放前面10放后面。第二次循环结束,如图所示。

【算法笔记(五)】排序算法算法笔记(五)前言一、冒泡排序二、选择排序三.插入排序四.希尔排序五.快速排序六.归并排序总结

3.代码实现

def bubblesort(s1):
    n = len(s1)
    for i in range(n):                           # 冒泡循环次数控制
        for j in range(n - i - 1):               # 冒泡循环一次,范围往前面缩1
            if s1[j] > s1[j + 1]:
                c1 = s1[j]                       # 把大的赋给c1
                s1[j] = s1[j + 1]                # 把小的换到前一位
                s1[j + 1] = c1                   # 把c1赋给后一位


l1 = [9, 0, 6, 5, 3, 10, 36, 2, 1]
print("排序之前的顺序", l1)
bubblesort(l1)
print("排序之后的顺序", l1)

           

运行结果

【算法笔记(五)】排序算法算法笔记(五)前言一、冒泡排序二、选择排序三.插入排序四.希尔排序五.快速排序六.归并排序总结

二、选择排序

1.什么是选择排序

选择排序是另外一一种简单的排序 方法。在数据集合里,通过轮循环找到最小值,把它放到第一个位置,然后在剩余的数据中再我最小值,放到第二个位置。以此类推,直到将所有值排序完成。

2.需求规则

(1)输入n个数值的列表,开始0到n-1轮的循环。

(2) 每轮循环记住最小值的下标,当前循环结束, 把最小值放到最前面。

(3)接着进行下一 轮循环,把最小值下标进行标记, 最后把最小值放到当前轮循环开始的位置。

(4)一直到第n-1轮,结束所有最小值的选择。

人工图示

第一步,把列表s1传入SeletSor(arr)自定义函数。

第二步 i = 0到5, j=i到S进行循环,每循环一次选择一个最小值,放到循环的最前面,循环比较过程如图

【算法笔记(五)】排序算法算法笔记(五)前言一、冒泡排序二、选择排序三.插入排序四.希尔排序五.快速排序六.归并排序总结
def selectsort(s1):
    n = len(s1)
    if n == 1:
        return 1
    for i in range(n):
        mid = i                                     # 获得每次循环第一个比较值的下标
        for j in range(i, n - 1):                   # 每次循环里寻找最小值
            if s1[mid] > s1[j + 1]:                 # 循环过程判断最小值
                mid += 1                            # 获得更小值的下标
        s1[i], s1[mid] = s1[mid], s1[i]             # 把最小的放到最前面


s1 = [3, 18, 0, 32, 2, 1]
print("排序之前:", s1)
selectsort(s1)
print("排序之后:", s1)
           

运行结果

【算法笔记(五)】排序算法算法笔记(五)前言一、冒泡排序二、选择排序三.插入排序四.希尔排序五.快速排序六.归并排序总结

三.插入排序

1.了解插入排序

插入排序(Insertion Sort)的原理是数列前而为排序完成的值,数列后面为未排序的值。取已

排序的值右边第一个 未排序的值CI,与已经排序的值进行比较,当C1大于当前值时,把当前值向后

移动1位,继续往前比较,当c小于当前值时,在当前位置插入Ci并把当前值向后移动1位,

完成一个循环的插入比较。接着进行下一轮的循环插入比较,一直 到所有未排序的值都完成插入

操作。第一次循环时,可以把数列第一。个值作为已经排序的数来看待,从第二个值开始进行插入

操作。

2.需求规则

(1)输入n个数值的列表。

2)先进行下标是0和1的数值比较,把大的放后面,小的插入前面,第1轮插入比较结束。

(3)继续选择下标是2的数值和下标是1的数值进行比较,大的后移1位,小的放到临时变量c中;然后继续比较c1和下标是0的数值,大的后移1位,小的插入前面。

(4)依次比较插入,一直到n-1轮结束比较, 获得最终排序结果。

人工图示演示

【算法笔记(五)】排序算法算法笔记(五)前言一、冒泡排序二、选择排序三.插入排序四.希尔排序五.快速排序六.归并排序总结

3.代码实现

def insertsort(arr):
    n = len(arr)
    if n == 1:
        return 1
    for i in range(1, n):
        c1 = arr[i]
        j = i
        while j > 0 and c1 < arr[j - 1]:
            arr[j] = arr[j - 1]
            j -= 1
        arr[j] = c1


l2 = [9, 3, 1, 5, 6]
print("排列前顺序", l2)
insertsort(l2)
print("排列后的顺序:", l2)
           

运行结果

【算法笔记(五)】排序算法算法笔记(五)前言一、冒泡排序二、选择排序三.插入排序四.希尔排序五.快速排序六.归并排序总结

四.希尔排序

1.什么是希尔排序

希尔排序(Sel Sor)又叫作缩小增量排序算法,是插入排序的一种更高效的改进算法。

2.需求规则

希尔排序的基本思想是:在n个元素的数列里,取增量spcn/数列开始值和增量尾值之间进行比较,小的放前面,大的放后面:把增量前后的数值都比较一遍, 然后增量数space减1,继续从头到尾做比较,并调整大小;一直到space=1,就完成了所有元素的大小调整和排序。

增量space的取法有各种方案。最初Shell提出取space=n//2向下取整,space =space//2 向下取整,直到increment=1。但由于直到最后一步,奇数位置的元素才会与偶数位置的元素进行比较,这祥使用这个序列的效率会很低。后来Knuth提出取spacen/3向下取整+1,还有人提出都取奇数也有人提出space互质。使用不同的序列会使希尔排序算法的性能有很大的差异。

人工演示图

【算法笔记(五)】排序算法算法笔记(五)前言一、冒泡排序二、选择排序三.插入排序四.希尔排序五.快速排序六.归并排序总结

3.代码实现

def sellsort(arr):
    n = len(arr)
    endi = 0                        # 最后修改下标
    if n == 1:
        return 1
    space = n // 3                  # 以列表中1/3作为增量
    while space > 0:
        for i in range(space):      # 控制一个变量循环space次
            key = arr[i]
            j = 0                   # 控制每个key元素在列表里比较次数
            while i + (j + 1) * space < n:
                print(f'交换开始下标数{j},交换结束{i + (j + 1) * space}')
                if space > 1:
                    if arr[i + (j + 1) * space] < key:
                        arr[i + j * space] = arr[i + (j + 1) * space]
                        endi = i + (j + 1) * space
                else:               # 当增量为1时,相邻元素比较并调整
                    if arr[j] > arr[j + 1]:
                        arr[j], arr[j + 1] = arr[j + 1], arr[j]
                j += 1
            if arr[i] != key:       # 必须考虑无需交换情况
                arr[endi] = key
        space -= 1


s1 = [18, 3, 0, 5, 2, 10, 7, 15, 38, 100]
print(f"排列前的为:{s1}")
sellsort(s1)
print(f"排列后的为:{s1}")
           

运行结果

【算法笔记(五)】排序算法算法笔记(五)前言一、冒泡排序二、选择排序三.插入排序四.希尔排序五.快速排序六.归并排序总结
【算法笔记(五)】排序算法算法笔记(五)前言一、冒泡排序二、选择排序三.插入排序四.希尔排序五.快速排序六.归并排序总结

五.快速排序

1.什么是快速排序

快速排序(Quick Sort)是对冒泡排序的一种改进, 由C.A.R.Hoare在1960年提出。它的基本思想是:通过一轮排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,直到整个数据变成有序序列。分割时,先选择一个元素作 为比较大小的基准(Pivot) 数。把数列里小于Pivot 数的元素放到前面,大于Pivot数的元素放到后面。这个基准数可以任意取一一个, 一般取开始、结束或中间位置的一个元素。

由于该算法需要把不同部分的两部分数据迭代缩小排序,所以采用了递归排序方法,通过空间换时间,实现快速排序。

2.需求规则

(1)选取列表最后一个数值作为基准数P, 把比P小的数放前面, 比P大的数放后面。

(2)分别对前面部分和后面部分的数据按照(1)的原则进行排列。

(3)一直到每部分的下标low==high,完成快速排序。

图示演示

【算法笔记(五)】排序算法算法笔记(五)前言一、冒泡排序二、选择排序三.插入排序四.希尔排序五.快速排序六.归并排序总结

3.代码演示

def movepivot(arr, low, hight):
    pivot = arr[hight]
    imove = (low - 1)
    for i in range(low, hight):
        if arr[i] <= pivot:
            imove += 1
            arr[imove], arr[i] = arr[i], arr[imove]
    arr[imove + 1], arr[hight] = arr[hight], arr[imove + 1]
    return imove + 1


def quicksort(arr, low, hight):
    if low < hight:
        pivot = movepivot(arr, low, hight)
        quicksort(arr, low, pivot - 1)
        quicksort(arr, pivot + 1, hight)


s1 = [10, 3, 28, 4, 12, 20]
print(f"排序前{s1}")
h = len(s1)
quicksort(s1, 0, h - 1)
print(f"排序后的结果{s1}")
           

结果如下

【算法笔记(五)】排序算法算法笔记(五)前言一、冒泡排序二、选择排序三.插入排序四.希尔排序五.快速排序六.归并排序总结

六.归并排序

1.什么是归并排序

归并排序(Merge Sort)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

2.需求规则

分治法先把数列分成相对均衡的两部分n/2,

然后再把左边的(eft) 子数列和右边的(right)

的子数列再各分成两部分:继续如此等分,直到只有一个元素。

等分过程采用递归方法,每分次, 在内存开辟临时的记录区域。所有元素分完后,开始大小比较归并,从两个元素比较归并到n/比较归并。

s1=[1,9,10,4,50,6,7,90,21,23,45],其数量长度为n=11

第一次分割, n//2=5,通过递归,把左边left[:5]存储到临时空间,右边right[:5]也如此。

第二次分制,把左边lelt[:5]分别为 left1[:2]、right1[2:] 右边right[5:]分割为left2[:7]、right2[7:]

第三次分割,在第二次分割的基础上再分别递归分割。

第四次分割,完成了所有元素的分割,分割为最小单元1.

接下来对分割完成的各个数列进行并归排序操作。

第一次并归,分别完成1和9的比较合并、4和50的比较合并,在前面合并的基础上生成了1、9、10、4、50子数组;同时完成了7和90比较合并、23和45比较合并。

第二次并归,实现了1、4、9、10、50的比较和并归,6、7、21、23、45、90的比较和并归。

第三次并归,实现了1、4、6、7、9、10、21、23、45、50、90所有元素的最终排序过程。

图示演示

【算法笔记(五)】排序算法算法笔记(五)前言一、冒泡排序二、选择排序三.插入排序四.希尔排序五.快速排序六.归并排序总结

3.代码展示

def mergesort(arr):
    if len(arr) <= 1:
        return arr
    mid = len(arr) // 2
    left = mergesort(arr[:mid])
    right = mergesort(arr[mid:])
    return merge(left, right)


def merge(left, right):
    r, l = 0, 0
    temp = []
    lmax = len(left)
    rmax = len(right)
    while l < lmax and r < rmax:
        if left[l] <= right[r]:
            temp.append(left[l])
            l += 1
        else:
            temp.append(right[r])
            r += 1
    temp += list(left[l:])
    temp += list(right[r:])
    return temp

s1 = [1,9,10,4,50,6,7,90,21,23,45]
print(f"排列之前为{s1}")
print(f"排列之后为{mergesort(s1)}")
           

运行结果如下

【算法笔记(五)】排序算法算法笔记(五)前言一、冒泡排序二、选择排序三.插入排序四.希尔排序五.快速排序六.归并排序总结

总结

到此,排序算法就结束了,大家可以点击这里一起探讨吧,下章将带上检索算法的笔记

继续阅读