数据结构与算法----复习Part 14 (树与二叉树)

本系列是算法通关手册LeeCode的学习笔记

算法通关手册(LeetCode) | 算法通关手册(LeetCode) (itcharge.cn)

目录

一,树(Tree)

树的相关术语

节点间关系

树的其他术语

二,二叉树(Binary Tree)

满二叉树(Full Binary Tree)

完全二叉树(Complete Binary Tree)

二叉搜索树(Binary Search Tree)

平衡二叉搜索树(Balanced Binary Tree)

三,二叉树的存储结构

顺序存储结构

链式存储结构

四,二叉树的遍历

二叉树的前序遍历

二叉树的中序遍历

二叉树的后序遍历

二叉树的层序遍历

五,二叉树的还原

从前序和中序序列构造二叉树:

从中序和后序序列构造二叉树

从前序和后序序列构造二叉树


 一,树(Tree)

        由 n >= 0 个节点与节点之间的关系组成的有限集合。 n = 0 时称空树,n > 0 时称非空树。

        树 具有以下特点:

                有且仅有一个节点没有前驱节点,该节点称为树的【根节点(Root)】;

                除了根节点之外,每个节点有且仅有一个直接前驱节点;

                包括根节点在内,每个节点可以有多个后继节点(一对多的关系);

                当 n > 1 时,除了根节点之外的其他节点与其后继节点组成的也是一棵树,称为根的

        【子树(Sub Tree)】;

树的相关术语

        

树的节点:由一个数据元素和若干个指向其子树的分支组成(节点 加 指向子树的箭头);

节点的度:一个节点所含有的子树个数;

叶子节点:度为 0 的节点,如图中的 C、F、H、I、G、K;

分支节点:度不为 0 的节点,如图中的 A、B、D、E、G;

数的度:树中节点的最大度数,如图中树的度为 3;

节点间关系

子节点:一个节点含有的【子树的根节点】称为该节点的子节点;

父节点:如果一个节点含有子节点,则称该节点为其子节点的父节点;

兄弟节点:具有相同父节点的节点互称为兄弟节点;

树的其他术语

节点的层次:从根节点开始定义,根为第 1 层,根的子节点为第 2 层,以此类推;

树的深度(高度):所有节点中最大的层数;

堂兄弟节点:父节点在同一层的节点互为堂兄弟;

路径:树中两个节点之间所经过的节点序列。如图中 E 到 G 的路径为 E-B-A-D-G;

路径长度:两个节点之间路径上经过的边数。如图中 E 到 G 的路径长度为 4;

节点的祖先:从该节点到根节点所经过的所有节点,被称为该节点的祖先。如图中 H 的祖先为 E、B、A;

节点的子孙:节点的子树中所有节点被称为该节点的子孙。例如图中 D 的子孙为 F、G、K

有序树:节点的各个子树从左至右有序,不能呼唤位置;

无序树:节点的各个子树可互换位置。

二,二叉树(Binary Tree)

        树中各个节点的度不大于 2 个的有序树,称为二叉树。通常树中的分支节点被称为【左子树】或【右子树】。二叉树的分支具有左右次序,不能随意互换位置。

        二叉树可以用递归的方式来定义,即二叉树满足以下两个要求之一:

                空树:二叉树是一个空树;

                非空树:二叉树是有一个根节点和两棵互不相交的子树,分别称为根节点的左子树、右

        子树组成的非空树,并且其本身都是二叉树。

        二叉树是种特殊的树,它最多有两个子树,分别为左子树和右子树,并且两个子树是有序的,不可以互换。也就是说,在二叉树种不存在度大于 2 的节点。

        二叉树在逻辑上可以分为 5 种基本形态

满二叉树(Full Binary Tree)

        如果所有分支节点都存在左子树和右子树,并且所有叶子节点都在同一层上,则称该二叉树为满二叉树。

        满二叉树满足:

                叶子节点只出现在最下面一层;

                非叶子节点的度一定为 2 ;

                在同等深度的二叉树中,满二叉树的节点个数最多,叶子节点个数最多。

        如果我们对满二叉树的节点进行编号。根节点编号为 1,然后按照层次依次向下,每一层从左到右的顺序进行编号,则深度为 k 的满二叉树最后一个节点的编号为 2^k - 1。

