0
点赞
收藏
分享

微信扫一扫

算法篇02

醉东枫 2022-01-13 阅读 49

1. 树 是一种数据结构,比如目录结构

2. 数 是一种可以递归定义的数据结构

3. 树 是由n个节点组成的集合:

  • 如果n=0,那这是一棵空树
  • 如果n>0,那存在1个节点作为树的根节点,其他节点可以分为m个集合,每个集合本身又是一棵树。

根节点:A就是根节点

叶子节点: 不能分叉的节点(叶子)

树的深度(高度):4

节点E的度:2

树的度: 树中节点最多的度,6

孩子节点/父节点: E 为 I 的父节点,I 为 E 的节点

子树: 树的某个分支

二叉树

        度不超过 2 的树,每个节点最多有两个孩子节点。两个孩子节点被区分为左孩子结点 和 右孩子节点。

堆是一个特殊的二叉树 

二叉树的存储方式(表示方式):怎么实现一个二叉树

  • 链式存储方式(数据结构部分讲解)
  • 顺序存储方式(堆排序中)

一. 堆排序:

1. 堆: 一种特殊的完全二叉树结构(全满但最好一排后边可以少)。

  • 大堆根:一棵完全二叉树,满足任一节点都比其他孩子节点大。
  • 小堆根:一棵完全二叉树,满足任一节点都比其孩子节点小。

可以将其形象的看作 市长、县长、村长、村民 。以下以大根堆为例。

父节点找子节点和子节点找父节点:

         知道孩子节点下标为n,则其父结点下标为:(n-1)//2。

2. 堆的向下调整----构建堆的基础:

        假设:根节点的左右子树都是堆,但根节点不满足根的性质,那么可以通过一次向下的调整将其变成一个堆...... 向下调整顺序如下:

---->--->---->

 

 当根节点的左右子树都是堆时,但自身不满足堆的性质. 可以通过一次向下调整来将其变换成一个堆

3. 堆构建好之后如何排序: 挨个出数

--拿出堆顶9----向下调整--

--再拿出堆顶----向下调整----再拿出堆顶,将2放到堆顶

改进:

    堆 相当于一个列表, 拿出来的堆顶元素放在另一个列表里很废内存, 秉持着能省则省的原则, 我们不建议再创建一个列表去放堆顶元素。  我们可以将 堆顶元素和最后的元素互换位置,并且将堆最后的位置向前移动一位,如图:

------>

 说明:3原本在最后一个元素,让3和9互换,然后将堆的位置下标变到4的位置下标(下标减1)。

 4.如何构造堆

        要建造堆,  首先要让下级先有序,  因此需要从最下面的根节点开始, 即最后一个 非叶子节点开始.   "农村包围城市战略"

        先对最后一个非叶子节点做 向下调整, 让他变成堆 ; 然后依次将前面的每个非叶子节点 通过向下调整 变成堆.

 5.堆排序过程

 6. 代码实现过程

向下调整函数:复杂度:O(log n)

# 向下调整函数
def sift(li,low,high):  #low表示二叉树的顶;high的作用是:防止j越界
    '''
    堆排序中的向下调整函数
    :param li:列表
    :param low: 堆的根节点位置
    :param high:堆的最后一个元素的位置,唯一的作用是防止 j 越界
    :return:
    '''
    i=low
    j=2*i+1 # j现在指的是左孩子结点
    tmp=li[low]
    while j <= high:   # 表示 j 不越界
        if j+1 <= high and li[j+1] > li[j]:  # 右孩子结点存在且更大
            j=j+1   # j指向右孩子结点
        if tmp < li[j]:
            li[i]=li[j]
            i=j   # i 指向下一层
            j=2*i+1
        else:  # 表示tmp>li[j]
            li[i]=tmp
            break
    else:   # 如果i到达叶子节点,最后一层,j已经出界
        li[i]=tmp

构建堆和排序(挨个出数):复杂度:O(nlog n)

def heap_sort(li):
    # 构造堆:农村包围城市
    n=len(li)
    for i in range((n-2)//2,-1,-1): # i表示建堆的时候调整部分的根节点下标        #将这个小分支变成堆:进行向下调整
        sift(li,i,n-1)  # j唯一的作用就是防止j越界,high为最后一个元素时,也能满足该条件
    # 堆构造完成
    print(li)
    # 接下来就是排序:挨个出数
    for i in range(n-1,-1,-1):   # i指向堆的最后一个元素
        li[0],li[i]=li[i],li[0]   # 将最后一个元素和堆顶元素互换
        sift(li,0,i-1)    # 将没排序的数据 做向下调整,i-1是新的high

最终堆排序的时间复杂度:O(nlog n)

 

 

 

 

 

 

 

 

 

 

 

 

举报

相关推荐

0 条评论