Python入门篇-数据结构堆排序Heap Sort

          Python入门篇-数据结构堆排序Heap Sort
python

                                      做者:尹正杰算法

版权声明:原创做品,谢绝转载!不然将追究法律责任。数据结构

 

 

 

一.堆Heap编码

  堆是一个彻底二叉树
  每一个非叶子结点都要大于或者等于其左右孩子结点的值称为大顶堆
  每一个非叶子结点都要小于或者等于其左右孩子结点的值称为小顶堆
  根结点必定是大顶堆中的最大值,必定是小顶堆中的最小值

 

二.大顶堆spa

  彻底二叉树的每一个非叶子结点都要大于或者等于其左右孩子结点的值称为大顶堆
  根结点必定是大顶堆中的最大值

 

三.小顶堆code

  彻底二叉树的每一个非叶子结点都要小于或者等于其左右孩子结点的值称为小顶堆
  根结点必定是小顶堆中的最小值

 

四.构建彻底二叉树orm

  待排序数字为30,20,80,40,50,10,60,70,90.
  构建一个彻底二叉树存放数据,并根据性质5对元素编号,放入顺序的数据结构中.
  构造一个列表为[0,30,20,80,40,50,10,60,70,90].

 

五.构建大顶堆 blog

1>.核心算法排序

  度数为2的结点A,若是它的左右孩子结点的最大值比它大的,将这个最大值和该结点交换.
  度数为1的结点A,若是它的左孩子的值大于它,则交换.
  若是结点A被交换到新的位置,还须要和其孩子结点重复上面的过程.

2>.起点结点的选择utf-8

  从彻底二叉树的最后一个结点的双亲结点开始,即最后一层的最右边叶子结点的父结点开始.
  结点数为n,则起始结点的编号为n//2(性质5).

3>.下一个结点的选择

  从起始结点开始向左找其同层结点,到头后再从上一层的最右边结点开始继续向左逐个查找,直至根结点.

4>.大顶堆的目标

  确保每一个结点的都比左右结点的值大.

5>.排序

  将大顶堆根结点这个最大值和最后一个叶子结点交换,那么最后一个叶子结点就是最大值,将这个叶子结点排除在待排序结点以外.
  从根结点开始(新的根结点),从新调整为大顶堆后,重复上一步.
  堆顶和最后一个结点交换,并排除最后一个结点.

 6>.代码实现

 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 
 7 
 8 import math
 9 
10 
11 def print_tree(array):
12     index = 1
13     depth = math.ceil(math.log2(len(array)))        #由于补0了,否则应该是math.ceil(math.log2(len(array) + 1)
14     sep = " "
15     for i in range(depth):
16         offset = 2 ** i
17         print(sep * (2 **(depth - i -1)-1),end="")
18         line = array[index:index + offset]
19         for j,x in enumerate(line):
20             print("{:>{}}".format(x,len(sep)),end="")
21             interval = 0 if i == 0 else 2 ** (depth - i) -1
22             if j < len(line) - 1:
23                 print(sep * interval,end="")
24             index += offset
25             print()
26 
27 #为了和编码对应,增长一个无用的0在首位
28 origin = [0,30,20,80,40,50,10,60,70,90]
29 total = len(origin) - 1     #初始化排序元素个数,即n
30 print(origin)
31 
32 print_tree(origin)
33 print_tree("=" * 50)
34 
35 
36 
37 def heap_adjust(n,i,array:list):
38     """
39         调整当前结点(核心算法)
40         调整的节点的起点在n//2,保证全部的调整的结点都有孩子结点
41     :param n: 待比较数个数
42     :param i: 当前结点的下标
43     :param array:待排序的数据
44     :return:
45     """
46     while 2 * i <= n:
47         #孩子结点判断2i位左孩子,2i+1为右孩子
48         lchile_index = 2 * i
49         max_child_index = lchile_index              #n = 2i
50         if n > lchile_index and array[lchile_index +1] > array[lchile_index]:       #n > 2i说明还有右孩子
51             max_child_index = lchile_index + 1      #n = 2i +1
52 
53         #和子树的根结点比较
54         if array[max_child_index] > array[i]:
55             array[i],array[max_child_index] = array[max_child_index],array[i]
56             i = max_child_index                     #被比较后,须要判断是否须要调整
57         else:
58             break
59 
60 #构建大顶推,大根堆
61 def max_heap(total,array:list):
62     for i in range(total//2,0,-1):
63         heap_adjust(total,i,array)
64     return array
65 
66 print_tree(max_heap(total,origin))
67 print_tree("=" * 50)
68 
69 #排序
70 def sort(total,array:list):
71     while total > 1:
72         array[1],array[total] = array[total],array[1]           #堆顶和最后一个结点交换
73         total -= 1
74         if total == 2 and array[total] >= array[total -1]:
75             break
76         heap_adjust(total,1,array)
77     return array
78 
79 print_tree(sort(total,origin))
80 print_tree(origin)
81   

 

 

六.总结

是利用堆性质的一种选择排序,在堆顶选出最大值或者最小值
  时间复杂度.
  堆排序的时间复杂度为O(nlogn).
  因为堆排序对原始记录的排序状态并不敏感,所以它不管是最好、最坏和平均时间复杂度均为O(nlogn).

1>.空间复杂度

  只是使用了一个交换用的空间,空间复杂度就是O(1).

2>.稳定性

  不稳定的排序算法.
相关文章
相关标签/搜索