python不同排序算法的比较

1. 冒泡排序:相邻两个数相比较,如果大于则交换顺序,有序区在列表尾部

  

   代码实例:  

def bubble_sort(li):
    for i in range(len(li)-1):
        for j in range(len(li)-i-1):
            if li[j] > li[j+1]:
                li[j], li[j+1] = li[j+1], li[j]

时间复杂度为O(N²) 如果遇到中途排序好而不发生变化的列表:[
7,8,9,1,2,3,4,5,6] 改进方法: def bubble_sort_better(li): for i in range(len(li)-1): andmark = False for j in range(len(li)-i-1): if li[j] > li[j+1]: li[j], li[j+1] = li[j+1], li[j] andmark = True if not andmark: return 值需要进行三次冒泡即可

 

2. 选择排序:第i个和后续的元素一一对比,如果小于则交换位置,有序区在列表头部

  

  代码实例: 

def select_sort(li):
    for i in range(len(li)-1):
        for j in range(i+1, len(li)):
            if li[i] > li[j]:
                li[i], li[j] = li[j], li[i]

时间复杂度O(N²)

创建新列表存放排序元素
def select_sort_new(li):
  new_li = []
  for i in range(len(li)):
    min_li = min(li)     # 遍历一次li
    new_li.append(min_li)
    li.remove(min_li)    # 遍历一次li
  return new_li

缺点:创建新的列表,增加空间复杂度,时间复杂度为O(N³)

 

 

3. 插入排序:将后续的元素和有序区的元素从右往左比较,大于则不变,小于则插入

  

 

   代码示例:

def insert_sort(li):
    for i in range(1,len(li)):          # i 为要插入元素的下标
        tem = li[i]                      # 保存插入元素的值
        j = i - 1                        # 插入元素的前一个元素
        while j >=0 and li[j]>tem:      # 当插入元素小于对比元素的时候,则将对比的元素后移
            li[j+1] = li[j]
            j -= 1                    # 向比较的元素继续往前移动
        li[j+1] = tem                # 如果大于对比的元素,则插入后面
           
时间复杂度为O(N²)

 

 

4. 快速排序:将元素把列表分成左右大小两个部分

  

 

   代码示例:

def partion(li, left, right):
    tem = li[left]        # 将左边的元素取出
    while left < right:     # 如果左边下标小于右边小标,保证中间存在元素
        while left < right and li[right] >= tem:  
            right -= 1
        li[left] = li[right]  # 将右边的的元素放到左边空位置上
        
        while left < right and li[left] <= tem:
            left += 1
        li[right] = li[left]
    li[left] = tem    # 当左右指针相等时,则将原来的数放到这个空位置上
    return left      # 返回这个分割的元素

# 递归
def quick_sort(li, left, right): if left < right: mid = partion(li, left, right) quick_sort(li, left, mid-1) quick_sort(li, mid+1, right) quick_sort(li, 0, len(li)-1)

时间复杂度为O(NlogN)

 

    

5. 堆排序:先将无序列表建大小根堆,在通过二叉树的算法逐一将最大元素作为根节点取出排序 

  堆排序的过程:

    1. 建立堆

    2. 得到堆顶元素为最大元素

    3. 去掉堆顶元素,将堆的最后一个元素放置堆顶,通过向下调整得出堆顶元素为第二大元素

    4. 重复以上步骤,知道堆元素为空

        

 

        

 

  代码示例:

import random
# 建堆函数
def sift(li, low, end):     # li列表,low堆的根节点位置,end堆的最后一个元素位置
   i = low      # i最开始指向根节点 j = 2 * i + 1       # j为二叉树每层的左孩子 tmp = li[low]       # 把堆顶存起来 while j <= end:      # 当j位置有元素 if j+1 <= end and li[j+1] > li[j]: # 存在右孩子并且比左孩子大 j = j + 1    # j指向右孩子 if li[j] > tmp    # 如果孩子大于堆顶的数 li[i] = li[j] # 堆顶的元素换成j的元素 i = j # 往下走一层 j = 2 * i + 1     # j重新赋值 else: li[i] = tmp   # 将取出的值放到对应的空位上 break else: li[i] = tmp   # 如果一开始就是最大的,则放原来的位置上 # 堆排序函数 def deap_sort(li): n = len(li) # 建堆过程,i为建堆时需要调整的根的下标,即每层二叉树的父节点 for i in range((n-2)//2, -1, -1): # (n-2)//2为二叉树的每个父节点,倒序到0,第二个-1是因为不包尾 sift(li, i, n-1) print(li) # 堆排序过程 for j in range(n-1, -1 ,-1):     # j为li的元素,从后往前开始循环 li[0], li[j] = li[j], li[0] # 第一个元素与最后一个元素交换,将最后一个元素放置堆顶,即取出元素过程 sift(li, 0, j-1) print(li)
li
= [i for i in range(100)] random.shuffle(li) heap_sort(li)

时间复杂度为O(NlogN)

# 第三方封装堆排序
import heapq
heapq.heapify(li) # 建堆
lis = []
for i in range(len(li)-1):
lis.append(heapq.heappop(li)) # 每次移除首个最小值元素
 

 

 

6. 归并排序:将列表两两区分,直到元素等于0或1,在进行排序合并

  

 

  

 

 

  代码示例:   

# 归并排序
def merge(li, low, mid, end):
    i = low
    j = mid + 1
    tmp = []
    while i <= mid and j <= end:    # 两表都存在数
        if li[i] <= li[j]:
            tmp.append(li[i])
            i += 1
        else:
            tmp.append(li[j])
            j += 1
    while i <= mid:     # 左边还存在元素
        tmp.append(li[i])
        i += 1
    while j <= end:     # 右边还存在元素
        tmp.append(li[j])
        j += 1
    li[low:end+1] = tmp

def merge_sort(li, low, end):
    if low < end:
        mid = (low + end) // 2
        merge_sort(li, low, mid)
        merge_sort(li, mid+1, end)
        merge(li, low, mid, end)

import random
li = list(range(100))
random.shuffle(li)
merge_sort(li, 0, len(li)-1)
print(li)

时间复杂度为O(NlogN)

 

 

 7. 六种排序的比较

  

 

 

 

8. 希尔排序:有插入排序变化而来,是一种分组插入排序算法

  1. 首先取一个整数d1 = n / 2,将元素分为d1个组,每组相邻量元素之间的距离是d1,在各组内进行排序

  2. 取第二个整数d2 = d1 / 2,重复上述分组过程,知道di = 1,即所有元素在同一组内进行直接插入排序

  3. 希尔排序每趟并不是使某些元素有序,而是使整体数据变得接近有序,最后一趟排序是的所有数据有序

    

 

   代码示例: 

# 希尔排序
import random
def shell_sort(li):
    d = len(li) // 2        # d的初始值为长度除以2
    while d >= 1:
        for i in range(d, len(li)):     # 第一次循环从d往后依次对比
            tmp = li[i]         # 将第一个对比的数存起来
            j = i - d           # j为每一组对应的数
            while j >= 0 and li[j] > tmp:
                li[j+d] = li[j]         # 大于交换位置
                j -= d          # 在向前进行比较
            li[j+d] = tmp       # 否则不变
        d //= 2                 # 第二次取d值

li = list(range(100))
random.shuffle(li)
shell_sort(li)

时间复杂度和选取的d序列有关

 

 

9. 计数排序:已知最大范围的列表,对其中的数据进行统计

  

 

   代码示例:

# 计数排序
def count_sort(li, max_count):
    count = [0 for _ in range(max_count+1)]      # 生成max_count个初始0
    for val in li:
        count[val] += 1     # 遍历计数过程
    li.clear()
    for index, val in enumerate(count):     # 获取下标和其对应的值
        for i in range(val):    
            li.append(index)    # 循环并添加对应下标数量

import random
li = [random.randint(0,100) for i in range(1000)]
count_sort(li,1000)

时间复杂度为O(N)

 

posted @ 2022-12-29 18:09  无敌小豆包  阅读(283)  评论(0)    收藏  举报