关闭

算法三:树和堆排序

166人阅读 评论(0) 收藏 举报
分类:
1、(不包含回路的,即n个结点恰好有n-1条边)
任意两个结点有且仅有唯一的一条路径连通。

根/祖先/根节点(没有父亲)

节点/结点

夫节点/父亲

子节点/儿子

叶结点(没有儿子)

深度:根到这个结点的层数。

2、二叉树:每个结点最多有两个儿子(左儿子,右儿子)

满二叉树:每个结点都有两个儿子/所有的叶结点都有相同的深度。
深度为h且有2^h-1个结点的二叉树。

完全二叉树:满二叉树最右边位置上拿掉一个或者几个叶结点
深度为h,除h层外,其他各层(1 - h-1)的结点数都达到最大个数。

完全二叉树存储:一维数组,从左到右一层一层放。
有N个结点,那么这个完全二叉树的高度为log2 N。
最典型的应用就是堆。

3、最小堆:所有父结点都比子结点要小

随便n元素的数,按照完全二叉树方式放入一个数组,生成最小堆:
1、从最后一个非叶结点(结点数组编号为n/2)开始,对该结点和下面的左右叶结点进行比较,使最小的数放在非叶结点上。
2、扫描完这层后,开始扫描上一层,该结点如果要移位,就需要对下面及下面的叶结点进行比较,使其符合最小堆要求,不移位不比较。
3、重复,直到扫描到根节点(结点编号为1)为止。
时间复杂度O(N)

5、堆排序
时间复杂度和快速排序一样O(NlogN)。
以从小到大排序为例。
1、生成最大堆   
2、把数组中最后h[n]的数和h[1]的数进行交换,n--
3、补上来的数h[1]和子节点一层一层对比,把小的数往上移,直到不能移动时,再跳到2反复。
create();
while(n>1)
{
    swap(1,n);
    n--;
    siftdown(1);
}

siftdown(int i)
{
    while(!到底或已经没有小的) 
    {
        n[i]和左儿子比,和右儿子比,如果有小的交换并记录在t中。
更新到交换后的结点i=t。
    }
}

6、堆的应用
优先队列:普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。
二叉堆就是优先队列(父节点大于子节点)

求一个数列中第K大/小的数。
取出K个数建一个大小为K的最小/大堆,再从K+1个数开始,依次拿去和堆顶比较,如果要小/大,就舍弃,如果大/小就一层一层往下比和移。
时间复杂度O(NlogN)

并查集/不相交集数据结构的算法:
通过一个数组来实现,其本质是维护一个森林,刚开始的时候,森林的每个点都是孤立的,可理解成一个结点的树,
之后通过一些条件,逐步将这些树合并成一棵大树。判断两个节点是否已经在同一棵树(数其实是个集合)中的时候,
也要注意必须求其根源,中间父亲节点是不能说明问题的,必须找到其祖宗判断两个结点的祖宗是否是同一个根结点才行。



0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:24094次
    • 积分:556
    • 等级:
    • 排名:千里之外
    • 原创:28篇
    • 转载:26篇
    • 译文:0篇
    • 评论:2条
    文章分类
    最新评论