快排&堆排&归排

1.快排

def quick(list):
    if len(list) < 2:
        return list

    tmp = list[0]  # 临时变量 可以取随机值
    left = [x for x in list[1:] if x <= tmp]  # 左列表
    right = [x for x in list[1:] if x > tmp]  # 右列表
    return quick(left) + [tmp] + quick(right)

li = [4,3,7,5,8,2]
print quick(li)  # [2, 3, 4, 5, 7, 8]

#### 对[4,3,7,5,8,2]排序
'''
[3, 2] + [4] + [7, 5, 8]                 # tmp = [4]
[2] + [3] + [4] + [7, 5, 8]              # tmp = [3] 此时对[3, 2]这个列表进行排序
[2] + [3] + [4] + [5] + [7] + [8]        # tmp = [7] 此时对[7, 5, 8]这个列表进行排序
'''

在这里插入图片描述
原理:
从排序前--------> 到P归位 经历过程(前面都比5小后面都比5大)
1、 首先从右向左比较,取出列表第一个元素5(第一个位置就空出来)与列表最后一个元素8比较,8>5不换位置
2、 用5与-2位置的9比,5<9不换位置
3、 5与-3位置的2比较,2<5,将-3位置的5放到1号位置,那么-3号位置空出来了,然后从左往右比较
4、 5与2号位置的7比,5<7,将7放到-3号位置,2号位置空出来了,在从右往左比
5、 -4号位置的1小于5将1放到空出的2号位置,-4位置空出来了,再从右向左比
6、 这样第一次循环就实现了5放到列表中间,前面的都比5大,后面的都比5小

2.堆排

def sift(data, low, high):
   '''  构造堆  堆定义:堆中某节点的值总是不大于或不小于父节点的值
   :param data: 传入的待排序的列表
   :param low:  需要进行排序的那个小堆的根对应的号
   :param high: 需要进行排序那个小堆最大的那个号
   :return:
   '''
   i = low            #i最开始创建堆时是最后一个有孩子的父亲对应根的号
   j = 2 * i+ 1       #j子堆左孩子对应的号
   tmp = data[i]      #tmp是子堆中原本根的值(拿出最高领导)
   while j <= high:  #只要没到子堆的最后(每次向下找一层)  #孩子在堆里
      # if j < high and data[j] < data[j + 1]:
      if j + 1 <= high and data[j] < data[j + 1]: #如果有右孩纸,且比左孩子大
         j += 1
      if tmp < data[j]:        #如果孩子还比子堆原有根的值tmp大,就将孩子放到子堆的根
         data[i] = data[j]     #孩子成为子堆的根
         i = j                 #孩子成为新父亲(向下再找一层)
         j = 2 * i + 1         #新孩子  (此时如果j<=high证明还有孩,继续找)
      else:
         break                 #如果能干就跳出循环就会流出一个空位
   data[i] = tmp                #最高领导放到父亲位置

def heap_sort(data):
   '''调整堆'''
   n = len(data)
   # n//2-1 就是最后一个有孩子的父亲那个子堆根的位置
   for i in range(n // 2 - 1, -1, -1):  #开始位置,结束位置, 步长       这个for循环构建堆
      # for循环输出的是: (n // 2 - 1 ) ~ 0 之间的数
      sift(data, i , n-1)     # i是子堆的根,n-1是堆中最后一个元素


data = [20,50,20,60,70,10,80,30,40]
heap_sort(data)
print data  # [80, 70, 20, 60, 50, 10, 20, 30, 40]

3.归排

原理图:
在这里插入图片描述

def merge(li, low, mid, high):
   '''
   :param li:      带排序列表
   :param low:     列表中第一个元素下标,一般是:0
   :param mid:     列表中间位置下标
   :param high:    列表最后位置下标
   :return:
   '''
   i = low
   j = mid + 1
   ltmp = []
   while i <= mid and j <= high:
      if li[i] < li[j]:
         ltmp.append(li[i])
         i += 1
      else:
         ltmp.append(li[j])
         j += 1
   while i <= mid:
      ltmp.append(li[i])
      i += 1
   while j <= high:
      ltmp.append(li[j])
      j += 1
   li[low:high+1] = ltmp

def mergesort(li, low, high):
   if low < high:
      mid = (low + high) // 2          #获取列表中间的索引下标
      mergesort(li, low, mid)          #先分解
      mergesort(li, mid+1, high)
      merge(li, low, mid, high)        #然后合并

data = [10,4,6,3,8,2,5,7]
mergesort(data, 0 , len(data) -1)
print(data)                            # [2, 4, 6, 8, 10, 12, 14, 16, 18]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值