Python實現常用的算法排序

常見的排序列表
在這裏插入圖片描述

選擇排序

選擇排序(Selection sort)是一種簡單直觀的排序算法。它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然後,再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。
在這裏插入圖片描述

import time

start_time = time.time()


class XuanZePaiXu(object):

    def __init__(self):
        self.lis = [1, 3, 9, 4, 2]

    def paixun(self):
        """
        進行排序
        :return:
        """
        for i in range(len(self.lis)-1):
            min_pos = i

            for j in range(min_pos+1, len(self.lis)):
                min_pos = j if self.lis[min_pos] > self.lis[j] else min_pos

            self.lis[min_pos], self.lis[i] = self.lis[i], self.lis[min_pos]
        print("排序以後的--->", self.lis)
        print("所用時間--->", time.time() - start_time)


if __name__ == '__main__':
    u = XuanZePaiXu()
    u.paixun()
冒泡排序

冒泡排序(Bubble Sort)也是一種簡單直觀的排序算法。它重複地走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。走訪數列的工作是重複地進行直到沒有再需要交換,也就是說該數列已經排序完成。這個算法的名字由來是因爲越小的元素會經由交換慢慢"浮"到數列的頂端。
在這裏插入圖片描述

import time


lis = [8, 3, 9, 4, 2, 7, 5]


def maopao():
    """
    冒泡排序
    正序: 從小到大
    :return:
    """
    for j in range(len(lis)-1, -1, -1):
        for i in range(j):
            if lis[i] > lis[i+1]:
                lis[i], lis[i+1] = lis[i+1], lis[i]
    print("排序以後的--->", lis)



if __name__ == '__main__':
    start_time = time.time()
    maopao()
    print("所用時間--->", time.time() - start_time)
插入排序

插入排序(英語:Insertion Sort)是一種簡單直觀的排序算法。它的工作原理是通過構建有序序列,對於未排序數據,在已排序序列中從後向前掃描,找到相應位置並插入。
在這裏插入圖片描述

import time


lis = [8, 3, 9, 4, 2, 7, 5]


def charu():
    """
    插入排序
    :return:
    """
    for j in range(1, len(lis)):
        for i in range(j, 0, -1):
            if lis[i] < lis[i-1]:
                lis[i], lis[i-1] = lis[i-1], lis[i]
    print("排序以後的--->", lis)


if __name__ == '__main__':
    charu()

在這裏插入圖片描述

希爾排序

希爾排序,也稱遞減增量排序算法,是插入排序的一種更高效的改進版本。但希爾排序是非穩定排序算法。

希爾排序的基本思想是:先將整個待排序的記錄序列分割成爲若干子序列分別進行直接插入排序,待整個序列中的記錄"基本有序"時,再對全體記錄進行依次直接插入排序
在這裏插入圖片描述
在這裏插入圖片描述

import time
lis = [9, 2, 6, 1, 10, 3]


def xier():
    """
    希爾排序
    :return:
    """
    start_time = time.time()
    n = len(lis)
    grep = n // 2

    while grep > 0:
        for j in range(grep, n):
            while j > 0:
                if lis[j] < lis[j - grep]:
                    lis[j], lis[j - grep] = lis[j - grep], lis[j]
                    j -= grep
                else:
                    break
        grep //= 2

    print("排序以後的--->", lis)
    print("所用時間--->", time.time() - start_time)


if __name__ == '__main__':
    xier()
快速排序

快速排序使用分治法(Divide and conquer)策略來把一個序列(list)分爲較小和較大的2個子序列,然後遞歸地排序兩個子序列。

步驟爲:

  • 挑選基準值:從數列中挑出一個元素,稱爲"基準"(pivot);
  • 分割:重新排序數列,所有比基準值小的元素擺放在基準前面,所有比基準值大的元素擺在基準後面(與基準值相等的數可以到任何一邊)。在這個分割結束之後,對基準值的排序就已經完成;
  • 遞歸排序子序列:遞歸地將小於基準值元素的子序列和大於基準值元素的子序列排序。
  • 遞歸到最底部的判斷條件是數列的大小是零或一,此時該數列顯然已經有序。

選取基準值有數種具體方法,此選取方法對排序的時間性能有決定性影響。
在這裏插入圖片描述

import time

lis = [8, 3, 9, 4, 2, 7, 5, 10]


def quick_sort(lis, first, last):
    """
    快速排序
    :return:
    """
    mid_v = lis[first]
    if first >= last:
        return
    low = first
    high = last

    while low < high:
        while low < high and lis[high] >= mid_v:
            high -= 1
        lis[low] = lis[high]

        while low < high and lis[low] < mid_v:
            low += 1
        lis[high] = lis[low]
    lis[low] = mid_v
    quick_sort(lis, first, low-1)
    quick_sort(lis, low+1, high)


if __name__ == '__main__':
    start_time = time.time()
    quick_sort(lis, 0, len(lis) - 1)
    print("排序以後的--->", lis)
    print("所用時間--->", time.time() - start_time)
歸併排序

歸併排序(英語:Merge sort,或mergesort),是創建在歸併操作上的一種有效的排序算法。該算法是採用分治法(Divide and Conquer)的一個非常典型的應用。

