数据结构之——二叉树

news2024/11/25 5:28:21

一、二叉树的基本概念

        二叉树是数据结构中的重要概念,每个节点最多有两个子树,分别为左子树和右子树。这种结构具有明确的层次性和特定的性质。

二叉树有五种基本形态:

  1. 空二叉树:没有任何节点。
  2. 只有一个根结点的二叉树:仅有一个节点作为整个树的根。
  3. 只有左子树:根节点仅存在左子树,右子树为空。
  4. 只有右子树:根节点仅存在右子树,左子树为空。
  5. 完全二叉树:除最后一层外,每一层的节点数都是最大的,最后一层的节点尽可能靠左排列。

        完全二叉树具有一些特点,例如叶子结点只可能出现在层序最大的两层上,并且某个结点的左分支下子孙的最大层序与右分支下子孙的最大层序相等或大 1。此外,满二叉树也是一种特殊的二叉树,除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层。平衡二叉树则是左右两个子树的高度差的绝对值不超过 1,并且左右两个子树都是一棵平衡二叉树。

        二叉树作为一种数据结构,在实际问题中具有广泛的应用。许多实际问题抽象出来的数据结构往往是二叉树形式,因为二叉树的存储结构及其算法都较为简单。例如,在计算机科学中的搜索算法、排序算法等领域,二叉树都发挥着重要的作用。

        尽管二叉树与树有许多相似之处,但二叉树不是树的特殊情形。树中结点的最大度数没有限制,而二叉树结点的最大度数为 2;树的结点无左、右之分,而二叉树的结点有左、右之分。

二、二叉树的特殊类型

(一)满二叉树

        满二叉树是一种特殊形态的二叉树。定义为除最后一层无任何子节点外,每一层上的所有结点都有两个子结点,叶子结点都在最下层,没有度为 1 的结点。其特点包括:

  1. 每层的结点数都达到最大,所有叶子结点必须在同一层上。
  2. 如果一颗树深度为 h,最大层数为 k,它的叶子数是 2^(h - 1),第 k 层的结点数是 2^(k - 1),总结点数是 2^k - 1,总节点数一定是奇数。

(二)完全二叉树

        完全二叉树是由满二叉树引出来的。对于深度为 K 的,有 n 个结点的二叉树,当且仅当其每一个结点都与深度为 K 的满二叉树中编号从 1 至 n 的结点一一对应时称之为完全二叉树。其特点如下:

  1. 叶子结点只可能在最大的两层上出现。
  2. 若 i≤⌊n/2⌋,则结点 i 为分支结点,否则为叶子结点。
  3. 对于最大层次中的叶子结点,都依次排列在该层最左边的位置上。
  4. 若有度为 1 的结点,则只可能有一个,且该结点只有左孩子而无右孩子。
  5. 按层序编号后,一旦出现某结点为叶子结点或只有左孩子,则编号大于 i 的结点均为叶子结点。
  6. 若 n 为奇数,则每个分支结点都有左孩子和右孩子;若 n 为偶数,则编号最大的分支结点只有左孩子,没有右孩子,其余分支结点左、右孩子都有。

(三)平衡二叉树

平衡二叉树又被称为 AVL 树,具有以下定义及性质:

  1. 它是一棵空树或它的左右两个子树的高度差的绝对值不超过 1,并且左右两个子树都是一棵平衡二叉树。
  2. 平衡二叉树的常用实现方法有红黑树、AVL、替罪羊树、Treap、伸展树等。
  3. 在平衡二叉搜索树中,高度一般都良好地维持在 O(log(n)),大大降低了操作的时间复杂度。常见的算法有红黑树、AVL、Treap、伸展树等。红黑树可以在 O (log n) 时间内做查找,插入和删除;AVL 树中任何节点的两个儿子子树的高度最大差别为一,n 个结点的 AVL 树最大深度约 1.44log2n;Treap 是一棵二叉排序树,它的左子树和右子树分别是一个 Treap,同时满足堆的性质;伸展树能在 O (log n) 内完成插入、查找和删除操作。

三、二叉树的性质

