python实现排序算法后续

来源:互联网 发布:淘宝客博主的收入 编辑:程序博客网 时间:2024/05/01 21:25

    上一篇因为时间的缘故,没有能写全这几个经典的排序算法,这里补上了三个,其中快排在上一篇中已经出现了,放在这里的原因是:出于对比的目的,归并排序、快速排序、堆排序三个排序算法的时间性能都很优秀,时间复杂度也都相同,所以放在这里,当然快排是我本人最喜欢用的一种排序算法,这里关于三个算法的原理都不再累赘了,这一段时间写的博客完全是出于复习的目的,所以也是尽可能的都读透彻,读明白了才可以。下面看代码:

#!usr/bin/env python  #-*- coding: utf-8 -*- '''简介:三个时间复杂度一样的优秀排序算法:归并、快排、堆排序'''import timeimport random#随机序列生成器def randomnumber_generate(total_num=100, max_num=1000):    num_list = []    n = 1 #得到1000以内的100个随机数    while n <= total_num:        lin = random.randint(0, max_num)        num_list.append(lin)        n += 1    return num_list#堆调整def Heap_adjust(num_list, i, size):left_child = 2*i+1right_child = 2*i+2max_temp = i#print left_child, right_child, max_tempif left_child<size and num_list[left_child]>num_list[max_temp]:max_temp = left_childif right_child<size and num_list[right_child]>num_list[max_temp]:max_temp = right_childif max_temp != i:num_list[i], num_list[max_temp] = num_list[max_temp], num_list[i]Heap_adjust(num_list, max_temp, size) #避免调整之后以max为父节点的子树不是堆#创建堆def Create_heap(num_list, size):a = size/2-1for i in range(a, -1, -1):#print '**********', iHeap_adjust(num_list, i, size)#堆排序def Heap_sort(num_list, size):# b=size-1Create_heap(num_list, size)i = size-1while i > 0:num_list[0], num_list[i] = num_list[i], num_list[0]size -= 1i -= 1Heap_adjust(num_list, 0, size)return num_list#归并排序def MergeSort(num_list):  #分割终止条件    if len(num_list)<2:          return num_list      result_list = []     #将原始序列分为左右两部分 ,递归对两个子列表进行排序,典型的分而治之的思想    #print num_list[len(num_list)/2]    left_list = MergeSort(num_list[:len(num_list)/2])      right_list = MergeSort(num_list[len(num_list)/2:])      #分别开始比较两个子列表,将较小的元素添加进新的列表    while len(left_list)>0 and len(right_list)>0:          if left_list[0]<right_list[0]:              result_list.append(left_list.pop(0))          else:              result_list.append(right_list.pop(0))      #倘若两个列表比较结束,即一个列表已经都被加入结果列表    #则将另一个列表其余元素均加入结果列表    if len(left_list)>0:          result_list.extend(MergeSort(left_list))      else:          result_list.extend(MergeSort(right_list))      return result_list    #快排def quickSort(num_list):      if len(num_list)<2:          return num_list      left_list = []  #存放比基准结点小的元素    right_list = []  #存放比基准元素大的元素    base_node = num_list.pop(0) #在这里采用pop()方法的原因就是需要移除这个基准结点,并且赋值给base_node这个变量                                #在这里不能使用del()方法,因为删除之后无法再赋值给其他变量使用,导致最终数据缺失                                #快排每轮可以确定一个元素的位置,之后递归地对两边的元素进行排序    for one_num in num_list:          if one_num < base_node:              left_list.append(one_num)          else:              right_list.append(one_num)      return quickSort(left_list) + [base_node] + quickSort(right_list)  if __name__ == '__main__':    num_list = [1,5,8,9,4,3,5,6,89,14,25,23, -2, -67, 100, 23, -5]    start_time_create = time.time()    #num_list = randomnumber_generate(total_num=100, max_num=1000)    end_time_create = time.time()    print '随机序列生成耗时:', end_time_create - start_time_create    start_time1 = time.time()    result_list1 = Heap_sort(num_list, len(num_list))    end_time1 = time.time()    print "堆排序结果为"    #print num_list    print result_list1    print '堆排序总耗时:', end_time1 - start_time1    start_time3 = time.time()    result_list3 = MergeSort(num_list)    end_time3 = time.time()    print "归并排序结果为"    #print num_list    print result_list3    print '归并排序总耗时:', end_time3 - start_time3    start_time2 = time.time()    result_list2 = quickSort(num_list)    end_time2 = time.time()    print "快速排序结果为"    #print num_list    print result_list2    print '快速排序总耗时:', end_time2 - start_time2
使用小数据作为测试,本次运行得到的结果如下:

