python 学习(排序)

python 学习(排序)

  1. 时间复杂度为N^2: 冒泡排序,插入排序,选择排序。
  2. 时间复杂度为NlogN:堆排序,快速排序, 归并排序。
  3. 时间复杂度基于数据大小:计数排序,基数排序。

常用的排序算法,使用python实现。

冒泡排序

def buble(num):
	for i in range(len(num)):
		count = 0
		for j in range(len(num)-1-i):
			if num[j] > num[j+1]:
				num[j], num[j+1] = num[j+1], num[j]
				count += 1
		if count == 0:
			break
	return num

每次将元素从底到顶遍历,如果当前元素比下一个元素大就交换,使得最大的元素在顶部。每次遍历顶部减一, 直至底到顶只有一个元素。 P.S如果一次遍历中没有发生交换,则该数组已经有序。

插入排序

def insert(num):
	n = len(num)

	for i in range(n-1):
		for j in range(i+1, 0, -1):
			if num[j] < num[j-1]:
				num[j], num[j-1] = num[j-1], num[j]
			else:
				break
	return num

从底部向顶部遍历,如果当前元素小于前一个元素就交换,该次遍历结束至底部。当底部顶部重合时结束排序。

选择排序

def select(num):
	n = len(num)

	for i in range(n):
		minIndex = i
		for j in range(i, n):
			if num[minIndex] > num[j]:
				minIndex = j
		num[i], num[minIndex] = num[minIndex], num[i] 
	return num

堆排序

从底部开始,遍历数组,保留数组中最小的数并与数组底部交换。数组底部+1,直至底部顶部重合。

def heapSort(nums):
    if len(nums) < 2:
        return nums

    for i in range(len(nums)):
        heapInsert(nums, i)
    size = len(nums)-1
    while size > 0:
        nums[size] = heapPop(nums, size)
        size -= 1
    return nums
    
def heapInsert(nums, i):
    while nums[i] > nums[(i-1) // 2] and i > 0:
        nums[i], nums[(i-1) // 2] = nums[(i-1) // 2], nums[i]
        i += (i-1) // 2

def heapPop(nums, size):
    t = nums[0]
    nums[0] = nums[size]
    index = 0
    left = index*2 + 1
    right = index*2 + 2
    while left < size-1:
        largest = right if right < size and nums[right] > nums[left] else left
        largest = index if nums[index] > nums[largest] else largest
        if index == largest:
            break
        nums[index], nums[largest] = nums[largest], nums[index]
        index = largest
        left = index*2 + 1
        right = index*2 + 1
    return t

构建小根堆(堆顶为最小值)。将数组放入堆中,再每次弹出堆顶,直至堆空。

快速排序

def quick(num):
	if len(num) < 2:
		return num
	quick_sort(num, 0, len(num)-1)
	return num

def quick_sort(num, l, r):
	if l < r:
		p = partition(num, l, r)
		quick_sort(num, l, p[0])
		quick_sort(num, p[1], r)

def partition(num, l, r):
	less = l-1
	more = r
	index = l

	while index < more:
		if num[index] < num[more]:
			less += 1
			num[index], num[less] = num[less], num[index]
			index += 1
		elif num[index] > num[more]:
			more -= 1
			num[more], num[index] = num[index], num[more]
		else:
			index += 1
	num[index], num[r] = num[r], num[index]
	return [less, more]

主要核心是partition过程。partition根据最后一个值,划分出比该值大的区域和比该值小的区域。分割数组,划分partition区域,直至不能划分为止。

归并排序

def merge(num):
	if len(num) < 2:
		return num

	mid = len(num) // 2
	left = merge(num[:mid])
	right = merge(num[mid:])
	return merge_sort(left, right)

def merge_sort(left, right):
	c = []
	l = 0
	r = 0

	while l < len(left) and r < len(right):
		if left[l] <= right[r]:
			c.append(left[l])
			l += 1
		else:
			c.append(right[r])
			r += 1
	
	if l == len(left):
		for i in right[r:]:
			c.append(i)
	else:
		for i in left[l:]:
			c.append(i)
	return c

分而治之思想,分化两侧,直至两侧长度为1。再将两侧合并在一起,由于每次归并时,两侧内容都是有序的,节省了时间。

计数排序

def countNums(nums):
    n = len(nums)
    res = [None]*n

    for i in range(n):
        p = 0
        for j in range(n):
            if nums[i] > nums[j]:
                p += 1
        res[p] = nums[i]
    return res

统计数组中其他数比该数大的个数p(越小的数,p越小)。p代表该数的排序后的位置。

基数排序

def radixSort(nums):
    i = 0
    n = 1

    max_ = max(nums)
    num_t = [int(k) for k in list(str(max_))]
    n = len(num_t)

    while i < n:
        bucket = {}
        for x in range(10):
            bucket[x] = []
        for x in nums:
            radix =(x / (10**i)) % 10
            bucket[radix].append(x)
        j = 0
        for k in range(10):
            if len(bucket[k]) > 0:
                for y in bucket[k]:
                    nums[j] = y
                    j += 1
        i +=1
    return nums

按每一位大小排序,从低位排到高位。

稳定性

根据排序前后相对次序是否变化将算法分为,稳定和不稳定。P.S:即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。(引用百度百科)
不稳定排序:选择排序、快速排序、希尔排序、堆排序。

稳定排序:冒泡排序、插入排序、归并排序和基数排序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值