二叉树具有多种重要性质,这些性质对于理解和操作二叉树至关重要。

(一)节点总数与深度关系

        对于一棵深度为 k 的二叉树,最多具有 2^{_{k}}-1个结点,最少有 k 个结点。这是因为每一层的节点数是上一层的两倍,深度为 k 的满二叉树的节点总数为 2^{_{k}}-1。而对于非满二叉树,其节点总数会小于这个值,但至少有 k 个结点,因为每一层至少有一个结点。

(二)叶子结点与度为 2 的结点关系

        对于任何一棵二叉树,如果其叶结点数为 n_{0},度为 2 的结点数为 n_{2},则有 n_{0}=n_{2}+1。证明如下:如果 n_{0}表示度为 0(即叶子结点)的结点数,用 n_{1}表示度为 1 的结点数,n_{2} 表示度为 2 的结点数,n 表示整个完全二叉树的结点总数,则有 n=n_{0}+n_{1}+n_{2}。根据二叉树和树的性质,可知 n=n_{1}+2*n_{2}+1(所有结点的度数之和加 1 等于结点总数)。根据两个等式可知 n_{0}+n_{1}+n_{2}=n_{1}+2*n_{2}+1,即 n_{2}=n_{0}-1,也即 n_{0}=n_{2}+1

(三)完全二叉树的深度性质

        具有 n个结点的完全二叉树的深度为 ⌊log2n⌋ + 1。证明:根据性质 2,深度为 k的二叉树,最多有 2^k - 1个结点,且完全二叉树的定义是与同深度的满二叉树前边的编号相同,即它们的结点总数n 位于 k层和 k-1层的满二叉树容量之间,即 2^{k - 1} - 1 < n <= 2^k - 1之间,或 2^{k - 1} <= n < 2^k,两边同时取对数得,k - 1 <= log2(n) < k ,又因层数为整数,故log2(n)=k - 1 ,即 k = log2(n)+1。

        这些性质在实际应用中非常有用,例如在计算二叉树的节点数量、判断二叉树的结构特点等方面。了解这些性质可以帮助我们更好地理解和使用二叉树这种数据结构。

四、二叉树的存储结构

(一)顺序存储结构

        顺序存储结构是指用一组地址连续的存储单元依次自上而下、自左至右存储完全二叉树上的结点元素。对于完全二叉树来说,顺序存储是十分合适的,因为完全二叉树的节点可以按照层次编号依次存储在数组中,通过节点的编号可以快速确定其在数组中的位置,进而方便地找到其双亲、左右孩子节点。

        在完全二叉树的顺序存储中,数组的下标与节点的编号有直接对应关系。例如,对于一个深度为 的完全二叉树,其节点总数最多为 。如果节点编号从 开始,那么根节点存储在数组下标为 的位置,节点 的左孩子存储在下标为 的位置,右孩子存储在下标为 的位置,节点 的双亲节点存储在下标为 的位置。

        然而,顺序存储结构也有明显的优缺点。优点包括:索引计算简单,通过节点在数组中的索引,可以快速计算出其父节点、左子节点和右子节点的索引,不需要进行指针操作,提高了访问效率;存储紧凑,相比于链式存储,顺序存储不需要额外的指针空间,节省了存储空间;遍历方便,由于节点在数组中的顺序与遍历顺序一致,可以方便地进行层次遍历、前序遍历、中序遍历和后序遍历等操作。

        缺点主要有:空间浪费,如果二叉树是一棵稀疏树(即节点较少),那么顺序存储会造成大量的空间浪费,因为数组中会有很多位置被空节点占据;插入和删除操作复杂,由于顺序存储需要保持二叉树的完全二叉树结构,插入和删除节点时需要进行大量的数据搬移操作,效率较低;高度限制,顺序存储的数组长度是固定的,因此对于高度较大的二叉树,可能会导致数组长度不够,无法存储完整的二叉树。

(二)链式存储结构