随机序列生成耗时: 0.0
堆排序结果为
[-67, -5, -2, 1, 3, 4, 5, 5, 6, 8, 9, 14, 23, 23, 25, 89, 100]
堆排序总耗时: 5.88893890381e-05
归并排序结果为
[-67, -5, -2, 1, 3, 4, 5, 5, 6, 8, 9, 14, 23, 23, 25, 89, 100]
归并排序总耗时: 0.000135183334351
快速排序结果为
[-67, -5, -2, 1, 3, 4, 5, 5, 6, 8, 9, 14, 23, 23, 25, 89, 100]
快速排序总耗时: 0.000169992446899
可以看到均正确的输出了,在之前的实验中发现一直出错没找到原因,错误在于:我把归并排序放在了快速排序的后面,导致归并排序的结果输出总是少一个数字:-67,后来才发现是因为在快速排序阶段因为使用了pop()方法,导致原始的数组被删除了基准元素,所以自然就会少一个数字了,换一下顺序就好了。

接下来使用随机序列生成器函数来自动的随机生成100个1000以内的数字来进行时间性能的测试,下面是结果:

随机序列生成耗时: 0.000493049621582
堆排序结果为
[5, 10, 13, 17, 50, 69, 72, 78, 79, 79, 88, 100, 108, 109, 110, 124, 125, 126, 135, 167, 167, 172, 196, 201, 210, 214, 221, 246, 269, 269, 271, 279, 283, 285, 289, 290, 298, 299, 308, 311, 314, 330, 369, 385, 406, 408, 418, 440, 445, 445, 459, 464, 473, 478, 493, 506, 508, 557, 562, 569, 577, 592, 596, 612, 617, 646, 654, 657, 676, 678, 685, 694, 716, 721, 738, 762, 794, 810, 814, 815, 818, 819, 825, 837, 838, 842, 852, 868, 872, 881, 882, 887, 890, 906, 908, 942, 948, 977, 981, 991]
堆排序总耗时: 0.000715017318726
归并排序结果为
[5, 10, 13, 17, 50, 69, 72, 78, 79, 79, 88, 100, 108, 109, 110, 124, 125, 126, 135, 167, 167, 172, 196, 201, 210, 214, 221, 246, 269, 269, 271, 279, 283, 285, 289, 290, 298, 299, 308, 311, 314, 330, 369, 385, 406, 408, 418, 440, 445, 445, 459, 464, 473, 478, 493, 506, 508, 557, 562, 569, 577, 592, 596, 612, 617, 646, 654, 657, 676, 678, 685, 694, 716, 721, 738, 762, 794, 810, 814, 815, 818, 819, 825, 837, 838, 842, 852, 868, 872, 881, 882, 887, 890, 906, 908, 942, 948, 977, 981, 991]
归并排序总耗时: 0.00460505485535
快速排序结果为
[5, 10, 13, 17, 50, 69, 72, 78, 79, 79, 88, 100, 108, 109, 110, 124, 125, 126, 135, 167, 167, 172, 196, 201, 210, 214, 221, 246, 269, 269, 271, 279, 283, 285, 289, 290, 298, 299, 308, 311, 314, 330, 369, 385, 406, 408, 418, 440, 445, 445, 459, 464, 473, 478, 493, 506, 508, 557, 562, 569, 577, 592, 596, 612, 617, 646, 654, 657, 676, 678, 685, 694, 716, 721, 738, 762, 794, 810, 814, 815, 818, 819, 825, 837, 838, 842, 852, 868, 872, 881, 882, 887, 890, 906, 908, 942, 948, 977, 981, 991]
快速排序总耗时: 0.00185680389404

三者对比之下,时间性能都很出色,相差的也是很小的,因为还有其他因素的干扰,感兴趣的还可以使用随机数列生成函数来进行翻倍处理,看看时间性能的变化是怎么样的。

0 0
原创粉丝点击