分治法:

  • 分割:遞歸地把當前序列平均分割成兩半。
  • 集成:在保持元素順序的同時將上一步得到的子序列集成到一起(歸併)。

在這裏插入圖片描述

import time


def gui_bing(lis):
    """
    歸併排序
    :return:  一個新的列表
    """
    if len(lis) <=1:
        return lis
    mid = len(lis) // 2
    right_lis = gui_bing(lis[:mid])
    left_lis = gui_bing(lis[mid:])
    right_pointer = left_pointer = 0
    result = []
    while len(right_lis) > right_pointer and len(left_lis) > left_pointer:
        if right_lis[right_pointer] > left_lis[left_pointer]:
            result.append(left_lis[left_pointer])
            left_pointer += 1
        else:
            result.append(right_lis[right_pointer])
            right_pointer += 1
    result += left_lis[left_pointer:]
    result += right_lis[right_pointer:]
    return result


if __name__ == '__main__':
    lis = [8, 3, 9, 4, 2, 7, 7, 5, 10]
    start_time = time.time()
    sorted_list = gui_bing(lis)
    print("排序以後的--->", sorted_list)
    print("所用時間--->", time.time() - start_time)

計數排序
計數排序的核心在於將輸入的數據值轉化爲鍵存儲在額外開闢的數組空間中。作爲一種線性時間複雜度的排序,計數排序要求輸入的數據必須是有確定範圍的整數。 以空間換時間
在這裏插入圖片描述

import time


def jishu(lis, k):
    """
    基數排序
    :param lis:
    :return:
    """
    n = len(lis)
    b = [0 for _ in range(n)]
    c = [0 for _ in range(k+1)]
    """記錄:k 範圍內 lis 個元素出現的次數"""
    for i in lis:
        c[i] += 1
    print('c--->', c)

    for i in range(1, len(c)):
        print("{}={} + {}".format(c[i], c[i-1], c[i]))
        c[i] = c[i-1] + c[i]
    print('2c--->', c)

    for i in lis:
        b[c[i]-1] = i
        c[i] -= 1
    return b


if __name__ == '__main__':
    lis = [8, 3, 9, 4, 2, 7, 7, 5, 10]
    start_time = time.time()
    sorted_list = jishu(lis, 10)
    print("排序以後的--->", sorted_list)
    print("所用時間--->", time.time() - start_time)
二分查找

二分查找也稱折半查找(Binary Search),它是一種效率較高的查找方法。但是,折半查找要求線性表必須採用順序存儲結構,而且表中元素按關鍵字有序排列。
在這裏插入圖片描述

import time


def search(lis, n):
    """
    二分查找
    :param lis:
    :param n:
    :return:  True or False
    """
    mid = len(lis) // 2
    if len(lis) > 0:
        if n == lis[mid]:
            return True
        elif n < lis[mid]:
            return search(lis[:mid], n)
        else:
            return search(lis[mid:], n)
    else:
        return False


if __name__ == '__main__':
    start_time = time.time()
    lis = [1,2,3,4,5,6,7]
    print(search(lis, 3))
    print("end--->", time.time() - start_time)

二叉樹

在這裏插入圖片描述
在這裏插入圖片描述


class Node(object):
    """
    構建節點類
    """
    def __init__(self, item):
        self.elem = item
        self.rchild = None
        self.lchild = None


class Tree(object):
    """
    二叉樹
    """
    def __init__(self):
        """
        初始化 根節點爲 None
        """
        self.root = None

    def add(self, item):
        """
        添加元素
        :param item:
        :return:
        """
        node = Node(item)
        if self.root is None:
            self.root = node
            return
        queue = [self.root]
        while queue:
            cur_node = queue.pop(0)
            if cur_node.lchild is None:
                cur_node.lchild = node
                return
            else:
                """
                如果遊標所指的左孩子不是空,則應該將遊標所指的
                左孩子加入到隊列中,以便下次循環進行查找
                """
                queue.append(cur_node.lchild)
            if cur_node.rchild is None:
                cur_node.rchild = node
                return
            else:
                queue.append(cur_node.rchild)

    def breadth_travel(self):
        """
        廣度優先遍歷
        :return:
        """
        if self.root is None:
            return
        print('self.root-->', self.root)
        queue = [self.root]

        while queue:
            cur_node = queue.pop(0)
            print('cur_node.item', cur_node.elem)
            if cur_node.lchild:
                queue.append(cur_node.lchild)
            if cur_node.rchild:
                queue.append(cur_node.rchild)

    def xian_xu(self, node):
        """
        先序遍歷
        :return:
        """
        if node is None:
            return
        print(node.elem)
        self.xian_xu(node.lchild)
        self.xian_xu(node.rchild)

    def zhong_xu(self, node):
        """
        中序遍歷
        :param node:
        :return:
        """
        if node is None:
            return
        else:
            self.zhong_xu(node.lchild)
            print(node.elem)
            self.zhong_xu(node.rchild)

    def hou_zu(self, node):
        """
        後序遍歷
        :param node:
        :return:
        """
        if node is None:
            return
        else:
            self.hou_zu(node.lchild)
            self.hou_zu(node.rchild)
            print(node.elem)


if __name__ == '__main__':
    tree = Tree()
    tree.add(2)
    tree.add(4)
    tree.add(1)
    tree.breadth_travel()
    tree.xian_xu(tree.root)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章