1.二叉链表

        二叉链表是二叉树的一种常见链式存储结构。在二叉链表中,每个节点包含三个域:数据域、左指针域和右指针域。当左孩子或右孩子不存在时,相应指针域值为空。

        二叉链表的特点是:除了指针外,二叉链比较节省存储空间。占用的存储空间与树形没有关系,只与树中节点个数有关。在二叉链中,找一个节点的孩子很容易,但找其双亲不方便。

        二叉链表适用于各种类型的二叉树,尤其是那些非完全二叉树。在实际应用中,二叉链表常用于二叉树的遍历、查找、插入和删除等操作。例如,在二叉树的遍历中,可以通过递归或非递归的方式遍历二叉链表,实现对二叉树中每个节点的访问。

2.三叉链表

        三叉链表是二叉树链式存储结构的另一种形式。三叉链表与二叉链表的主要区别在于,它的节点比二叉链表的节点多一个指针域,该域用于存储指向本节点双亲的指针。

        在三叉链表中,每个结点由四个域组成,其中,data、lchild 以及 rchild 三个域的意义与二叉链表结构相同。这种存储结构既便于查找孩子结点,又便于查找双亲结点。但是,相对于二叉链表存储结构而言,它增加了空间开销。

        三叉链表适用于需要频繁查找双亲节点的场景。例如,在某些算法中,需要快速找到某个节点的双亲节点进行操作,此时三叉链表就可以发挥其优势。不过,由于其增加了空间开销,在空间有限的情况下,需要权衡使用。

五、二叉树的遍历方式

(一)先序遍历

        先序遍历的顺序是根左右,即先访问根节点,再访问左子树,最后访问右子树。

在 C 语言中,先序遍历可以通过递归和非递归两种方式实现。

1.递归实现:

// 前序遍历二叉树的函数,假设 BiTree 是一个二叉树类型
void preOrder(BiTree T) {
    // 如果当前节点不为空
    if (T!= NULL) {
        // 调用 visit 函数访问当前节点,visit 函数应该是一个自定义的用于处理节点的函数
        visit(T);
        // 递归遍历左子树
        preOrder(T->lchild);
        // 递归遍历右子树
        preOrder(T->rchild);
    }
    // 函数返回,结束遍历
    return;
}

2.非递归实现:借助栈实现,先将根节点入栈,当栈不为空时,取出栈顶元素并访问,然后将其右孩子和左孩子依次入栈(如果存在)。

// 非递归实现前序遍历二叉树的函数,假设 BiTree 是一个二叉树类型
void preOrderNonRecursive(BiTree T) {
    // 创建一个栈
    Stack stack;
    // 初始化栈
    initStack(&stack);
    // 将根节点入栈
    push(&stack, T);
    // 当栈不为空时循环
    while (!isEmpty(&stack)) {
        // 弹出栈顶元素
        BiTree node = pop(&stack);
        // 如果弹出的节点不为空
        if (node!= NULL) {
            // 访问该节点
            visit(node);
            // 先将右子树入栈(因为先访问左子树,后访问右子树)
            push(&stack, node->rchild);
            // 再将左子树入栈
            push(&stack, node->lchild);
        }
    }
}

(二)中序遍历

中序遍历的顺序是左根右,即先访问左子树,再访问根节点,最后访问右子树。

C 语言实现方式如下:

1.递归实现:

// 中序遍历二叉树的函数,假设 BiTree 是一个二叉树类型
void midOrder(BiTree T) {
    // 如果当前节点不为空
    if (T!= NULL) {
        // 先递归遍历左子树
        midOrder(T->lchild);
        // 访问当前节点
        visit(T);
        // 再递归遍历右子树
        midOrder(T->rchild);
    }
    // 函数返回,结束遍历
    return;
}

2.非递归实现:借助栈实现,从根节点开始,将其所有左孩子依次入栈,直到左孩子为空。然后弹出栈顶元素并访问,接着将其右孩子作为新的根节点重复上述过程。

