树和堆知识点总结

本文总结了树和堆的基本概念与重要性质。树包括二叉树、完全二叉树和平衡二叉树,常见应用如快速数据检索、人工智能、区块链的默克尔树等。堆是一种特殊的树形数据结构,主要分为最小堆和最大堆,常用于优先任务调度和数据排序。文章还介绍了建堆的过程及其时间复杂度,并讨论了堆在多路归并排序和求topK问题中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、 树

1. 树的定义

树(英语:Tree)是一种无向图(undirected graph),其中任意两个顶点间存在唯一一条路径。或者说,只要没有回路的连通图就是树。

二叉树(英语:Binary tree)是每个节点最多只有两个分支(不存在分支度大于2的节点)的树结构。通常分支被称作“左子树”和“右子树”。二叉树的分支具有左右次序,不能颠倒。

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

平衡二叉树:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

2. 树的应用:

快速数据检索:

  • STL的红黑树
  • 数据库的B+

文档结构组织:DOM

人工智能:决策树

游戏:通过构造空间树实现快速碰撞检测( https://www.zhihu.com/question/25111128

区块链的默克尔树

3. 常用算法

递归:树的深度优先遍历https://blog.youkuaiyun.com/weixin_41876155/article/details/80905220

二叉查找树:左节点值 < 根节点值 < 右节点值

队列:树的广度优先遍历(分层遍历)(https://blog.youkuaiyun.com/weixin_41876155/article/details/80905220

 

二、堆

1. 堆的定义 

堆的实现通过构造二叉堆(binary heap),实为二叉树的一种;由于其应用的普遍性,当不加限定时,均指该数据结构的这种实现。这种数据结构具有以下性质:

  • 任意节点小于(或大于)它的所有后裔,最小元(或最大元)在堆的根上(堆序性)。---> 最小堆/最大堆
  • 堆总是一棵完全树。即除了最底层,其他层的节点都被元素填满,且最底层尽可能地从左到右填入。
  • 根节点i,左节点2 * i + 1,右节点2 * i + 2。

2. 建堆的过程:

代码实现: (Lintcode 130: Heapify)

Description

Given an integer array, heapify it into a min-heap array.

For a heap array A, A[0] is the root of heap, and for each A[i], A[i * 2 + 1] is the left child of A[i] and A[i * 2 + 2] is the right child of A[i].

Example

Given [3,2,1,4,5], return [1,2,3,4,5] or any legal heap array.

Challenge

O(n) time complexity.

解答(超时)--- 神奇的是,把函数拉出来就不超时了,待我后面慢慢研究一下……

思路:找到叶子节点和它的根节点比较

public class Solution {
    /*
     * @param A: Given an integer array
     * @return: nothing
     */
    public void heapify(int[] A) {
        // write your code here
        for(int i = (A.length - 1)/2; i >= 0; --i){
            while(i < A.length){
                int left = 2 * i + 1;
                int right = 2 * i + 2;
                int min_pos = i;
                if(left < A.length && A[left] < A[min_pos]){
                    min_pos = left;
                }
                if(right < A.length && A[right] < A[min_pos]){
                    min_pos = right;
                }
                if(min_pos != i){
                    int temp = A[i];
                    A[i] = A[min_pos];
                    A[min_pos] = temp;
                    i = min_pos;
                }
                else{
                    break;
                }
            }
        }
    }
}

建堆的复杂度分析:

  • N个节点的堆高度最大为h = logN,最下面一层非叶子节点最多调整1次,倒数第2层最多2次,依此类推,根节点最多需要h次。
  • 最下面一层子节点共有2^(h-1)个,倒数第2层有2^(h-2)个,依此类推,根节点有2^(h-h)1个。
  • 所以总的时间复杂度为1^(h-1) + 2*2^(h-2) + (h-1)*2 + h,得到结果为N*2 – 2 – log(N),所以时间复杂度O(n)

3. Merge K Sorted List

Description

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

Example:

Input:
[
  1->4->5,
  1->3->4,
  2->6
]
Output: 1->1->2->3->4->4->5->6

Solution:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists==null || lists.length == 0)
            return null;
 
        PriorityQueue<ListNode> queue = new PriorityQueue<ListNode>(new Comparator<ListNode>(){  //用优先队列实现堆
            public int compare(ListNode l1, ListNode l2){
                return l1.val - l2.val;
            }
        });
 
        ListNode head = new ListNode(0);
        ListNode p = head;
 
        for(ListNode list: lists){
            if(list != null)
                queue.offer(list);  //维护一个最小堆,入堆list个元素,如示例,1,1,2
        }    
 
        while(!queue.isEmpty()){
            ListNode n = queue.poll();
            p.next = n;
            p = p.next;
 
            if(n.next != null)   //入堆4
                queue.offer(n.next);
        }     
        return head.next;
    }
}

 

3. 堆的应用

优先任务调度

  • 操作系统如何根据线程优先级进行快速调度?

海量数据多路归并排序

  • 面试最爱问题,海量数据排序选择topK

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值