Loading

堆排序

1.树的概念

 

(1)树是一种数据结构

(2)树是一种可以递归定义的数据结构

(3)树是由n个节点组成的集合

  n > 0, 存在一个节点是根节点,其他节点可以分为m个集合,每一个集合本身又是一棵树。

2.二叉树

概念

定义:每个节点最多有两个子节点,两个子节点被区分为左子节点和右子节点。

满二叉树:每一层的子节点都达到最大数。

完全二叉树:叶子节点只能出现在最下层和次下层,并且最下层的结点集中在最左边的若干个位置上

 

二叉树的顺序存储方式

父节点与两个子节点的关系:

父节点坐标是 i ,则左子节点是2i+1,右子节点是2i+2

例如:

 

3.堆

什么是堆:是一种特殊的完全二叉树。

  大根堆:一颗完全二叉树,满足任何一个子节点都比父节点小

  小根堆:一颗完全二叉树,满足任何一个子节点都比父节点大

示例:

 

 

 

堆的向下调整的前提是:在二叉树中,只有一个位置不满足堆的性质,其它位置都满足堆的性质。
向下调整 是让调整的结点与其孩子节点进行比较。

4.堆排序过程

1.建立堆;

2.得到堆顶元素,即最大值;

3.去掉堆顶, 将堆的最后一个元素放到堆顶,此时再通过一次向下调整,使堆重新有序;

4.得到堆顶元素,即第二大值;

5.重复步骤3,直到堆变空。

代码实现:

 1 def adjust(li, start, last_leaf):
 2     """
 3     用于调整父节点与子节点的位置,保证父节点大于子节点
 4     :param li: 
 5     :param start: 起始父节点
 6     :param last_leaf: 最后一个子节点
 7     :return: 
 8     """
 9     i = start # i最开始指向根节点
10     son_big = 2 * i + 1  # son_big开始是左孩子
11     tmp = li[start]  # 把堆顶存起来
12     while son_big <= last_leaf:  # 只要son_big位置有数
13         if son_big+1 <= last_leaf and li[son_big+1] > li[son_big]:  # 找到较大的子节点
14             son_big = son_big+1
15         if tmp < li[son_big]:  # 如果子节点都大于跟节点,则将子节点变成根节点
16             li[i] = li[son_big]
17             i = son_big  # 向下看一层
18             son_big = 2 * i + 1
19         else:   # 如果子节点都小于跟节点,则将tmp放某一个父节点上
20             li[i] = tmp
21             break
22     else:
23         li[i] = tmp
24 
25 def heapsort(li):
26     n = len(li)
27     # 第一步,建堆,从后向前调整父节点与子节点的位置后就建堆完成
28     for i in range((n-2)//2, -1, -1):
29         adjust(li, i, n-1)
30 
31     for i in range(n-1, -1, -1):
32         li[0], li[i] = li[i], li[0]  # 将最大值li[0]放最后,
33         adjust(li, 0, i-1)  #这时候要调整的二叉树就不算刚刚放到最后的最大值了。
34     return li
35 
36 a = [i for i in range(100)]
37 
38 random.shuffle(a)
39 print(a)
40 sorted_list = heapsort(a)
41 print(sorted_list)

 

posted @ 2021-07-13 16:28  climber_dzw  阅读(41)  评论(0编辑  收藏  举报