// 非递归实现中序遍历二叉树的函数,假设 BiTree 是一个二叉树类型
void midOrderNonRecursive(BiTree T) {
    // 创建一个栈
    Stack stack;
    initStack(&stack);
    // 设置当前节点为传入的根节点
    BiTree node = T;
    // 当当前节点不为空或者栈不为空时循环
    while (node!= NULL ||!isEmpty(&stack)) {
        if (node!= NULL) {
            // 当前节点不为空时,将其入栈,并将当前节点移动到左子节点
            push(&stack, node);
            node = node->lchild;
        } else {
            // 当前节点为空,说明左子树已遍历完,从栈中弹出一个节点
            node = pop(&stack);
            // 访问该节点
            visit(node);
            // 将当前节点移动到右子节点
            node = node->rchild;
        }
    }
}

(三)后序遍历

后序遍历的顺序是左右根,即先访问左子树,再访问右子树,最后访问根节点。

C 语言代码实现:

1.递归实现:

// 后序遍历二叉树的函数,假设 BiTree 是一个二叉树类型
void afterOrder(BiTree T) {
    // 如果当前节点不为空
    if (T!= NULL) {
        // 先递归遍历左子树
        afterOrder(T->lchild);
        // 再递归遍历右子树
        afterOrder(T->rchild);
        // 最后访问当前节点
        visit(T);
    }
    // 函数返回,结束遍历
    return;
}

2.非递归实现:借助栈实现,需要额外使用一个辅助栈来记录遍历顺序。先将根节点入栈,然后依次将其右孩子和左孩子入栈(如果存在)。当栈为空时,遍历结束。最后将辅助栈中的元素依次弹出并访问,得到后序遍历结果。

// 非递归实现后序遍历二叉树的函数,假设 BiTree 是一个二叉树类型
void afterOrderNonRecursive(BiTree T) {
    // 创建两个栈 stack1 和 stack2
    Stack stack1, stack2;
    // 初始化 stack1
    initStack(&stack1);
    // 初始化 stack2
    initStack(&stack2);
    // 将根节点入栈 stack1
    push(&stack1, T);
    // 当 stack1 不为空时循环
    while (!isEmpty(&stack1)) {
        // 从 stack1 弹出一个节点
        BiTree node = pop(&stack1);
        // 将弹出的节点入栈 stack2
        push(&stack2, node);
        // 如果当前节点的左子树不为空,将左子树入栈 stack1
        if (node->lchild!= NULL) {
            push(&stack1, node->lchild);
        }
        // 如果当前节点的右子树不为空,将右子树入栈 stack1
        if (node->rchild!= NULL) {
            push(&stack1, node->rchild);
        }
    }
    // 当 stack2 不为空时循环
    while (!isEmpty(&stack2)) {
        // 从 stack2 弹出一个节点并访问
        visit(pop(&stack2));
    }
}

(四)层次遍历

        层次遍历是从上层至下层,同层自左至右遍历。借助队列实现,先将根节点入队,然后当队列不为空时,取出队首元素并访问,接着将其左孩子和右孩子依次入队(如果存在),直到队列为空。

C 语言代码如下:

// 层次遍历二叉树的函数,假设 BiTree 是一个二叉树类型
void levelOrder(BiTree T) {
    // 创建一个队列
    Queue queue;
    // 初始化队列
    initQueue(&queue);
    // 将根节点入队
    enqueue(&queue, T);
    // 当队列不为空时循环
    while (!isEmptyQueue(&queue)) {
        // 从队列中取出一个节点
        BiTree node = dequeue(&queue);
        // 如果取出的节点不为空
        if (node!= NULL) {
            // 访问该节点
            visit(node);
            // 将该节点的左子节点入队
            enqueue(&queue, node->lchild);
            // 将该节点的右子节点入队
            enqueue(&queue, node->rchild);
        }
    }
}

六、二叉树的应用场景

        二叉树在计算机科学领域有广泛的应用场景,以下是对其在不同领域的具体介绍:

(一)哈夫曼编码

        哈夫曼编码是一种使用二叉树(特别是赫夫曼树)实现的数据压缩方法。它通过构建一个带权路径长度最短的二叉树,即最优二叉树,来提高数据传输的有效性。具体步骤如下:

  1. 首先将待编码的文章当成一个字符串,遍历这个字符串中所有的字符,并且统计每一个字符出现的次数。
  2. 根据字符出现的次数对字符进行排序。
  3. 选取排序后出现次数最少的两个字符加入哈夫曼树,并将两个字符的出现次数取值相加,合并成为一个中间节点。中间节点仅记录两个节点取值的加和,但是不记录任何字符。
  4. 将中间节点加入字符排序序列中,删除已经使用过的节点,对序列重新排序,重复步骤 2 - 4,构建过程中产生的中间节点也算作在内。
  5. 当所有的字符和中间节点全部合成完毕时,序列中只剩余一个节点,就是哈夫曼树的根节点,哈夫曼树创建完毕。

        接着为每一个存储字符的节点分配哈夫曼编码:从根节点开始,向下寻找每一个叶子节点;如果向左孩子方向走一步,则记 0;如果向右孩子方向走一步,则记 1;重复上述步骤,直到遍历完成整个哈夫曼树为止,最终得到根节点通往每一个叶子节点的路径字符串,就是这个叶子节点对应字符的哈夫曼编码。

        例如,一篇文章经过哈夫曼编码后,完全由 0 和 1 构成,且每一篇文章因为内容的不同,即使是相同的字符所对应的哈夫曼编码也是不同的。所以,即使单纯得到一篇文章的密文结构,没有得到对应的哈夫曼编码表,也是无法进行解密的。哈夫曼树和哈夫曼编码在密码学当中具有非常高的学术研究价值。

(二)海量数据并发查询

        在处理大量动态数据时,二叉排序树(二叉查找树)因其既有链表的好处也有数组的好处,能够在处理大批量的动态数据时提供高效的查询性能。这种数据结构在复杂度为 O (K + LgN) 的情况下,对于海量数据的并发查询非常有用。

        例如,在一些需要处理大量实时数据的系统中,如金融交易系统、网络流量监测系统等,二叉排序树可以快速地对数据进行查找和插入操作,满足系统对数据处理的实时性要求。

(三)数据结构实现

        C++ STL 中的 set/multiset、map 以及 Linux 虚拟内存的管理,都是通过红黑树实现的。红黑树能够在查找、插入和删除操作中保持相对平衡,提供高效的查找效率,最大查找 / 删除 / 插入操作的时间复杂度为 O (logk)。

        红黑树是一种自平衡的二叉查找树,它在插入和删除操作后通过旋转和翻色,自动调整结构以保持平衡,从而保证了查找、插入和删除操作的效率。在内存中的有序数据存储中,红黑树可以快速地进行增删操作,且由于内存存储不涉及 I/O 操作,红黑树的性能优势更加明显。此外,红黑树还适用于实现 Key - Value 对的数据结构,通过键值对进行查找,适用于需要快速查找特定键值对应的值的应用场景。

(四)文件系统

        B - Tree 和 B+ - Tree 在文件系统中有着重要的应用,特别是在目录管理上。它们能够高效地处理大量的数据,并提供快速的查找、插入和删除操作,这对于文件系统的性能至关重要。

        B + 树只在叶节点存储数据,而非叶子节点只存储索引信息。这种结构使得 B + 树能够更好地适应磁盘读取方式,因为在磁盘上读取一条记录的成本非常高。B + 树的叶节点形成了一个链表,可以很容易地实现范围查询,非常适合需要高效处理大量数据的系统。此外,B + 树相比 B 树有更好的空间利用率和查询性能,更适合用作大型数据库的索引结构。B + 树的所有数据记录都存储在叶子节点上,且叶子节点同时还维护了一条双向链表,这提高了范围查询的效率。因此,B + 树在需要处理大量范围查询和排序操作的场景中表现出色,如文件系统等。

(五)路由搜索引擎

        路由器使用二叉树结构进行路由表的查找,这种结构能够快速地根据目的地址查找最佳的路由路径,从而提高网络通信的效率。

        例如,在互联网中,路由器需要根据数据包的目的地址快速地选择最佳的路由路径,将数据包转发到正确的目的地。二叉树结构可以有效地组织路由表,使得路由器能够快速地进行查找和决策,提高网络通信的效率和可靠性。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【HTTPS】深入解析 https