完全二叉树(Complete Binary Tree)

        如果叶子节点只能出现在最下面两层,并且最下层的叶子节点都依次排列在该层最左边的位置上,称为完全二叉树。

        完全二叉树满足:

                叶子节点只能出现在最下面两层;

                最下层的叶子节点一定集中在该层最左边的位置上;

                倒数第二层如果有叶子节点,则一定集中在右边位置上;

                如果节点的度为一,则该节点只有做孩子节点;

                

二叉搜索树(Binary Search Tree)

        也叫二叉查找树,是指一棵空树或具有以下性质的二叉树:

                如果任意节点的左子树不为空,则左子树上所有节点的值均小于它根节点的值;

                如果任意节点的右子树不为空,则右子树上所有节点的值均大于它根节点的值;

                任意节点的左子树、右子树均为二叉搜索树

平衡二叉搜索树(Balanced Binary Tree)

        一种结构平衡的二叉搜索树。即叶节点的高度差绝对值不超过 1,并且左右两个子树都是一棵平衡二叉搜索树。

三,二叉树的存储结构

        二叉树的存储结构分为两种:【顺序存储结构】和【链式存储结构】。

顺序存储结构

        其实,堆排序、优先队列中的二叉堆结构,采用的就是二叉树的顺序存储结构。

        二叉树的顺序存储结构使用一维数组在存储二叉树中的节点,节点存储位置则采用完全二叉树的节点层次编号,按照层次从上到下,每一层从左到右的顺序依次存放二叉树的数据元素。在进行顺序存储时,如果对应的二叉树节点不存在,则设置为空节点。

        可以看出节点之间的逻辑关系:

                如果某二叉树节点(非叶子节点)的下标为 i,那么其左孩子节点的下标为 i * i + 1,右

        孩子节点的下标为 2 * i + 2;

                如果某二叉树节点(非根节点)的下标为 i,那么其根节点的下标为 (i - 1) // 2

        对于完全二叉树(尤其是满二叉树)来说,采用顺序存储结构比较合适,它能充分利用存储空间,而对于一般二叉树,如果需要设置很多的【空节点】,则采用顺序存储结构就会浪费很多存储空间,并且由于顺序存储结构固有的一些缺陷,会使得二叉树的插入,删除等操作不方便,效率也比较低,对于二叉树来说,当数的形态和大小经常发生动态变化时,更适合采用链式存储结构。

链式存储结构

        二叉树采用链式存储结构时,每个节点包含一个用于数据域 val ,存储节点信息,还包含两个指针域 left 和 right ,分别指向左右两个孩子节点,当左孩子或右孩子不存在,相应指针域为空。

对应代码:

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

        二叉树的链表存储结构具有灵活、方便的特点。节点的最大数目只受系统最大可存储空间的限制。一般情况下,二叉树的链表存储结构比顺序存储结构更省空间,而对于二叉树实施相关操作也很方便,因此,一般使用链式存储结构来存储二叉树。

四,二叉树的遍历

        从根节点出发,按照某种次序依次访问二叉树中的所有节点,使得每个节点被访问依次且仅被访问一次。

        使用深度优先的方式遍历二叉树,分为二叉树的前、中、后序遍历。

        使用广度优先遍历二叉树,则是二叉树的层序遍历。

二叉树的前序遍历

        如果二叉树为空,则返回;

        如果二叉树不为空,则:

                访问根节点;

                以前序遍历的方式遍历根节点的左子树;

                以前序遍历的方式遍历根节点的右子树;

        可见前序遍历过程是一个递归过程,在遍历任何一棵子树时,仍然是按照先访问根节点,然后遍历子树根节点的左子树,最后遍历根节点的右子树的顺序进行遍历。

注意这里的访问,指的是得到该节点的 val 值,而不是进入该节点。

递归实现

class Solution:
    def preorderTraversal(self, root: TreeNode):
        res = []
        
        def preorder(root):
            if not root:
                return
            res.append(root.val)
            preorder(root.left)
            preorder(root.right)
        
        preorder(root)
        return res

前序遍历的显示栈实现:

        根据栈先入后出的特点,先放入右子树,再放入左子树。

        判断二叉树是否为空,为空则直接返回;

        初始化维护一个栈,将根节点入栈;

        当栈不为空时:

                弹出栈顶元素 node,并访问该元素;

                如果 node 的右子树不为空,则将 node 的右子树入栈;

                如果 node 的左子树不为空,则将 node 的左子树入栈;

    def preorderTraversalStack(self, root):
        if not root:
            return []

        res = []
        stack = [root]

        while stack:
            node = stack.pop()
            res.append(node.val)
            if node.right:
                stack.append(node.right)
            if node.left:
                stack.append(node.left)
        
        return res

