<算法入门>快速理解7种排序算法 | python3实现(附源码)

算法是程序的灵魂,而排序算法 是算法的入门经典,作者在此用python亲自实现了7种主流的排序算法,并做简短的说明.

<算法入门>快速理解7种排序算法 | python3实现(附源码)_第1张图片
排序算法

学习难度:

桶排序 < 冒泡排序 < 选择排序 < 插入排序 < 快速排序 < 归并排序 < 希尔排序

桶排序(简化版)

桶排序:
将列表中最大数与最小数之间的数全部做成标签,贴到N个桶上
将每个元素放到对应值的桶里面(如果有M个相同的元素值,则将M个元素全部放到相应的桶中,取的时候占用M个位置)
最后按照桶编号的先后顺序,从桶中依次取出值,排列完成


__author__ = 'zhaozhao'

def pail_sort(my_list):

    max_num = max(my_list)
    min_num = min(my_list)

    Y_list = list()

    for i in range(min_num, max_num+1):
        zhao_list = [i, 0]
        Y_list.append(zhao_list)

    for m in my_list:
        for Y in Y_list:
            if Y[0] == m:
                Y[1] += 1

    result = list()

    for n in Y_list:
        for t in range(0, n[1]):
            result.append(n[0])


    return result

    pass


def main():

    Y_list = [100, 54, 26, 63, 12, 22, 93, 17, 12, 77, 31, 44, 55, 20]
    print("简单桶排序之前的序列:", Y_list)
    print("简单桶排序之后的序列:", pail_sort(Y_list))


if __name__ == '__main__':
    main()

冒泡排序

冒泡排序:
有N个待排序元素
1.设置游标,游标带领第一个元素开始,与右侧元素(第1个元素)比较,如果大于右侧元素,则二者交换数值,然后游标带领元素继续向右移动,如果小于右侧元素,则不进行交换,游标继续向右移动,当游标移动到列表最右侧,第一轮比较就完成了(共比较N-1次)
2.然后游标回到起始位置,开始第二轮比较,由于最后一个元素已经确定大于剩余的元素所以(第二轮共比较N-2)次。
3.由于每次都只能选取出一个最大值,所以N个元素的数组,进行N-1轮对比即可完成排列


__author__ = 'zhaozhao'

def bubble_sort(my_list):

    N = len(my_list)
    # 循环的次数
    circle_num = N-1

    while circle_num > 0:
        # 初始的游标值
        index_value = 0

        while index_value < circle_num:

            if my_list[index_value] < my_list[index_value+1]:
                pass
            else:
                my_list[index_value], my_list[index_value+1] = my_list[index_value + 1], my_list[index_value]

            # 游标右移一个单位
            index_value += 1
            pass

        circle_num -= 1

    print("冒泡排序之后的序列:",my_list)
    return my_list


def main():
    Y_list = [100, 54, 26, 63, 12, 22, 93, 17, 12, 77, 31, 44, 55, 20]
    print("冒泡排序之前的序列:",Y_list)
    bubble_sort(Y_list)
    pass

if __name__ == '__main__':
    main()


选择排序

选择排序(升序):
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

__author__ = 'zhaozhao'

def selection_sort(my_list):

    # N为列表元素的个数
    N = len(my_list)

    circle_num = 0

    #需要进行N-1次循环
    while circle_num < N:

        # 每次循环开始的游标索引值 为 circle_num , 结束的索引值为N-1
        for m in range(circle_num, N):
            if my_list[circle_num] <= my_list[m]:
                pass
            else:
                my_list[circle_num], my_list[m] = my_list[m], my_list[circle_num]



        circle_num += 1

    print("选择排序之后的序列:",my_list)


def main():
    Y_list = [100, 54, 26, 63, 12, 22, 93, 17, 12, 77, 31, 44, 55, 20]
    print("选择排序之前的序列:",Y_list)
    selection_sort(Y_list)
    pass


if __name__ == '__main__':
    main()

插入排序

