经典排序算法,冒泡排序,选择排序,直接插入排序,希尔排序,快速排序,归并排序,二分查找。原理及python实现。

1.冒泡排序

                      冒泡排序
1.比较相邻的元素,如果第一个比第二个大(升序),就交换他们两个
2.对每一对相邻的元素做同样的工作,从开始到结尾的最后一对
  这步做完后,最后的元素会是最大的数
3.针对所有的元素重复以上的步骤,除了最后一个
4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
5.稳定性:数值相同的元素在排序中不交换位置为稳定反之为不稳定
6.最优复杂度:O(n)   最坏复杂度:O(n^2)   稳定性:稳定

代码实现:

def bubble_sort(alist):
    """冒泡排序"""
    n = len(alist)
    for j in range(n-1):
        # range(5)的取值范围是从0~4此处要取到n-2(下标从0开始)所以
        # 此处的值为n-1
        count = 0
        # 如果进行了交换count加一,如果内层循环中发现某次交换一次都没有发生
        # 即count == 0,则说明列表已经是有序的了,直接退出外层循环,优化了程序
        for i in range(n-1-j):
            if alist[i] > alist[i+1]:
                alist[i], alist[i+1] = alist[i+1], alist[i]
                count += 1
        if count == 0:
            break


if __name__ == '__main__':
    li = [56, 88, 12, 62, 54, 79, 32, 11, 96]
    print(*li)
    bubble_sort(li)
    print(*li)

2.选择排序

               选择排序
1.始终从未排序的序列中找到最小的放到最前面
2.将第一个元素先作为最小值,用第一个元素和后面的元素依次比较
3.首次碰见比第一个元素更小的元素就记录这个“较小元素”的位置
4.继续比较如果碰见比“较小元素”还更小的元素,就将记录的“较小元素”的位置信息,替换成“更小元素”的位置信息
5.直到比较完整个序列,最小的元素位置信息就被记录下来了
6.交换第一个元素和最小元素的位置,序列的头部就变成了最小的元素
7.再将第二个元素先作为序列剩余元素的最小元素,和剩下的元素重复上述步骤进行比较
8.将第二小的元素找到,并和第二个元素进行交换
9.多次重复上述步骤n-1次,即可得到升序序列
10.最优复杂度:O(n^2)    最坏复杂度:O(n^2)    稳定性:不稳定

代码实现:

def select_sort(alist):
    """选择排序"""
    n = len(alist)
    for j in range(n-1):
        # 列表的长度为n,从0开始计算一共为n-1个数。
        # 最后一趟只剩最后一个数,一定是最大的不用比较。
        # 所以只需要比较n-2次。
        min_index = j
        for i in range(j+1, n):
            if alist[min_index] > alist[i]:
                min_index = i
        alist[j], alist[min_index] = alist[min_index], alist[j]


if __name__ == '__main__':
    li = [56, 26, 77, 6, 54, 38, 96, 43, 99]
    print(*li)
    select_sort(li)
    print(*li)

3.插入排序

              插入排序
⒈ 从第一个元素开始,该元素可以认为已经被排序
⒉ 取出下一个元素,在已经排序的元素序列中从后向前扫描
⒊ 如果该元素(已排序)大于新元素,将该元素移到下一位置
⒋ 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
⒌ 将新元素插入到下一位置中
⒍ 重复步骤2~5
7. 最优复杂度:O(n) 最坏复杂度:O(n^2) 稳定性:稳定

代码实现:

def insert_sort(alist):
    """插入排序"""
    n = len(alist)

    for j in range(1, n):
        # 1~n-1
        for i in range(j, 0, -1):
            # range(start, stop[, step])
            # stop的值要取前一个,所以此处取值为j~1,
            if alist[i] < alist[i-1]:
                alist[i], alist[i-1] = alist[i-1], alist[i]

            # 此处为对代码的优化
            # 因为序列的alist[i]之前的序列已经是有序的了
            # 如果alist[i] >= alist[i-1]直接放入前面的有序部分的尾部就行
            # 没有必要再和前面的元素依次比较了
            # 此处的优化使代码的最优时间复杂度由O(n^2)变为了O(n)
            else:
                break


if __name__ == '__main__':
    # li = [5, 3, 2, 4, 7, 1, 6]
    li = [1, 2, 3, 4, 5, 4, 6, 7]
    print(*li)
    # start_time = time.time()
    insert_sort(li)
    # end_time = time.time()
    print(*li)
    # print(end_time-start_time)

 

4.希尔排序

           希尔排序
1.希尔排序是按照不同步长对元素进行插入排序
2.当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快
3.当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。
4.最优复杂度:O(n^1.3)   最坏复杂度:O(n^2)   稳定性:不稳定

代码实现:

def shell_sort(alist):
    """希尔排序"""
    n = len(alist)
    step = n//2

    while step > 0:
        for j in range(step, n):
            for i in range(j, 0, -step):
                if alist[i] < alist[i-step]:
                    alist[i], alist[i-1] = alist[i-1], alist[i]
                else:
                    break
        step = step//2


