归并排序与归并排序的使用及归并排序与快速排序、堆排序运行时间比较

"""归并排序"""
'''
假设现在的列表分两段有序,如何将其合成为一个有序列表:[2]578|9|[1]346  ,其中指针i指向2,j指向1,中间mid=9。这种操作称为一次归并
第1步:2和1比较,1小存入ltmp=[1],j指针移动+1;
第2步:i指向2,j指向3,2和3比较,2小,2存入列表litmp=[1,2],i指针移动+1;
第3步:i指向5,j指向3,5和3比较,3小,3存入列表litmp=[1,2,3],j指针移动+1;
第4步:i指向5,j指向4,5和4比较,4小,4存入列表litmp=[1,2,3,4],j指针移动+1;
第5步:i指向5,j指向6,5和6比较,5小,5存入列表litmp=[1,2,3,4,5],i指针移动+1;
第6步:i指向7,j指向6,6和7比较,6小,6存入列表litmp=[1,2,3,4,5,6],j指针移动+1,
第7步:i指向7,j指向空,右边无元素,无需比较,则剩下左边部分都出来7、8、9,即7、8、9存入列表litmp=[1,2,3,4,5,6,7,8,9];
'''

def merge(li,low,mid,high):
    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,肯定有一部分没数了
    #如果右半部分无数字结束
    while i<=mid:
        ltmp.append(li[i])
        i+=1
    # 如果左半部分无数字结束
    while j<=high:
        ltmp.append(li[j])
        j+=1
    #将存入ltmp中排好序的数值写回去li 因为li函数参数截出来就是从low到high
    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)
#时间复杂度





###---------------------归并排序的使用-----------------------------
"""
归并排序
分解:将列表越分越小,直至分成一个元素
终止条件:一个元素是有序的
合并:将两个有序列表归并,列表越来越大。
"""

def merge(li,low,mid,high):
    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,肯定有一部分没数了
    while i<=mid:
        ltmp.append(li[i])
        i+=1
    while j<=high:
        ltmp.append(li[j])
        j+=1
    li[low:high+1]=ltmp


def merge_sort(li,low,high):
   if low<high:#至少有两个元素,递归
       mid=(low+high)//2
       merge_sort(li,low,mid)
       merge_sort(li,mid+1,high)
       merge(li,low,mid,high)


#测试
import random
li=list(range(1000))
random.shuffle(li)
print(li)
merge_sort(li,0,len(li)-1)
print(li)
##########NB三人组#################
'''
三种排序算法的事件复杂度都是O(nlogn)
一般情况下,就运行时间而言:
   快速排序<归并排序<堆排序
三种排序算法的缺点:
   快速排序:极端情况下排序效率低
   归并排序:需要额外的内存开销
   堆排序:在快的排序算法中相对较慢
   
 快速排列

    优点:虽然三种算法的时间复杂度都是O(nlogn),但是三者速度仍然有微小区别,快排是NB三人组算法中最快的一个

    缺点:快排算法可能出现最坏情况,这个情况的出现在每次要归位的数是所有剩余数中最大(或者最小的数)时,此时快速排列的时间复杂度是O(n**2)

 

  归并排序

    优点:归并排序速度第二

    缺点:空间复杂度为O(n),消耗内存

 

  堆排序

    优点:可以实现部分排序

    缺点:速度是三者中最慢的,代码复杂,逻辑复杂

       运行时间装饰器
'''
#####快速排序、归并排序、堆排序时间运行比较代码实现######
# 运行时间装饰器



import time
def tell_time(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)
        end_time = time.time()
        print(end_time - start_time)
        return res
    return wrapper

##————————————————————————————————————————————————————————————————###########

import random
from common import *

li = [i for i in range(100000)]
random.shuffle(li)

li1 = li.copy()  # 将列表拷贝三份
li2 = li.copy()
li3 = li.copy()


def position(li, head, end):  # 一次归位函数
    tmp = li[head]
    while head < end:
        while head < end and li[end] >= tmp:
            end -= 1
        li[head] = li[end]
        while head < end and li[head] <= tmp:
            head += 1
        li[end] = li[head]
    li[head] = tmp
    return head


def _quick_sort(li, head, end):  # 快速排列由外到内
    if head < end:
        mid = position(li, head, end)
        _quick_sort(li, head, mid-1)
        _quick_sort(li, mid+1, head)


@tell_time
def quick_sort(li, head, end):  # 为了避免递归对装饰器的影响
    _quick_sort(li, head, end)


def sift(li, head, end):  # 向下调整函数
    tmp = li[head]
    i = head
    j = head * 2 + 1
    while j <= head:
        if j+1 <= head and li[j+1] > li[j]:
            j += 1
        if li[j] > tmp:
            li[i] = li[j]
            i = j
            j = j * 2 + 1
        else:
            break
    li[i] = tmp


@tell_time
def heap_sort(li):  # 堆排序
    end = len(li) - 1
    for i in range((end - 1) // 2, -1, -1):
        sift(li, i, end)

    for i in range(end, 0, -1):
        li[0], li[i] = li[i], li[0]
        sift(li, 0, i-1)


def merge(li, head, mid, end):  # 一次归并函数
    i = head
    j = mid + 1
    tmp_li = []
    while i <= mid and j <= end:
        if li[i] <= li[j]:
            tmp_li.append(li[i])
            i += 1
        else:
            tmp_li.append(li[j])
            j += 1

    while i <= mid:
        tmp_li.append(li[i])
        i += 1

    while j <= end:
        tmp_li.append(li[j])
        j += 1

    li[head:end+1] = tmp_li


def _merge_sort(li, head, end):
    if head < end:  # 归并排序由内到外
        mid = (head + end) // 2
        _merge_sort(li, head, mid)
        _merge_sort(li, mid+1, end)
        merge(li, head, mid, end)


@tell_time
def merge_sort(li, head, end):
    _merge_sort(li, head, end)

quick_sort(li1, 0, len(li1) - 1)
merge_sort(li2, 0, len(li2) - 1)
heap_sort(li3)

#测试堆排序、快速排序、归并排序时间运行
print('-----------------------------','测试堆排序、快速排序、归并排序时间运行')
import random,copy
li=list(range(100000))
random.shuffle(li)

li1=copy.deepcopy(li)
li2=copy.deepcopy(li)
li3=copy.deepcopy(li)


quick_sort(li1)
heap_sort(li2)
merge_sort(li3)
'''
基础算法总结

  算法名称     时间复杂度——最好——平均——最坏        空间复杂度          稳定性

  冒泡排序      O(n) O(n**2)   O(n**2)           O(1)            稳定

  选择排序      O(n**2) O(n**2)   O(n**2)         O(1)            不稳定

  插入排序     O(n**2)    O(n**2)   O(n**2)        O(1)            稳定

  快速排序     O(nlogn)  O(nlogn)  O(n**2)         O(1)            不稳定

  归并排序    O(nlogn)   O(nlogn) O(nlogn)         O(n)              稳定

  堆排序     O(nlogn)   O(nlogn) O(nlogn)         O(1)            不稳定
'''







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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

落雪snowflake

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值