python堆排序、归并排序

'''
堆排序:
	堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
	1)最大堆(最小堆)调整:将堆的末端子节点作调整,使得子节点永远小于(大于)父节点
	2)创建最大堆(小堆):将堆中的所有数据重新排序
	3)堆排序:移除位在第一个数据的根节点,并做最大堆(小堆)调整的递归运算

问题1:当堆顶元素改变时,如何重建堆?
	首先将完全二叉树根结点中的记录移出,该记录称为待调整记录。此时根结点相当于空结点。从空结点的左、右子中选出一个关键字较小的记录,如果该记录的关键字小于待调整记录的关键字,则将该记录上移至空结点中。此时,原来那个关键字较小的子结点相当于空结点。重复上述移动过程,直到空结点左、右子的关键字均不小于待调整记录的关键字。此时,将待调整记录放入空结点即可。上述调整方法相当于把待调整记录逐步向下“筛”的过程,所以一般称为“筛选”法。

问题2:如何由一个任意序列建初堆?
	一个任意序列看成是对应的完全二叉树,由于叶结点可以视为单元素的堆,因而可以反复利用“筛选”法,自底向上逐层把所有子树调整为堆,直到将整个完全二叉树调整为堆。 

问题3:如何利用堆进行排序(进行堆排序的步骤)?
	1)将待排序记录按照堆的定义建初堆(算法9.10),并输出堆顶元素;
	2)调整剩余的记录序列,利用筛选法将前n-i个元素重新筛选建成为一个新堆,再输出堆顶元素;
	3)重复执行步骤②n-1次进行筛选, 新筛选成的堆会越来越小,而新堆后面的有序关键字会越来越多,最后使待排序记录序列成为一个有序的序列,这个过程称之为堆排序。 

时间复杂度:O(nlog2n)

稳定性:不稳定排序算法
'''

#构造大根堆
def createHeap(mylist,index,heap_size):
    #建立堆的起始索引
    largest = index
    #左右孩子结点
    left_child = 2 * index + 1
    right_child = 2* index + 2

    #判断左右孩子索引是否超出索引;并且比较值的大小
    if left_child < heap_size and mylist[left_child] > mylist[largest]:
        largest = left_child
    if right_child < heap_size and mylist[right_child] > mylist[largest]:
        largest = right_child

    #判断索引的初始位置和当前的位置是否相同,不相同比较大小之后交换位置
    if largest != index:
        mylist[largest],mylist[index] = mylist[index],mylist[largest]
        #递归继续建堆
        createHeap(mylist,largest,heap_size)

def heapSort(mylist):
    #自底向上建堆
    for i in range(len(mylist)//2 - 1,-1,-1):
        createHeap(mylist,i,len(mylist))

    #堆顶元素互换
    for j in range(len(mylist) - 1,0,-1):
        mylist[0],mylist[j] = mylist[j],mylist[0]
        #字堆顶建堆
        createHeap(mylist,0,j)

    return mylist


if __name__ == '__main__':
    mylist = [5,7,2,4,2,36,8,1,2,89,27,12,11]
    print(heapSort(mylist))
'''
归并排序(速度仅次于快排):
	建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
	
	1)将一组无序的数组使用二分思想进行分割,直至分到每一个子序列只剩一个元素,或者子序列有序时,然后开始合并,分为子序列时可以使用递归。
	2)通过不断的分割之后,所有的子序列都已经内部有序,之后进行合并,也就是二路归并,通过比较,将两个有序的序列合并为一个有序的序列,之后重复合并,直至所有的序列都合并完成,需要排序的数组就排序完成了。

时间复杂度:O(nlog2n)

稳定性:稳定排序算法
'''

def mergesort(newlist1,newlist2):
    #定义一个空列表,方便合并两个有序数组
    nums = []
    #定义一个计数
    x, y = 0, 0
    #长度小于两个分组的长度
    while x < len(newlist1) and y < len(newlist2):
        #找出两个数组中较小的,添加到空列表中,小的数组的下标+1
        if newlist1[x] < newlist2[y]:
            nums.append(newlist1[x])
            x += 1
        else:
            #反之另外一个加入空列表中,下标+1
            nums.append(newlist2[y])
            y += 1
    #当其中一个遍历完成之后,另外的一个数组中的元素全部添加到数组中
    if x == len(newlist1):
        for i in newlist2[y:]:
            nums.append(i)
    else:
        for i in newlist1[x:]:
            nums.append(i)
    return nums

def merge(mylist):
    if len(mylist) < 2:
        return mylist
    else:
        # 归并排序使用的是二分思想,不断将其二分
        _index = len(mylist) // 2
        # 递归调用继续二分
        left_index = merge(mylist[:_index])
        right_index = merge(mylist[_index:])
        # 多次二分之后,当只剩一个元素时,一定有序,调用函数进行合并
        return mergesort(left_index,right_index)


if __name__ == '__main__':
    mylist = [2,3,4,2,1,7,8,5,99,0,1,-1,-6,45]
    print(merge(mylist))


发布了63 篇原创文章 · 获赞 1 · 访问量 2047

猜你喜欢

转载自blog.csdn.net/qq_45061361/article/details/104033393