三、排序

1. 冒泡排序

  • 思想:每次都是相邻元素进行比较,当后面的元素小于前面元素时,就进行交换位置 。
  • 时间复杂度:O(N^2)    空间复杂度:O(1)
  • 稳定性:稳定
def bubble_sort_mod(array):  
    for i in range(len(array)): 
        is_sorted = True 
        for j in range(1, len(array) - i):
            if (array[j] < array[j - 1]):
                array[j], array[j - 1] = array[j - 1], array[j]
                is_sorted = False        
        if (is_sorted): break
    return array   

2. 选择排序

  • 思想:是对冒泡排序的改进,每一轮仅进行一次交换,把最大值换到最后面即可。
  • 时间复杂度:O(N^2)     空间复杂度:O(1)
  • 稳定性:不稳定
# 这里是每一轮换最大值,把最大值换到数组最后面去
def selection_sort(nums):
    for i in range(len(nums)):
        pos_max = 0 
        for j in range(1, len(nums) - i):
            if nums[j] > nums[pos_max]:
                pos_max = j 
        nums[len(nums)-i-1], nums[pos_max] = nums[pos_max], nums[len(nums)-i-1]
    return nums

3.  插入排序

  • 思想:类似于打牌的时候人们插牌的方式,来一张新牌就把它与前面排好的牌进行比对,找到合适的插入位置。
  • 时间复杂度:O(N^2)    空间复杂度:O(1)
  • 稳定性:稳定
def insert_sort(nums):
    for i in range(1, len(nums)):
        current_value = nums[i]
        position = i 
        while position > 0 and nums[position-1] > current_value:  # while 循环实现 
            nums[position] = nums[position-1]  # 移动操作仅一次赋值,是交换操作的三分之一,此时性能会好一些 
            position -= 1 
        nums[position] = current_value  # 插入 
    return nums

4. 希尔排序

  • 思想:希尔排序就是再插入排序的基础上多了个gap而已。
  • 时间复杂度:O(N^1.3)       空间复杂度:O(1)
  • 稳定性:不稳定
def shell_sort(nums):
    sublistcount = len(nums) // 2 
    while sublistcount > 0:
        for startposition in range(sublistcount):
            gapInsertionSort(nums, startposition, sublistcount)
        print("After increments of size", sublistcount, "The list is", nums)
        sublistcount = sublistcount // 2 
    return nums 

def gapInsertionSort(nums, start, gap): #插入排序 
    for i in range(start+gap, len(nums), gap):
        currentvalue = nums[i]
        position = i 
    
        while position >= gap and nums[position-gap] > currentvalue:
            nums[position] = nums[position-gap]
            position -= gap 
        nums[position] = currentvalue 

5. 计数排序

  • 思想:首先找到数组的最大值和最小值,根据这两个值制造一定长度的抽屉。其次要把数字一个个的放到抽屉里面,然后再按顺序拿出来。
  • 时间复杂度:O(N)     空间复杂度:O(K), K表示最大值与最小值之差
  • 稳定性:稳定
def count_sort(items):
    mmax, mmin = max(items), min(items)
    nums = mmax - mmin + 1 
    counts = [0] * nums 
    for i in range(len(items)):
        counts[items[i]-mmin] = counts[items[i] - mmin] + 1 
    pos = 0 
    for i range(nums): # 只是从抽屉里把所有的数都拿出来,O(n)复杂度
        for j in range(counts[i]):
            items[pos] = i + mmin 
            pos += 1 
    return items 

6. 归并排序

  • 思想:将数组持续分为两半,分别对两半运用双指针的办法进行归并排序。是一种递归的方法
  • 时间复杂度:O(N)   空间复杂度:O(1)
  • 稳定性:稳定
# 更python的写法 
def merge_sort(nums):
    if len(nums) <= 1: # base情况 也就是递归的结束条件
        return nums 
    # 分解问题,并递归调用
    middle = len(nums) // 2 
    left = merg_sort(nums[:middle])  #  左半部
    right = merg_sort(nums[middle:]) # 右半部
    
    # 合并左右半步,完成排序
    merged = []
    while left and right:
        if left[0] <= right[0]:
            merged.append(left.pop(0))
        else:
            merged.append(right.pop(0))
    merged.extend(right if right else left)
    return merged 

7. 快速排序

  • 思想:依据一个“中值”数据项把数组分为两半:小于中值的一半和大于中值的一半。然后分别对两半进行快速排序。
  • 时间复杂度:O(NlgN)    空间复杂度:  首先就地快速排序使用的空间是O(1)的,也就是个常数级;而真正消耗空间的就是递归调用了,因为每次递归就要保持一些数据;
  • 稳定性:不稳定
def quickSort(nums):
    quickSortHelper(nums, 0, len(nums)-1)
    
def quickSortHelper(nums, first, last):
    if first < last:
        splitpoint = partition(nums, first, last) # 先找到中点 
        quickSortHelper(nums, first, splitpoint-1)
        quickSortHelper(nums, splitpoint+1, last)

def partition(nums, first, last):
    pivotvalue = nums[first]
    leftmark = first + 1 
    rightmark = last
    done = False 
    while not done:
        while leftmark <= rightmark and nums[leftmark] <= pivotvalue:
            leftmark += 1 
        while leftmark <= rightmark and nums[rightmark] >= pivotvalue:
            rightmark -= 1
        if rightmark < leftmark:
            done = True 
        else:
            nums[leftmark], nums[rightmark] = nums[rightmark], nums[leftmark]
            
    nums[first], nums[rightmark] = nums[rightmark], nums[first]
    return rightmark 

  

posted @ 2020-12-22 21:44  RamboBai  阅读(124)  评论(0编辑  收藏  举报