zoukankan      html  css  js  c++  java
  • 排序查询算法(一)

    冒泡排序

    # coding:utf-8
    
    def bubble_sort(alist):
        """冒泡排序"""
        nums = len(alist) - 1  # 要执行的次数
        while nums:
            for i in range(nums):
                if alist[i] > alist[i+1]:
                    alist[i], alist[i+1] = alist[i+1], alist[i]
            nums -= 1
    
        return alist
    
    
    if __name__ == "__main__":
        b = bubble_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6])
        print(b)
    

    另一种方法

    # coding:utf-8
    
    def bubble_sort(alist):
        """冒泡排序"""
        nums = len(alist)
        count = 0  # 记录是否有进行数据交换
        for j in range(nums-1):  # 规定要执行的次数
            for i in range(0, nums-1-j):  # 规定每次执行比较的个数
                if alist[i] > alist[i+1]:
                    alist[i], alist[i+1] = alist[i+1], alist[i]
                    count += 1
            if count == 0:  # 说明该序列是有序的序列,不必进行后面的比较,直接返回
                return alist
    
        return alist
    
    
    if __name__ == "__main__":
        b = bubble_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6])
        print(b)
    

    时间复杂度

    • 最优时间复杂度:O(n) (表示遍历一次发现没有任何可以交换的元素,排序结束。)
    • 最坏时间复杂度:O(n2)
    • 稳定性:稳定

    改进:当传进来的顺序表是有序的时候

    # coding:utf-8
    
    
    def bubble_sort(alist):
        """冒泡排序"""
        nums = len(alist)
        count = 0  # 记录是否有进行数据交换
        for j in range(nums-1):  # 规定要执行的次数
            for i in range(0, nums-1-j):  # 规定每次执行比较的个数
                if alist[i] > alist[i+1]:
                    alist[i], alist[i+1] = alist[i+1], alist[i]
                    count += 1
            if count == 0:  # 说明该序列是有序的序列,不必进行后面的比较,直接返回
                return alist
    
        return alist
    
    
    if __name__ == "__main__":
        b = bubble_sort([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
        print(b)
    

    选择排序

    # coding:utf-8
    
    def select_sort(alist):
        """选择排序"""
        n = len(alist)
        for j in range(n-1):  # 外层循环代表执行多少次
            min_index = j  # j: 0 ~ n-2 共n-1个数字
            for i in range(j, n):  # 内层循环表示每次从哪开始
                if alist[min_index] > alist[i]:
                    min_index = i
            alist[j], alist[min_index] = alist[min_index], alist[j]
        
        return alist
    
    
    if __name__ == "__main__":
        s = select_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6])
        print(s)
    

    时间复杂度

    • 最优时间复杂度:O(n2)
    • 最坏时间复杂度:O(n2)
    • 稳定性:不稳定(考虑升序每次选择最大的情况)

    插入排序

    # coding:utf-8
    
    def insert_sort(alist):
        """插入排序"""
        n = len(alist)
        for j in range(1, n):  # 右边的部分
             for i in range(0, j):  # 左边的部分 i=[0 ~ n-1]
                 if alist[i] > alist[j]:
                     alist[i], alist[j] = alist[j], alist[i]
           
        return alist
    
    
    if __name__ == "__main__":
        i = insert_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6])
        print(i)
    

    上面这种是错的,插入排序的思想是右边 无序部分 的值和左边 有序部分 的值的比较,而且是从左边 有序部分 的右边开始。因此应该改成这样:

    # coding:utf-8
    
    def insert_sort(alist):
        """插入排序"""
        n = len(alist)
        for j in range(1, n):  # 右边的部分
            for i in range(j, 0, -1):
                 if alist[i] > alist[j]:
                     alist[i], alist[j] = alist[j], alist[i]
          
        return alist
    
    
    if __name__ == "__main__":
        i = insert_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6])
        print(i)
    

    优化:

    # coding:utf-8
    
    def insert_sort(alist):
        """插入排序"""
        n = len(alist)
        for j in range(1, n):  # 右边的部分
            i = j
            while i > 0:
                if alist[i-1] > alist[i]:
                    alist[i-1], alist[i] = alist[i], alist[i-1]
                    i -= 1
                else:
                    break
    
        return alist
    
    
    if __name__ == "__main__":
        i = insert_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6])
        print(i)
    

    时间复杂度

    • 最优时间复杂度:O(n) (升序排列,序列已经处于升序状态)
    • 最坏时间复杂度:O(n2)
    • 稳定性:稳定

    希尔排序

    # coding:utf-8
    
    def shell_sort(alist):
        """希尔排序"""
        n = len(alist)
        gap = n//2  # 取对半
    
        while gap > 0:
            # 插入算法,与普通的插入算法的区别就是步长gap
            for j in range(gap, n):
                # j = [gap, gap+1, gap+2, gap+3]
                i = j
                while i > 0:
                    if alist[i] < alist[i-gap]:
                        alist[i], alist[i-gap] = alist[i-gap], alist[i]
                        i -= gap
                    else:
                        break
            # 缩短gap步长
            gap //= 2
    
        return alist
    
    
    if __name__ == "__main__":
        i = shell_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6])
        print(i)
    

    时间复杂度

    • 最优时间复杂度:根据步长序列的不同而不同
    • 最坏时间复杂度:O(n2)
    • 稳定想:不稳定

    快速排序

    # coding:utf-8
    
    def quick_sort(alist, first, last):
        """快速排序"""
        if first >= last:
            return
    
        mid_value = alist[first]
        low = first
        high = last
    
        while low < 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)  # 对同一个列表的操作,写成这样"quick_sort(alist[:low-1])"相当于传入新的列表
        # 对low右边的列表排序
        quick_sort(alist, low+1, last)
    
    
    if __name__ == "__main__":
        li = [1, 3, 7, 2, 8, 9, 4, 5, 0, 6]
        quick_sort(li, 0, len(li)-1)
        print(li)
    

    时间复杂度

    • 最优时间复杂度:O(nlogn)
    • 最坏时间复杂度:O(n2)
    • 稳定性:不稳定

    归并排序

    # coding:utf-8
    
    def merge_sort(alist):
        """归并排序"""
        n = len(alist)
        if n <=1:
            return alist
        min = n//2
        # left 采用归并排序后形成的新的有序的列表
        left_li = merge_sort(alist[:min])
        # right 采用归并排序后形成的新的有序的列表
        right_li = merge_sort(alist[min:])
        # 将两个有序的子序列合并为一个新的整体
    
        # 左右列表的两个指针
        left_pointer, right_pointer = 0, 0
        # 存放结果的列表
        result = []
        while left_pointer < len(left_li) and right_pointer < len(right_li):
            if left_li[left_pointer] <= right_li[right_pointer]:  # 加等于号 = 是为了遇到相等值时,前面的值还是在前面(稳定)
                result.append(left_li[left_pointer])
                left_pointer += 1
            # elif left_li[left_pointer] > right_li[right_pointer]:
            else:
                result.append(right_li[right_pointer])
                right_pointer += 1
        # 不管左边还是右边走到头,退出循环,然后把与之对应的那一边的最后一个值加进来
        result += left_li[left_pointer:]
        result += right_li[right_pointer:]
    
        return result
    
    
    if __name__ == "__main__":
        i = merge_sort([1, 3, 7, 2, 8, 9, 4, 5, 0, 6])
        print(i)
    

    易于理解的版本

    def merge_sort(alist):
        if len(alist) <= 1:
            return alist
        # 二分分解
        num = len(alist)/2
        left = merge_sort(alist[:num])
        right = merge_sort(alist[num:])
        # 合并
        return merge(left,right)
    
    def merge(left, right):
        '''合并操作,将两个有序数组left[]和right[]合并成一个大的有序数组'''
        #left与right的下标指针
        l, r = 0, 0
        result = []
        while l<len(left) and r<len(right):
            if left[l] < right[r]:
                result.append(left[l])
                l += 1
            else:
                result.append(right[r])
                r += 1
        result += left[l:]
        result += right[r:]
        return result
    
    alist = [54,26,93,17,77,31,44,55,20]
    sorted_alist = mergeSort(alist)
    print(sorted_alist)
    

    时间复杂度

    • 最优时间复杂度:O(nlogn)
    • 最坏时间复杂度:O(nlogn)
    • 稳定性:稳定

    二分查找

    # coding:utf-8
    
    def binary_search(alist, item):
        """二分查找 递归"""
        n = len(alist)
        if n > 0:
            min = n//2
            if item == alist[min]:
                return True
            elif item < alist[min]:
                return binary_search(alist[:min], item)
            else:
                return binary_search(alist[min+1:], item)
        else:
            return False
    
    
    def binary_search2(alist, item):
        """二分查找  非递归"""
        n = len(alist)
        first = 0
        last = n-1
        while first <= last:
            min = (first + last)//2
            if item == alist[min]:
                return True
            elif item < alist[min]:
                last = min -1
            else:
                first = min + 1
        return False
    
    
    if __name__ == "__main__":
        print(binary_search([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 5))
        print(binary_search([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 10))
        print(binary_search2([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 5))
        print(binary_search2([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 10))
    

    时间复杂度

    • 最优时间复杂度:O(1)
    • 最坏时间复杂度:O(logn)

    二叉树的定义和广度优先遍历和深度优先遍历

    # coding:utf-8
    
    class Node(object):
        """树的节点"""
        def __init__(self, item):
            self.elem = item
            self.lchild = None
            self.rchild = None
    
    
    class Tree(object):
        """二叉树"""
        def __init__(self):
            self.root = None
    
        def add(self, item):
            """树的插入"""
            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
                    break
                else:
                    queue.append(cur_node.lchild)
                if cur_node.rchild is None:
                    cur_node.rchild = node
                    break
                else:
                    queue.append(cur_node.rchild)
    
        def breadth_travel(self):
            """广度遍历"""
            if self.root is None:
                return
            queue = [self.root]
            while queue:
                cur_node = queue.pop(0)
                print(cur_node.elem, end=" ")
                if cur_node.lchild is not None:
                    queue.append(cur_node.lchild)
                if cur_node.rchild is not None:
                    queue.append(cur_node.rchild)
    
        def preorder(self, node):
            """先序遍历"""
            if node is None:
                return
    
            print(node.elem, end=" ")
            self.preorder(node.lchild)
            self.preorder(node.rchild)
    
        def inorder(self, node):
            """中序遍历"""
            if node is None:
                return
    
            self.inorder(node.lchild)
            print(node.elem, end=" ")
            self.inorder(node.rchild)
    
        def postorder(self, node):
            """后序遍历"""
            if node is None:
                return
    
            self.postorder(node.lchild)
            self.postorder(node.rchild)
            print(node.elem, end=" ")
    
    
    if __name__ == "__main__":
        tree = Tree()
        tree.add(0)
        tree.add(1)
        tree.add(2)
        tree.add(3)
        tree.add(4)
        tree.add(5)
        tree.add(6)
        tree.add(7)
        tree.add(8)
        tree.add(9)
        tree.breadth_travel()
        print("\n")
        tree.preorder(tree.root)
        print("\n")
        tree.inorder(tree.root)
        print("\n")
        tree.postorder(tree.root)
    
  • 相关阅读:
    MVP模式与MVVM模式
    webpack的配置处理
    leetcode 287 Find the Duplicate Number
    leetcode 152 Maximum Product Subarray
    leetcode 76 Minimum Window Substring
    感知器算法初探
    leetcode 179 Largest Number
    leetcode 33 Search in Rotated Sorted Array
    leetcode 334 Increasing Triplet Subsequence
    朴素贝叶斯分类器初探
  • 原文地址:https://www.cnblogs.com/yly123/p/11321334.html
Copyright © 2011-2022 走看看