我的主页&#xff1a;2的n次方_ 1. 背景介绍 在使用 http 协议的时候是不安全的&#xff0c;可能会出现运营商劫持等安全问题&#xff0c;运营商通过劫持 http 流量&#xff0c;篡改返回的网页内容&#xff0c;例如广告业务&#xff0c;可能会通过 Referer 字段 来统计是…

kubernetes get pods的STATUS字段显示ImagePullBackOff 的解决办法

问题&#xff1a; [rootmaster ingress]# kubectl -n ingress-nginx get pods NAME READY STATUS RESTARTS AGE ingress-nginx-admission-create-mcrc6 0/1 ImagePullBackOff 0 37m ingress-…

掌握RocketMQ——基本概念和系统架构

简述RcoketMQ 概念&#xff1a;RocketMQ是一个开源的分布式消息中间件&#xff0c;由阿里巴巴开发并贡献给Apache软件基金会。它用于处理高吞吐量、低延迟的消息传递&#xff0c;并广泛应用于现代分布式系统中。 1 基本概念 1.1 消息 (Message) 概念&#xff1a;消息是信息传…

自定义协议以及序列化和反序列化

我们知道TCP是全双工的&#xff0c;可以同时进行发收&#xff0c;因为他有一个发送缓冲区和一个接收缓冲区 我们使用write其实是把数据拷贝到发送缓冲区&#xff0c;使用read接收缓冲区的数据&#xff0c;其实是把数据拷贝到文件缓冲区里&#xff0c;发送的过程中&#xff0c;我…

脸书(Facebook)高效开发国外客户的6个技巧

Facebook作为全球使用人数最多的社媒平台&#xff0c;全球三分之一的人都在用。做外贸的话基本上是必须要去掌握的一个平台&#xff0c;因为通过Facebook是可以开发到很多其他渠道平时开发不到的优质客户的。 Facebook跟LinkedIn不同&#xff0c;LinkedIn比较偏向于大B的客户&…

传热学一些“数”和意义

物体单位面积上的导热热阻/单位表面积上的对流换热热阻 无量纲时间 Nu与Bi的表达式相同&#xff0c;但是意义是无量纲的h。它们表达式里的长度取值不同&#xff0c;比如同样一个平板&#xff0c;Bi的L是厚度&#xff0c;Nu是长度&#xff0c;因为Bi面向固体&#xff0c;λ为固…

八种基本服务器类型,看这篇完全够了

号主&#xff1a;老杨丨11年资深网络工程师&#xff0c;更多网工提升干货&#xff0c;请关注公众号&#xff1a;网络工程师俱乐部 上午好&#xff0c;我的网工朋友。 服务器作为网络基础设施的核心组件&#xff0c;其重要性不言而喻。 无论是个人空间还是大型企业的数据中心&…

激波是什么?

你肯定能听懂。激波&#xff0c;激烈的波&#xff0c;代表特征&#xff1a;激波扫过你时&#xff0c;重则五脏震动&#xff0c;支离破碎。轻则耳膜震动&#xff0c;隆隆作响&#xff0c;当然也有相对你而言尺度很小的激波&#xff0c;没啥伤害。 所以激波&#xff0c;和相对于…

【VScode】VScode如何离线安装扩展

VScode如何离线安装扩展 一&#xff0c;简介二&#xff0c;操作步骤2.1 扩展下载2.2 扩展安装 三&#xff0c;总结 一&#xff0c;简介 本文以“C/C Extension Pack”扩展为例&#xff0c;介绍如何在没有网络的环境下给VScode安装扩展&#xff0c;供参考。 二&#xff0c;操作…

gradle.properties的注释乱码的解决方案

问题描述&#xff1a; gradle项目的配置脚本的注解出现乱码&#xff1a;&#xff08;#&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff09; gradle.properties #??? PRODSERVER2193.168.0.22 解决方案&#xff1a;&#xff08;3步&#xff09; 增…