插入排序:
序列共有N个元素
将序列分为,已排序序列(第一个元素) 和 未排序序列(除第一个元素以外的其它元素,共N-1个)两部分,然后通过N-1轮循环,将N-1个元素,依次添加到已排序序列中


__author__ = 'zhaozhao'

def insert_sort(my_list):
    N = len(my_list)
    finish_list = list()
    f_len = len(finish_list)
    finish_list.append(my_list[0])
    # circle_num为待插入的值的索引
    for circle_num in range(1, N):
        for pre in range(0, circle_num):

            # 如果新加入的值比已排序的值小,就把新值加入到 已排序值的前面
            if my_list[circle_num] < finish_list[pre]:
                finish_list.insert(pre, my_list[circle_num])
                break

            # 如果新加入的值比已排序的序列最大的值都大,那么
            elif my_list[circle_num] >= finish_list[-1]:
                finish_list.append(my_list[circle_num])

                break
            # 如果新加入的值 比已排序的某个值大但比 已排序后面的值小
            elif my_list[circle_num] >= finish_list[pre] and my_list[circle_num] < finish_list[pre+1]:
                finish_list.insert(pre+1, my_list[circle_num])
                break
            else:
                pass



    return finish_list


def main():
    Y_list = [100, 54, 26, 63, 12, 22, 93, 17, 12, 77, 31, 44, 55, 20]
    print("插入排序之前的序列:", Y_list)
    insert_sort(Y_list)
    print("插入排序之后的序列:", insert_sort(Y_list))


if __name__ == '__main__':
    main()


快速排序(面试常用算法)

快速排序
1.选择左侧第一个元素为 基准元素(其实基准元素可以是任意值,这里选择第一个是为了方便叙述)

  1. 创建两个指针, 左侧指针初始位置在列表首部,右侧指针初始位置在列表尾部
  2. 先移动(为了保证,两个指针相遇时,所在位置的元素不大于 基准元素)右侧指针(左移),当到达 元素值 小于基准值 的位置停止(等待左侧指针的支援)
  3. 移动左侧指针(右移),当到达 元素值 大于基准值 的位置停止,将此元素与 右侧指针当时所在位置的值互换.
  4. 互换元素后,右侧指针继续先移动, 循环 3,4步骤
    6, 当左右指针相遇时, 将相遇位置的 元素值与 基准元素对调,完成第一轮循环
    7, 此时,基准元素左侧的值都小于 基准值,基准元素右侧的值都大于基准值
    8, 递归调用上面的算法,将两侧的 元素列表 进行排序
    9, 伴随着层层递归,新的基准值两侧的元素会越来越少,当基准值 无两侧元素时,排序终止
__author__ = 'zhaozhao'

def q_sort(my_list, left, right):

    #设置左右指针
    left_point = left
    right_point = right
    stand_num = left

    if left > right:
        return

    while left_point != right_point:

        #先移动右指针,如果遇到 比基准值更小 的值,就停下来

        while (my_list[right_point] >= my_list[stand_num]) and (left_point < right_point):
            right_point -= 1

        # 再移动左指针,如果遇到比基准值更大的值,就停下来

        while (my_list[left_point] < my_list[stand_num]) and (left_point < right_point):
            left_point += 1

        # 找到了双方可交换的点后, 开始交换

        my_list[left_point], my_list[right_point] = my_list[right_point],my_list[left_point]

        # 将基准点 与 指针相遇的点互换

        if left_point == right_point:
            my_list[stand_num], my_list[left_point] = my_list[left_point], my_list[stand_num]


        q_sort(my_list, left, left_point-1)
        q_sort(my_list, right_point+1, right)


    return (my_list)


def quick_sort(out_of_order):
    end = len(out_of_order) - 1
    start = 0
    q_sort(out_of_order, start, end)
    # print("排列完成的数组:",out_of_order)

    return out_of_order