二叉树的中序遍历

        如果二叉树为空,则返回;

        如果二叉树不为空,则:

                以中序遍历的方式遍历根节点的左子树;

                访问根节点;

                以中序遍历的方式遍历根节点的右子树;

递归实现:

    def inorderTraversal(self, root: TreeNode):
        res = []
        
        def inorder(root):
            if not root:
                return
            inorder(root.left)
            res.append(root.val)
            inorder(root.right)
        
        inorder(root)
        return res

中序遍历的显式栈实现:

        访问根节点要在左子树遍历完之后,因此我们应该从根节点开始,循环遍历左子树,不断将当前子树的根节点放入栈中,直到当前节点无左子树时,从栈中弹出该节点并处理;

        判断二叉树是否为空,为空则直接返回;

        初始化维护一个空栈;

        当根节点或者栈不为空时,

                如果当前节点不为空,则遍历左子树,并不断把当前子树的根节点入栈;

                如果当前节点为空,则说明当前节点无左子树,则弹出栈顶元素 node,并访问,然后尝

        试访问该节点的右子树;

    def inorderTraversalStack(self, root):
        if not root:
            return []
        
        res = []
        stack = []
        
        while root or stack:
            while root:
                stack.append(root)
                root = root.left
            
            node = stack.pop()
            res.append(node.val)
            root = node.right
        
        return res

二叉树的后序遍历

        如果二叉树为空,则返回;

        如果二叉树不为空,则

                以后序遍历的方式遍历根节点的左子树;

                以后序遍历的方式遍历根节点的右子树;

                访问根节点

递归实现:

    def postorderTraversal(self, root: TreeNode):
        res = []
        
        def postorder(root):
            if not root:
                return 
            postorder(root.left)
            postorder(root.right)
            res.append(root.val)
        
        postorder(root)
        return res

后序遍历的显式栈实现

        后序遍历中,根节点的访问在左右子树访问之后。

        判断二叉树是否为空,为空则直接返回;

        初始化维护一个空栈,使用 prev 保存前一个访问的节点,用于确定当前节点的右子树是否已经访问完毕;

        当根节点或者栈不为空时,从当前节点开始:

                如果当前节点右左子树,则不断遍历左子树,并将当前根节点压入栈中;

                如果当前节点无左子树,则弹出栈顶元素 node;

                如果栈顶元素 node 无右子树或者右子树已经访问完毕,则访问该元素,然后记录前一

        节点,并将当前节点标记为空节点,意为需要栈弹出一个栈顶元素;

                如果栈顶元素 node 有右子树,则将栈顶元素重新压入栈中,继续访问栈顶元素的右子

        树。

    def postorderTraversalStack(self, root):
        res = []
        stack = []
        prev = None
        
        while root or stack:
            while root:
                stack.append(root)
                root = root.left
            
            node = stack.pop()
            
            if not node.right or node.right == prev:
                res.append(node.val)
                prev = node
                root = None     # 需要弹出新的栈顶元素
            else:
                stack.append(node)
                root = node.right
        
        return res

二叉树的层序遍历

        如果二叉树为空,则返回;

        如果二叉树不为空,则:

                先依次访问二叉树第一层的节点;

                然后依次访问二叉树第二层的节点;

                ...

        层序遍历过程是一个广度优先搜索的过程

二叉树的层序遍历通过队列实现:

        判断二叉树是否为空,为空则直接返回;

        令根节点入队;

        当队列不为空时,求出当前队列长度 s;

        依次从队列中取出这 s 个元素,并对这 s 个元素依次进行访问,然后将其左右孩子节点入队,然后继续遍历下一层节点;

        当队列为空时,结束遍历;

实现代码:

    def levelOrder(self, root: TreeNode):
        if not root:
            return []
        
        queue = [root]
        order = []
        
        while queue:
            level = []
            size = len(queue)
            for _ in range(size):
                cur = queue.pop(0)
                level.append(cur.val)
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            if level:
                order.append(level)
        return order

104. 二叉树的最大深度