OpenHarmony(鸿蒙南向开发)——标准系统方案之瑞芯微RK3568移植案例(上)

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 持续更新中…… 本文章是基于瑞芯微RK3568芯片的DAYU200开发板&#xff0c;进行标准…

解决AWS Organizatiion邀请多个Linker账号数量限额问题

文章目录 情景再现什么是 AWS Organizations&#xff1f;操作步骤完整支持工单截图参考链接 情景再现 冷知识&#xff1a;默认情况下&#xff0c;一个组织中允许的原定设置最大账户数为10个。新创建的账户和组织的限额可能会低于默认的 10 个账户。 现在需要用一个AWS账号&…

小红书推广的7个数字营销策略分享-华媒舍

数字营销在如今的商业环境中变得越来越重要。在众多数字营销策略中&#xff0c;小红书已经成为了一种受欢迎的推广平台。本文将介绍小红书推广的七个数字营销策略&#xff0c;重点聚焦于第四个策略&#xff0c;该策略能够帮助你超额完成销售目标。 数字营销策略一&#xff1a;明…

JAVA:Fastjson 序列化和反序列化的技术指南

请关注微信公众号&#xff1a;拾荒的小海螺 博客地址&#xff1a;http://lsk-ww.cn/ 1、简述 在 Java 领域&#xff0c;JSON 作为轻量级数据交换格式广泛使用。对于高性能、高并发场景&#xff0c;选择一个高效的 JSON 序列化和反序列化库非常重要。Fastjson 是由阿里巴巴开发…

成长之路:我的技术布道之路回顾

成长之路&#xff1a;从零开始的技术布道之路回顾-哔哩哔哩 大家好&#xff0c;我是许泽宇&#xff0c;今天想跟大家分享一下我在过去一年的成长和收获。这一年对我来说是满满的一年&#xff0c;我在技术布道的道路上取得了一些小小的成绩&#xff0c;也收获了很多宝贵的经验。…

精选四款免费电脑录屏软件,轻松搞定屏幕录制

大家好&#xff0c;我是一个喜欢找各种办公软件的人&#xff0c;今天我要来聊聊咱们日常工作中一个超实用的小工具——电脑录屏软件。作为一个天天和电脑打交道的办公室文员&#xff0c;我算是尝遍了市面上几款热门的录屏神器&#xff0c;它们各有各的绝活&#xff0c;让我在工…

unix系统中的system函数

一、前言 本文将介绍unix系统中的system函数&#xff0c;包括system函数的作用以及使用方法。 二、system函数 简单来说&#xff0c;system函数用于创建一个子进程并让子进程运行新的程序。其原理是依次执行如下操作&#xff1a; fork() --> execl() --> waitpid() 函…

在QT中将Widget提升为自定义的Widget后,无法设置Widget的背景颜色问题解决方法

一、问题 在Qt中将QWidget组件提升为自定义的QWidget后&#xff0c;Widget设置的样式失效&#xff0c;例如设置背景颜色为白色失效。 二、解决方法 将已经提升的QWidget实例对象&#xff0c;脱离父窗体的样式&#xff0c;然后再重新设置自己的样式。

AP8505固定5V输出5V0.2A,SOP7/DIP7非隔离开关电源IC

AP8505基于高压同步整流架构&#xff0c;集成PFM控制器以及500V高可靠性MOSFET&#xff0c;用于外部元器件极精简的小功率非隔离开关电源。AP8505无线门铃芯片内置500V高压启动&#xff0c;实现系统快速启动、超低待机功能。5V非隔离无线门铃芯片AP8505提供了完整的智能化保护功…

基于Python的爬虫设计与数据分析—计算机毕业设计源码37836

目 录 摘要 1 绪论 1.1课题背景 1.2研究目的及意义 1.3爬虫技术 1.4django框架介绍 2 1.5论文结构与章节安排 3 2 基于Python的爬虫设计与数据分析分析 4 2.1 可行性分析 4 2.2 系统流程分析 4 2.2.1数据流程 5 2.2.2业务流程 5 2.3 系统功能分析 5 2.3.1 功能性分析 6 2…