def main():
    Y_list = [100, 54, 26, 63, 12, 22, 93, 17, 12, 77, 31, 44, 55, 20]
    print("快速排序之前的序列:", Y_list)
    print("快速排序之后的序列:", quick_sort(Y_list))


if __name__ == '__main__':
    main()


归并排序(先分后和, 分而治之)

归并排序(python内置sort方法的实现原理):
归并排序是典型的分治法排序,将待排序元素拆成多个分组,分组内部进行排序,然后分组进行合并,最终合并成完整的数组。

__author__ = 'zhaozhao'

# 负责 将列表拆分
def merge_sort(Y_list):

    if len(Y_list) <= 1:
        return Y_list

    # 先将未排序的列表进行分组
    num = len(Y_list) // 2

    left_list = merge_sort(Y_list[:num])
    right_list = merge_sort(Y_list[num:])

    # 将分组的列表交给merge函数, merge负责将列表合并
    return merge(left_list, right_list)


# 负责将列表合并
def merge(left, right):

    left_point = 0
    right_point = 0

    finish_list = list()

    while right_point < len(right) and left_point < len(left):

        if left[left_point] <= right[right_point]:
            finish_list.append(left[left_point])
            left_point += 1

        else:
            finish_list.append(right[right_point])
            right_point += 1

    finish_list += left[left_point:]
    finish_list += right[right_point:]

    return finish_list


def main():
    Y_list = [100, 54, 26, 63, 12, 22, 93, 17, 12, 77, 31, 44, 55, 20]
    print("归并排序之前的序列:", Y_list)
    print("归并排序之后的序列:", merge_sort(Y_list))


if __name__ == '__main__':
    main()

希尔排序

希尔排序:
希尔排序是为优化插入排序,而创建的算法, 其核心思想是通过设置步长 将元素分组,对每个分组进行快速排序,然后将步长减少,产生新的分组,对每个新分组进行快速排序,当步长减为1时,完成排序

__author__ = 'zhaozhao'

def shell_sort(Y_list):

    gap = len(Y_list)

    while gap >= 0:

        tem_list = list()

        if gap == 0:
            return Y_list

        # 将要抽取的值和索引保存到一个 列表里

        for index, value in enumerate(Y_list):
            if index % gap == 0:
                zhao_list = [index, value]
                tem_list.append(zhao_list)

        tem_value_list = list()

        for i in tem_list:
            tem_value_list.append(i[1])
        tem_value_list = insert_sort(tem_value_list)

        for i, vv in enumerate(tem_value_list):

            tem_list[i][1] = vv

        # 排序好的值  替换 原位置的值
        for iv in tem_list:

            Y_list[iv[0]] = iv[1]


        gap = gap // 2


    return Y_list


def insert_sort(my_list):
    N = len(my_list)
    finish_list = list()
    f_len = len(finish_list)
    finish_list.append(my_list[0])
    # circle_num为待插入的值的索引
    for circle_num in range(1, N):
        for pre in range(0, circle_num):

            # 如果新加入的值比已排序的值小,就把新值加入到 已排序值的前面
            if my_list[circle_num] < finish_list[pre]:
                finish_list.insert(pre, my_list[circle_num])
                break

            # 如果新加入的值比已排序的序列最大的值都大,那么
            elif my_list[circle_num] >= finish_list[-1]:
                finish_list.append(my_list[circle_num])

                break
            # 如果新加入的值 比已排序的某个值大但比 已排序后面的值小
            elif my_list[circle_num] >= finish_list[pre] and my_list[circle_num] < finish_list[pre+1]:
                finish_list.insert(pre+1, my_list[circle_num])
                break
            else:
                pass



    return finish_list


def main():

    Y_list = [100, 54, 26, 63, 12, 22, 93, 17, 12, 77, 31, 44, 55, 20]
    print("希尔排序之前的序列:", Y_list)
    print("希尔排序之后的序列:", shell_sort(Y_list))


if __name__ == '__main__':
    main()

你可能感兴趣的:(<算法入门>快速理解7种排序算法 | python3实现(附源码))