赞
踩
链表 ——> 二叉树 ——> 二叉查找树 ——> 平衡二叉树
二叉树时间复杂度:O(logn) ,即2^x(树的深度)=N
如:21亿点需要查找几次:2^32 = 21亿,查找32次。
1、满二叉树
2、完全二叉树:设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边。(除最后一层外,为一颗满二叉树)
完全二叉树的基础上可以引申出 堆(heap) 的数据结构:
堆的定义:堆就是一个数组,用来存放完全二叉树。
大堆:所有 根节点值 均大于 左右孩子节点值
小堆:所有 根节点值 均小于 左右孩子节点值
如何理解数组存放完全二叉树?堆排序:
arr = [3, 1, 4, 2, 5] arr[0] 为堆顶。
直接手撕代码:
平均时间复杂度:O(nlogn) ,堆常用于topk算法,大顶堆求小值(前k个最小的值),小顶堆求大值(前k个最大的值)
- class Solution:
- def heapify(self, arr, i, n): #以构建大堆为例,该函数处理单个节点
- left = 2*i+1 #左孩子节点
- right = 2*i+2 #右孩子节点
- maxi = i
- #left/right<n限制要构造堆的数组前n项,比较根节点和左右孩子节点,将最大值交换至根节点位置
- if left<n and arr[maxi]<arr[left]:
- maxi = left
- if right<n and arr[maxi]<arr[right]:
- maxi = right
- if maxi != i: #说明最大值不是根节点,需要进行交换
- arr[maxi], arr[i] = arr[i], arr[maxi]
- self.heapify(arr, maxi, n) #注意!交换的目标节点同样需要继续重建堆
- return arr
-
- def HeapSort(self, arr): #[3, 1, 4, 2, 5, 3] 为例
- if not arr:
- return
- n = len(arr)
- for i in range(n-1, -1, -1): #构造堆结构需要自底向上构建。
- self.heapify(arr, i, n)
- #此时建好堆,数组为 [5, 3, 4, 2, 1, 3]
- 做排序时依次将堆顶值交换到数组末尾,从大到小排列
- for i in range(n-1, -1, -1):
- arr[i], arr[0] = arr[0], arr[i]
- self.heapify(arr, 0, i) #注意每次交换堆顶值,需要重建堆,且重建的为前i项,第i项后已经排好序。
- return arr
-
3、二叉排序树(二叉查找树)的定义:
某结点左子树的所有结点的值都小于该节点的值且该结点右子树的值都大于该节点的值
!!!二叉排序树的使用性质:中序遍历后是一个有序数组。
区别:
(1) 二叉排序树是为了实现动态查找而设计的数据结构,它是面向查找操作的,在二叉排序树中查找一个结点的平均时间复杂度是O(log n);
(2) 堆是为了实现排序而设计的一种数据结构,它不是面向查找操作的,因而在堆中查找一个结点需要进行遍历,其平均时间复杂度是O(n)。
4、平衡二叉树是特殊的二叉排序树
改进版:平衡二叉树 AVL 为了尽量降低树的高度,平均查找长度越小,查找速度越快
平衡因子 = 左子树的高度 - 右子树的高度
平衡二叉树的条件:
1、是二叉排序树
2、满足每个结点的平衡因子绝对值不大于1
平衡二叉树的平衡调整:
左旋如下:
S结点上提,E结点下降,伴随指针向左滑动
右旋示例:
5、红黑树:寻找相对平衡的二叉树
1.每个结点要么是红的要么是黑的。
2.根结点是黑的。
3.每个叶结点(叶结点即指树尾端NIL指针或NULL结点)都是黑的。
4.如果一个结点是红的,那么它的两个儿子都是黑的。
5.对于任意结点而言,其到叶结点树尾端NIL指针的每条路径都包含相同数目的黑结点。
红黑树变换:
1、改变颜色:红变黑、黑变黑
2、左旋、右旋
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。