class Solution:
    def maxDepth(self, root: Optional[TreeNode]) -> int:
        if not root :
            return 0
        return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1
        

103. 二叉树的锯齿形层序遍历

import collections
class Solution:
    def zigzagLevelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root:
            return []
        queue = [root]
        order = []
        odd = True
        while queue:
            level = collections.deque()
            size = len(queue)
            for _ in range(size):
                curr = queue.pop(0)
                if odd:
                    level.append(curr.val)
                else:
                    level.appendleft(curr.val)
                if curr.left:
                    queue.append(curr.left)
                if curr.right:
                    queue.append(curr.right)
            if level:
                order.append(list(level))
            odd = not odd
        return order

111. 二叉树的最小深度

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def minDepth(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
        queue = [root]
        dep = 1
        while queue:
            n = len(queue)
            for i in range(n):
                node = queue.pop(0)
                if node.left == None and node.right == None:
                    return dep
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
            dep += 1
        return dep

        与最大不同,找树的最小深度算是广度遍历的经典应用场景,逐层的排查节点是否是叶子节点,能够找到树的最小深度。

五,二叉树的还原

        指的是通过二叉树的遍历序列,还原出对应的二叉树。

        这个部分比较抽象,所以建议找视频资源进行学习:

        比如:【已知二叉树中序、后序序列,如何还原二叉树?一道题搞定】 https://www.bilibili.com/video/BV1624y1t7Cg/share_source=copy_web&vd_source=87ace2077a752fc4561aff19bae87dac

         简单来说就是根据遍历过程中的规则,不断查找两个遍历结果,实现二叉树的还原,我们的重心在代码实现。而代码实现的重点在于充分明白所知序列能够发挥的作用。

前序序列作用,前序的遍历顺序是【根左右】,因此我们可以从中知道根节点的位置;

中序序列作用,中序遍历的顺序是【左根右】,因此我们知道根节点后,可以知道左子树与右子树的中序序列

后序序列作用,后序遍历的顺序是【左右根】,我们可以知道根节点的位置。

        开始代码实现之前,我们要明确的是,只有前序和后序无法唯一确定二叉树。

从前序和中序序列构造二叉树:

        从前序遍历序列中得到当前根节点位置在 preorder[ 0 ];

        通过在中序遍历中查找上一步根节点对应位置 inorder[ k ],从而将二叉树左右子树分隔开,并得到左右子树节点个数;

        从上一步得到的左右子树个节点个数,将前序序列中的左右子树分开;

        构造当前节点,并递归建立左右树,在左右树的对应位置继续递归遍历并执行上述三步,直到节点为空

    def buildTreeFromPreIn(self, preorder, inorder):
        def createTree(preorder, inorder, n):
            if n == 0:
                return None

            k = 0

            while preorder[0] != inorder[k]:
                k += 1  #   找到中序遍历的分隔位置
            node = TreeNode(inorder[k])
            node.left = createTree(preorder[1: k + 1], inorder[0: k], k)
            node.right = createTree(preorder[k + 1: ], inorder[k + 1: ], n - k - 1)
            return node

        return createTree(preorder, inorder, len(inorder))

从中序和后序序列构造二叉树

        从后序序列中得到当前根节点的位置在 postorder[ n - 1 ];

        通过在中序遍历中查找根节点对应的位置 inorder[k],从而将二叉树的所有子树分隔开,并得到左右子树的节点个数;

        从上一步得到的左右子树节点个数,将后序序列中的左右子树分开;

        构造当前节点,并递归建立左右子树,并在左右子树对应位置继续递归执行上述三步,直到节点为空

    def buildTreeFromInPost(self, inorder, postorder):
        def createTree(inorder, postorder, n):
            if n == 0:
                return None

            k = 0

            while postorder[n - 1] != inorder[k]:
                k += 1
            node = TreeNode(inorder[k])
            node.right = createTree(inorder[k + 1: n], postorder[k: n - 1], n - k - 1)
            node.left = createTree(inorder[0: k], postorder[0: k], k)
            return node
        return createTree(inorder, postorder, len(postorder))

从前序和后序序列构造二叉树

        我们可以默认指定前序序列的第 2 个值为左子树的根节点,由此递归划分左右子树。

        从前序遍历序列中可知当前根节点的位置在 preorder[ 0 ];

        从前序序列的第二个值为左子树的根节点,通过在后序序列中查找上一步根节点对应的位置,postorder[ k ]。从而将二叉树的左右子树分隔开,从得到左右子树节点的个数.

        从上一步得到的左右子树个数,将后序序列结果中的左右子树分开;

        构造当前节点,并递归建立左右子树,在左右子树对应位置继续递归遍历并执行上述三步,直到节点为空。

 def constructFromPrePost(self, preorder: List[int], postorder: List[int]) -> TreeNode:
        def createTree(preorder, postorder, n):
            if n == 0:
                return None
            node = TreeNode(preorder[0])
            if n == 1:
                return node

            k = 0

            while postorder[k] != preorder[1]:
                k += 1
            node.left = createTree(preorder[1: k + 2], postorder[: k + 1], k + 1)
            node.right = createTree(preorder[k + 2: ], postorder[k + 1: -1], n - k - 2)
            return node
        return createTree(preorder, postorder, len(preorder))

算法通关手册(LeetCode) | 算法通关手册(LeetCode)

原文内容在这里,如有侵权,请联系我删除。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/454210.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ISIS单区域实验简述

ISIS 中间系统到中间系统,也是链路状态协议,工作在数据链路层,不依赖IP地址;与OSPF一样采用最短路径SPF算法,收敛速度快。 实验基础配置: r1: sys sysname r1 undo info enable int g0/0/0 ip add 12.1.1.1…

使用vue动态在列表中添加或者删除某一行

** 使用vue动态在列表中添加或者删除某一行 ** 先看一下展示的效果&#xff1a; 好了上代码&#xff1a; 样式界面&#xff1a; <template><div class"container"><h4 style"margin-left: 20px;">线路停靠站站点</h4><el-b…

JS ATM练习案例(复习循环知识)

需求&#xff1a;用户可以选择存钱、取钱、查看余额和退出功能。 分析&#xff1a;1循环时反复出现提示框&#xff0c;所以提示框写到循环里面。 2.退出的条件是4&#xff0c;所以是4就会结束循环 3.提前准备一个金额预存储 4取钱为减法操作&#xff0c;存钱为加法操作&#xf…

访问学者申请记|美国首所翻译博士点

N老师出国访学的目的一方面是开拓眼界&#xff0c;另一方面也是为完成翻译方向的博士论文创造更好的条件。最终我们获得美国纽约州立大学宾汉姆顿分校的邀请函&#xff0c;该校的“翻译研究和教学项目”&#xff08;TRIP&#xff09;是美国高校设立的第一个翻译博士学位项目&am…

electron + vtkjs加载模型异常,界面显示类似于图片加载失败的图标

electron vtkjs加载模型显示异常&#xff0c;类似于图片加载失败的效果&#xff0c;如上图。 electron开发版本&#xff1a;13。 解决方法&#xff1a;升级electron版本号。 注意&#xff1a;win7最高兼容electron 22版本。

哪个骨传导蓝牙耳机的好?独家揭秘六大选购技巧

在科技飞速前进的今天&#xff0c;骨传导蓝牙耳机以独特的听觉技术逐渐进入大众视野&#xff0c;赢得了众多消费者的青睐。作为一名资深的数码爱好者&#xff0c;我最近频繁地收到朋友们的咨询&#xff0c;他们希望了解哪个骨传导蓝牙耳机的好&#xff1f;对于初入数码圈的朋友…

AI知识库也太方便了吧,中小型企业都要知道它!

生活在这个信息爆炸的时代&#xff0c;信息的获取变得前所未有的方便&#xff0c;但随之而来的却是信息筛选和管理的难题。对于中小型企业来说&#xff0c;如何有效运用自身积累的各类信息&#xff0c;直接影响着企业的运营效率和市场竞争力。而这&#xff0c;正是AI知识库可以…

linux驱动——中断

1.Cortex-A系列的中断的简介 中断的基本概念&#xff1a;(interrupt) 中断本质上是系统内部的异常机制,当中断产生之后&#xff0c;他会停下当前正在执行的任务&#xff0c;转而去做其他的事情,在停下当前正在执行的任务之前,要先入栈&#xff08;保护现场,其他的事情做完之后…

智慧城市大模型来啦!港大百度推出UrbanGPT

论文作者解读链接&#xff1a;https://blog.csdn.net/qq_42715656/article/details/136681839 项目链接&#xff1a;https://urban-gpt.github.io/ 代码链接&#xff1a;https://github.com/HKUDS/UrbanGPT 论文链接&#xff1a;https://arxiv.org/abs/2403.00813 研究实验室链…

CMake 编译 raylib 程序

CMakeLists.txt 内容如下&#xff1a; cmake_minimum_required(VERSION 3.0) project(t001) # 搜索指定目录下源文件 file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) # 包含头文件路径 include_directories(F:/vclib/raylib-5.0_win64_mingw-w64/include) # 包含静态…

mysql基于mycat实现读写分离

试验环境 基于mysql主从复制已经实现 mycat主机192.168.199.149&#xff0c;安装好java和jdk 数据库主机192.168.199.150 数据库从机192.168.199.151 149配置 下载mycat并解压 vim /root/mycat/conf/server.xml vim /root/mycat/conf/schema.xml 150是主数据库&#xff0…

Cesium--基于材质旋转图片

材质部分的代码如下 // 自定义材质const customMaterial new Cesium.Material({translucent: true,fabric: {uniforms: {image:circle_img,speed:30.0,},source: czm_material czm_getMaterial(czm_materialInput materialInput){czm_material material czm_getDefaultMateri…

“光谱视界革新:ChatGPT在成像光谱遥感中的智能革命“

遥感技术主要通过卫星和飞机从远处观察和测量我们的环境&#xff0c;是理解和监测地球物理、化学和生物系统的基石。ChatGPT是由OpenAI开发的最先进的语言模型&#xff0c;在理解和生成人类语言方面表现出了非凡的能力。本文重点介绍ChatGPT在遥感中的应用&#xff0c;人工智能…

JVM 类的加载篇

我们都知道一个类从加载到卸载一共分为七个过程 加载 - 链接(验证 - 准备 - 解析) - 初始化 - 使用 - 卸载 下文我们将详细解析这些过程 谁需要加载? 在Java中数据类型分为基本数据类型和引用数据类型,基本数据类型由虚拟机预定义,引用数据类型则需要类的加载 1.加载/装载(loa…

Flex布局实现一部分元素左对齐,一部分右对齐

单个Flex容器内有三个靠右对齐的按钮&#xff0c;如图&#xff1a; display: flex; justify-content: flex-end; 现在需让红色按钮靠左&#xff0c;而另外两个蓝色按钮保持靠右&#xff1a; 方法一&#xff1a; 为红色按钮单独加上&#xff1a;flex: 1; 原理是&#xff1a;利用…

【Docker】docker-compose安装

中文网上复制粘贴的很多&#xff0c;尤以docker-compose为甚。搜索引擎上能搜到的&#xff0c;github的那个网址&#xff0c;curl显示要十几个小时&#xff08;蛮奇怪&#xff0c;win主机直接访问下载就很快&#xff0c;虚拟机Linux去curl就很慢&#xff09;。daocloud的那个&a…

php对接谷歌admob广告收益reporting api分享

今天收到需求,需要对接reporting api接口&#xff0c;拉取广告收益回来。网上找到文档开始对接&#xff0c;对接完成了&#xff0c;今天分享给大家一些心得 文档地址:https://developers.google.com/admob/api/v1/reporting?hlzh-cn#php-client-library 因为接口使用的google…

闪回技术

目录 闪回技术 恢复mybonus表 彻底删除mybonus表 清空回收站 Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 闪回技术 Flash Back 给予用户最为直接的支持之一就是给了用户后悔的机会 但是现在如果用户想去操作这个…

全网最完整的iperf测试工具使用说明

文章目录 前言iPerf 2.0、iPerf 3.0 和 iPerf 3.1 之间的变化iPerf 3 用户文档iPerf 2.0.6、iPerf 2.0.7 和 iPerf 2.0.8 之间的更改iPerf 2 用户文档调整 TCP 连接调整 UDP 连接组 播IPv6 模式使用代表性流测量带宽将服务器作为守护程序运行 前言 iPerf - TCP、UDP 和 SCTP 的…

VUE实现Provide的计算属性

通过此篇可以学到&#xff1a; 如何使用Providerinject进行“跨代”传值如何实现一个计算属性的Provider如何解决告警“injection "xxxxx" not found. ” 一、描述 目前需要创建一个计算属性传入Provide&#xff0c;并且能够被其他组件Inject 二、实现 父组件 .…