if __name__ == '__main__':

    li = [56, 26, 77, 6, 54, 38, 96, 43, 99]
    print(*li)
    shell_sort(li)
    print(*li)

5.快速排序(划重点)

                      快速排序
通过一趟排序将要排序的数据分割成独立的两部分
其中一部分的所有数据都比另外一部分的所有数据都要小
然后再按此方法对这两部分数据分别进行快速排序
整个排序过程可以递归进行,以此达到整个数据变成有序序列
过程描述
1.定义一个标杆,将列表的第一个元素存入标杆,列表的第一个位置相当于空出来了
2.定义两个指针low,high,分别记录列表头和列表尾的位置
3.判断low是不是小于high,列表尾high位置的元素是不是大于等于标杆,如果是high向左移动一位
  重复执行这步判断,当条件不成立时,让low位置存放当前high位置的元素
4.判断low是不是小于high,列表头low位置的元素是不是小于标杆,如果是low向右移动一位
  重复执行这步判断,当条件不成立时,让high位置存放当前low位置的元素
5.让4、5两步交替执行,直到low >= high时退出循环。此时low = high
6.此时找到的low的位置就是标杆的位置,将记录的标杆元素,放置在这个位置。
7.递归执行上述步骤直到low >= high时退出。
8.最优时间复杂度计算:n拆分多少次能只剩一个元素,也就是n除以多少次2能等于1
  即n/2^x = 1 --> 2^x = n --> x = logn (log以2为底,n的对数)
  每次让列表中的值沿着初始值分为左右两半的过程的时间复杂度为n
  所以最优时间复杂度为nlogn
9.最优复杂度:O(nlogn)   最坏复杂度:O(n^2)   稳定性:不稳定

代码实现:

def quick_sort(alist, first, last):
    """快速排序"""

    if first >= last:
        return
    mid_value = alist[first]
    low = first
    high = last

    while low < high:
        # high左移
        while low < high and alist[high] >= mid_value:
            high -= 1
        alist[low] = alist[high]

        # low 右移
        while low < high and alist[low] < mid_value:
            low += 1
        alist[high] = alist[low]
    # 循环退出low = high
    alist[low] = mid_value
    # 对low左边的进行快速排序
    quick_sort(alist, first, low-1)
    # 对low右边的进行快速排序
    quick_sort(alist, low+1, last)


if __name__ == '__main__':
    li = [56, 45, 33, 22, 96, 79, 88, 64, 9, 16, 8, 21, 25, 28]
    print(*li)
    quick_sort(li, 0, len(li)-1)
    print(*li)

6.归并排序

          归并排序
归并排序的思想是先递归分解数组,再合并数组
将数组分解最小之后,然后合并两个有序数组。
基本思路就是比较两个数组最前面的数,谁小就取谁,
取了后相应的指针就往后移一位。
然后再比较,直至一个数组为空,最后把两一个数组的剩余部分复制过来即可。
最优复杂度:O(nlogn)   最坏复杂度:O(nlogn)   稳定性:稳定

代码实现:

import random


def merge_sort(alist):
    """归并排序"""
    n = len(alist)
    if n <= 1:
        return alist
    mid = n//2
    # left 采用归并排序后形成的有序的新的列表
    left_li = merge_sort(alist[:mid])
    # right 采用归并排序后形成的有序的新的列表
    right_li = merge_sort(alist[mid:])

    # 将两个有序的子序列合并为一个新的整体
    left, right = 0, 0
    result = []

    while left < len(left_li) and right < len(right_li):
        # print(left_li[left], right_li[right])
        if left_li[left] <= right_li[right]:
            result.append(left_li[left])
            left += 1
        else:
            # right_li[right] < left_li[left]
            result.append(right_li[right])
            right += 1
    result += left_li[left:]
    result += right_li[right:]

    return result


if __name__ == '__main__':
    li = []
    for i in range(10):
        li.append(random.randint(1, 100))
    print(*li)
    result = merge_sort(li)
    print(*result)

7.二分查找 

代码实现:

def binary_search(alist, item):
    """二分法查找_递归"""
    n = len(alist)
    if n > 0:
        mid = (n-1) // 2
        if alist[mid] == item:
            return True
        elif item < alist[mid]:
            return binary_search(alist[:mid], item)
        else:
            return binary_search(alist[mid+1:], item)
    else:
        return False


def binary_search_2(alist, item):
    """二分法查找_非递归"""
    n = len(alist)
    last = n - 1
    first = 0
    while first <= last:
        mid = (first + last) // 2
        # 找到alist[i]要插入的位置
        if alist[mid] == item:
            return True
        elif item < alist[mid]:
            last = mid-1
        else:
            first = mid+1
    return False


if __name__ == "__main__":
    li = [i for i in range(20)]
    print(li)
    print(binary_search(li, 18))
    print(binary_search_2(li, 16))

 文章有不足之处或您有更好的方案想法,欢迎评论区留言。

 

    原文作者:排序算法
    原文地址: https://blog.csdn.net/Daputao_net/article/details/82180633
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