红黑树及其应用介绍(万字长文)

红黑树

定义与性质

红黑树是一种特殊的二叉查找树,它遵循了特定的规则使得其具有了平衡性。红黑树的定义包括以下几个方面:

  1. 每个节点要么是红色,要么是黑色。
  2. 根节点是黑色的。
  3. 每个叶子节点(NIL节点,空节点)是黑色的。
  4. 对于任意一个节点,其子节点中黑色节点的数量不少于 1。
  5. 对于任意一个节点,从该节点到其叶子节点的所有路径上,黑色节点数量相同。

红黑树的性质:

  1. 红黑树是一棵二叉查找树。
  2. 红黑树的平衡是指,对于任意一个节点,其左右子树的高度差不超过 1。
  3. 红黑树的查找、插入、删除等操作的时间复杂度都可以做到 O(logn)。
  4. 红黑树的颜色变换规则使得它在插入、删除等操作后能够快速地恢复平衡。

红黑树在很多领域中都有广泛的应用,例如操作系统、数据库、图形学等。它的平衡性和高效的操作性能使得它成为一种非常优秀的数据结构,其结构图如下。
在这里插入图片描述

查找遍历

红黑树的查找遍历有以下几种常用的方法:

  1. 递归遍历:使用递归的方式遍历红黑树,对于每个节点,递归遍历其左子树和右子树。
  2. 前序遍历:先遍历根节点,然后按照前序遍历的方式遍历左子树,最后按照前序遍历的方式遍历右子树。
  3. 中序遍历:先遍历左子树,然后遍历根节点,最后按照中序遍历的方式遍历右子树。
  4. 后序遍历:先遍历左子树,然后按照后序遍历的方式遍历右子树,最后遍历根节点。
  5. 层序遍历:按照层级的方式遍历红黑树,对于每一层,按照从左到右的顺序遍历该层的所有节点。

递归遍历

红黑树的递归遍历是指使用递归的方式遍历红黑树的所有节点。具体的遍历方式可以是前序遍历、中序遍历、后序遍历等。以下是一个使用递归实现红黑树前序遍历的 Java 代码示例:

public void preorderTraversal(TreeNode root) {
    if (root == null) {
        return;
    }
    System.out.print(root.val + " "); // 先输出根节点的值
    preorderTraversal(root.left); // 递归遍历左子树
    preorderTraversal(root.right); // 递归遍历右子树
}

其中,TreeNode表示红黑树的节点,其代码如下:

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

在递归遍历的过程中,需要注意以下几点:

  1. 对于每个节点,先递归遍历其左子树,再递归遍历其右子树。
  2. 对于叶子节点(leftright都为null),不需要进行递归遍历。
  3. 递归终止条件为节点为null

前中后序遍历

红黑树的前序遍历、中序遍历和后序遍历是指按照不同的顺序遍历红黑树的节点。

前序遍历:先访问根节点,然后按照前序遍历的方式遍历左子树,最后按照前序遍历的方式遍历右子树。

中序遍历:先按照中序遍历的方式遍历左子树,然后访问根节点,最后按照中序遍历的方式遍历右子树。

后序遍历:先按照后序遍历的方式遍历左子树,然后按照后序遍历的方式遍历右子树,最后访问根节点。

以下是一个使用递归实现红黑树前序遍历、中序遍历和后序遍历的 Java 代码示例:

import java.util.ArrayList;
import java.util.List;

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

/**
 * 前序遍历
 */
public List<Integer> preorderTraversal(TreeNode root) {
    List<Integer> result = new ArrayList<>();
    preorderTraversal(root, result);
    return result;
}

private void preorderTraversal(TreeNode root, List<Integer> result) {
    if (root == null) {
        return;
    }
    result.add(root.val); // 先访问根节点
    preorderTraversal(root.left, result); // 递归遍历左子树
    preorderTraversal(root.right, result); // 递归遍历右子树
}

/**
 * 中序遍历
 */

public List<Integer> inorderTraversal(TreeNode root) {
    List<Integer> result = new ArrayList<>();
    inorderTraversal(root, result);
    return result;
}

private void inorderTraversal(TreeNode root, List<Integer> result) {
    if (root == null) {
        return;
    }
    inorderTraversal(root.left, result);
    result.add(root.val);
    inorderTraversal(root.right, result);
}

/**
 * 后序遍历
 */
public List<Integer> postorderTraversal(TreeNode root) {
    List<Integer> result = new ArrayList<>();
    postorderTraversal(root, result);
    return result;
}

private void postorderTraversal(TreeNode root, List<Integer> result) {
    if (root == null) {
        return;
    }
    postorderTraversal(root.left, result);
    postorderTraversal(root.right, result);
    result.add(root.val);
}

层序遍历

红黑树的层序遍历是指按照从根节点到叶子节点的顺序,依次访问每个节点。具体来说,遍历顺序为从根节点开始,按照深度优先搜索的方式遍历每个节点,对于每个节点,先访问其左子树,再访问其右子树。

在 Java 中,可以使用递归或者迭代的方式实现红黑树的层序遍历。

递归实现:

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class RedBlackTree {
    private final TreeNode root;

    public RedBlackTree(TreeNode root) {
        this.root = root;
    }

    public List<Integer> levelOrderTraversal() {
        List<Integer> result = new ArrayList<>();
        levelOrderTraversal(root, 0, result);
        return result;
    }

    private void levelOrderTraversal(TreeNode node, int level, List<Integer> result) {
        if (node == null) {
            return;
        }
        if (result.size() == level) {
            result.add(node.val);
        } else {
            result.set(level, node.val);
        }
        levelOrderTraversal(node.left, level + 1, result);
        levelOrderTraversal(node.right, level + 1, result);
    }
}

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

迭代实现:

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class RedBlackTree {
    private final TreeNode root;

    public RedBlackTree(TreeNode root) {
        this.root = root;
    }

    public List<Integer> levelOrderTraversal() {
        List<Integer> result = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        TreeNode current = root;
        while (current != null || !stack.isEmpty()) {
            while (current != null) {
                result.add(current.val);
                stack.push(current);
                current = current.left;
            }
            current = stack.peek();
            current = current.right;
            stack.pop();
        }
        return result;
    }
}

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

插入与删除

红黑树是一种特殊的二叉查找树,它遵循了特定的规则使得其具有了平衡性,因此查询、插入和删除操作的时间复杂度都能够保持在对数级别。

红黑树的插入操作如下:

  1. 如果插入的节点的父节点是黑色的,则直接将该节点插入到树中。
  2. 如果插入的节点的父节点是红色的,则需要进行变色操作。具体来说,如果该节点的祖父节点是黑色的,则将该节点的父节点和祖父节点都变成黑色的。如果该节点的祖父节点是红色的,则需要进行旋转操作,将该节点的父节点和祖父节点的颜色进行交换,并且可能需要继续旋转,直到该节点的祖父节点是黑色的为止。

红黑树的删除操作如下:

  1. 如果要删除的节点没有子节点,则直接将该节点删除,并且将其父节点变成黑色的。
  2. 如果要删除的节点只有一个子节点,则将该节点的子节点替代该节点的位置,并且将该节点的父节点和子节点都变成黑色的。
  3. 如果要删除的节点有两个子节点,则需要找到该节点的后继节点,也就是左子树的最大值节点。然后将该节点的后继节点替代该节点的位置,并且将该节点的父节点和后继节点都变成黑色的。如果该节点的后继节点的父节点是红色的,则需要进行变色操作。

在进行变色操作时,需要遵循以下规则:

  1. 每个节点都必须是红色或者黑色。
  2. 根节点是黑色的。
  3. 如果一个节点是红色的,那么它的子节点必须是黑色的(也就是说不存在连续的红色节点)。
  4. 对于任意一个节点,从该节点到其叶子节点的所有路径上,黑色节点数量相同。

这些规则保证了红黑树的平衡性,使得查询、插入和删除操作的时间复杂度都能够保持在对数级别。

插入

红黑树插入节点的代码实现可以分为以下几个步骤:

  1. 新建一个节点,并将新节点的值设置为待插入的值。
  2. 按照红黑树的性质,将新节点插入到合适的位置。
  3. 如果新节点是红色,需要进行旋转操作来保持红黑树的性质。
  4. 更新父节点的指针,使其指向新节点。
  5. 如果根节点为空,将新节点设置为根节点。

以下是红黑树插入节点的详细代码实现:

public class RedBlackTree<Key extends Comparable<Key>, Value> {
    private static final boolean RED = true;
    private static final boolean BLACK = false;

    private Node root;

    private class Node {
        Key key;
        Value value;
        Node left, right;
        int size;
        boolean color;

        Node(Key key, Value value, int size, boolean color) {
            this.key = key;
            this.value = value;
            this.size = size;
            this.color = color;
        }
    }

    private boolean isRed(Node x) {
        if (x == null) {
            return false;
        }
        return x.color == RED;
    }

    private Node rotateLeft(Node h) {
        Node x = h.right;
        h.right = x.left;
        x.left = h;
        x.color = h.color;
        h.color = RED;
        x.size = h.size;
        h.size = size(h.left) + size(h.right) + 1;
        return x;
    }

    private Node rotateRight(Node h) {
        Node x = h.left;
        h.left = x.right;
        x.right = h;
        x.color = h.color;
        h.color = RED;
        x.size = h.size;
        h.size = size(h.left) + size(h.right) + 1;
        return x;
    }

    private void flipColors(Node h) {
        h.color = RED;
        h.left.color = BLACK;
        h.right.color = BLACK;
    }

    public int size() {
        return size(root);
    }

    private int size(Node x) {
        if (x == null) {
            return 0;
        }
        return x.size;
    }

    public void put(Key key, Value value) {
        root = put(root, key, value);
        root.color = BLACK;
    }

    private Node put(Node h, Key key, Value value) {
        if (h == null) {
            return new Node(key, value, 1, RED);
        }

        int cmp = key.compareTo(h.key);
        if (cmp < 0) {
            h.left = put(h.left, key, value);
        } else if (cmp > 0) {
            h.right = put(h.right, key, value);
        } else {
            h.value = value;
        }

        if (isRed(h.right) && !isRed(h.left)) {
            h = rotateLeft(h);
        }
        if (isRed(h.left) && isRed(h.left.left)) {
            h = rotateRight(h);
        }
        if (isRed(h.left) && isRed(h.right)) {
            flipColors(h);
        }

        h.size = size(h.left) + size(h.right) + 1;
        return h;
    }
}

以上代码实现了红黑树的插入操作。在实际应用中,我们可以根据需要选择合适的遍历方式来访问红黑树中的节点。

删除

红黑树删除节点的代码实现可以分为以下几个步骤:

  1. 找到待删除节点。
  2. 如果待删除节点是叶子节点(NIL节点),直接删除。
  3. 如果待删除节点只有一个子节点,用其子节点替换该节点。
  4. 如果待删除节点有两个子节点,找到其右子树中的最小节点(或左子树中的最大节点),用该节点替换待删除节点。
  5. 更新父节点的指针,使其指向待删除节点的子节点。
  6. 如果根节点为空,将待删除节点设置为根节点。

以下是红黑树删除节点的详细代码实现:

public class RedBlackTree<Key extends Comparable<Key>, Value> {
    private static final boolean RED = true;
    private static final boolean BLACK = false;

    private Node root;

    private class Node {
        Key key;
        Value value;
        Node left, right;
        int size;
        boolean color;

        Node(Key key, Value value, int size, boolean color) {
            this.key = key;
            this.value = value;
            this.size = size;
            this.color = color;
        }
    }

    private Node deleteMin(Node h) {
        if (h.left == null) {
            return null;
        }
        h.left = deleteMin(h.left);
        h.size = size(h.left) + size(h.right) + 1;
        return balance(h);
    }

    private Node deleteMax(Node h) {
        if (h.right == null) {
            return null;
        }
        h.right = deleteMax(h.right);
        h.size = size(h.left) + size(h.right) + 1;
        return balance(h);
    }

    private Node balance(Node h) {
        if (isRed(h.right)) {
            h = rotateLeft(h);
        }
        if (isRed(h.left) && isRed(h.left.left)) {
            h = rotateRight(h);
        }
        if (isRed(h.left) && isRed(h.right)) {
            flipColors(h);
        }
        return h;
    }

    private void flipColors(Node h) {
        h.color = RED;
        h.left.color = BLACK;
        h.right.color = BLACK;
    }

    public void delete(Key key) {
        root = delete(root, key);
    }

    private Node delete(Node h, Key key) {
        if (key.compareTo(h.key) < 0) {
            if (!isRed(h.left) && !isRed(h.left.left)) {
                h = moveRedLeft(h);
            }
            h.left = delete(h.left, key);
        } else {
            if (isRed(h.left)) {
                h = rotateRight(h);
            }
            if (key.compareTo(h.key) == 0 && (h.right == null)) {
                return null;
            }
            if (!isRed(h.right) && !isRed(h.right.left)) {
                h = moveRedRight(h);
            }
            if (key.compareTo(h.key) == 0) {
                Node x = min(h.right);
                h.key = x.key;
                h.value = x.value;
                h.right = deleteMin(h.right);
            } else {
                h.right = delete(h.right, key);
            }
        }
        return balance(h);
    }

    private Node min(Node x) {
        if (x.left == null) {
            return x;
        } else {
            return min(x.left);
        }
    }

    private Node max(Node x) {
        if (x.right == null) {
            return x;
        } else {
            return max(x.right);
        }
    }

    private Node moveRedLeft(Node h) {
        flipColors(h);
        if (isRed(h.right.left)) {
            h.right = rotateRight(h.right);
            h = rotateLeft(h);
            flipColors(h);
        }
        return h;
    }

    private Node moveRedRight(Node h) {
        flipColors(h);
        if (isRed(h.left.left)) {
            h = rotateRight(h);
            flipColors(h);
        }
        return h;
    }
}

复杂度分析

时间复杂度

红黑树的插入和删除操作的时间复杂度分析如下:

插入操作:

插入操作的时间复杂度主要取决于红黑树的高度。在最坏情况下,插入操作需要将新节点插入到树的最顶层,并且需要进行多次旋转操作来维护红黑树的性质。因此,插入操作的时间复杂度为 O(logn)。

删除操作:

删除操作的时间复杂度也主要取决于红黑树的高度。在最坏情况下,删除操作需要将被删除节点的父节点和祖先是红色节点,并且需要进行多次旋转操作来维护红黑树的性质。因此,删除操作的时间复杂度为 O(logn)。

总的来说,红黑树的插入和删除操作的时间复杂度都是 O(logn),这使得红黑树成为了一种非常高效的数据结构,适用于需要频繁进行插入和删除操作的场景。

空间复杂度

红黑树插入和删除操作的空间复杂度主要与树的高度相关。在最坏情况下,插入或删除操作可能需要进行多次旋转操作,导致树的高度增加。但是,由于红黑树的性质,树的高度始终不会超过 O(logn),因此插入和删除操作的空间复杂度均为 O(logn)。

在实际实现中,红黑树通常采用自平衡的方式来维护树的性质,避免了过多的旋转操作。这种实现方式的空间复杂度为 O(1)或 O(logn),具体取决于红黑树的具体实现方式。

总的来说,红黑树插入和删除操作的空间复杂度均为 O(logn)或 O(1),是一种非常高效的数据结构。

应用场景

Mysql 数据库索引

在 MySQL 数据库中,红黑树被广泛应用于 B+树索引结构中。

B+树索引是一种平衡的多路查找树,其结构与红黑树类似,具有以下优点:

  1. 快速查找:B+树索引能够快速地查找数据,因为它具有平衡的结构,可以将查找范围限制在最小的范围内。

  2. 高存储密度:B+树索引可以将大量数据存储在索引节点中,从而减少了存储空间的浪费。

  3. 支持范围查询:B+树索引可以支持范围查询,因为它具有顺序存储的特点,可以快速地定位到某个范围内的数据。

在 MySQL 数据库中,B+树索引通常存储在磁盘上,以提高查询效率。当数据量较大时,B+树索引可以显著提高数据库的查询速度。

具体来说,在 MySQL 数据库中,B+树索引是以文件的形式存储的,每个节点存储在一个磁盘块中。B+树索引的每个节点都包含了指向子节点的指针和指向数据记录的指针。在查询时,MySQL 数据库会根据 B+树索引的结构,快速地定位到所需的数据记录,从而提高查询效率。

红黑树在 B+树索引中的应用,使得 B+树索引具有了平衡的结构和快速的查找能力,从而提高了数据库的查询效率。
在这里插入图片描述

Java HashMap

Java HashMap 是一种常用的集合类,它是基于哈希表实现的。下面是 HashMap 的结构和工作原理的详细介绍:

Java 8 中 HashMap 的类定义

public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, Cloneable, java.io.Serializable {
    // 省略了部分代码
}

在这个类定义中,我们可以看到 HashMap 继承了AbstractMap类,实现了Map接口,同时还实现了CloneableSerializable接口。这意味着 HashMap 是一个可克隆和可序列化的集合。

在 HashMap 中,每个键值对都是一个Entry对象,它存储在一个哈希桶中。哈希桶是一个数组,它的长度是 2 的幂次方,以提高哈希表的性能。

  1. 数据结构:

HashMap 使用一个Entry<K,V>数组来存储数据,其中K是键类型,V是值类型。每个Entry对象包含一个键和一个值,它们通过哈希函数(通常是HashCode方法)关联起来。

  1. 哈希函数:

HashMap 使用哈希函数将键转换为数组下标,以确定数据存储在数组中的位置。哈希函数的作用是将任意的键值转换为固定长度的、分散均匀的整数,从而减少冲突的可能性。HashMap 中使用的哈希函数是HashCode方法,它是 Object 类的一个默认方法,每个类都可以重写它以生成自己的哈希值。

  1. 冲突解决:

如果两个键通过哈希函数得到了相同的哈希值,就会发生冲突。HashMap 中解决冲突的方法是将冲突的键值存储在一个链表中,这个链表存储在哈希表的桶中。每个桶都包含一个头节点,指向链表中的第一个元素。当哈希冲突时,新元素将被添加到链表的末尾。

  1. 查找操作:

HashMap 的查找操作非常快速,它通过哈希函数将键转换为数组下标,然后在数组中查找与该键关联的值。如果找到了,就返回该值;如果没有找到,则返回null

  1. 插入操作:

HashMap 的插入操作首先通过哈希函数将键转换为数组下标,然后在数组中查找与该键关联的值。如果找到了,就更新该值的值;如果没有找到,就创建一个新的Entry对象,将其插入到数组的相应位置,并将其链接到哈希表的相应桶中的链表末尾。

  1. 删除操作:

HashMap 的删除操作首先通过哈希函数将键转换为数组下标,然后在数组中查找与该键关联的值。如果找到了,就从链表中删除该值,并将该位置。

Java 8 中的 HashMap

Java 8 中的 HashMap 实现相比之前的版本做了一些改进和优化,主要包括以下几个方面:

  1. 初始容量:在 Java 8 中,HashMap 默认的初始容量是 16,而不是以前的 10。这是一个小的优化,可以减少哈希冲突的可能性,提高哈希表的性能。

  2. 负载因子:负载因子是哈希表中元素个数与哈希表大小的比值。在 Java 8 中,负载因子的默认值是 0.75,而不是以前的 0.75。这是一个较大的优化,可以减少哈希冲突的可能性,提高哈希表的性能。

  3. 红黑树:在 Java 8 中,当哈希表中的元素数量超过阈值(默认为 8)时,HashMap 会将哈希桶转换为红黑树。这是一个较大的优化,可以提高哈希表的查询性能,特别是在哈希冲突较多的情况下。

  4. 遍历器:在 Java 8 中,HashMap 提供了一个新的遍历器,称为foreach遍历器,它可以方便地遍历哈希表中的元素。与以前的版本相比,它更加简洁和易于使用。

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

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

相关文章

【LeetCode题目详解】第八章 贪心算法 part06 738.单调递增的数字 968.监控二叉树 (day37补)

本文章代码以c为例&#xff01; 一、力扣第738题&#xff1a;单调递增的数字 题目&#xff1a; 当且仅当每个相邻位数上的数字 x 和 y 满足 x < y 时&#xff0c;我们称这个整数是单调递增的。 给定一个整数 n &#xff0c;返回 小于或等于 n 的最大数字&#xff0c;且数…

zookeeper介绍、zookeeper的安装与配置

1、zookeeper介绍 1.1 官网说明 官方地址&#xff1a;http://zookeeper.apache.org/ 它是拿来管理 Hadoop、Hive、Pig的管理员&#xff0c; Apache Hbase和Apache Solr以及阿里的Dubbo等项目中都采用到了Zookeeper。 一句话&#xff1a;ZooKeeper是一个分布式协调技术、高性…

MySQL基础入门

推荐查看 数据库相关概念 MySQL百度百科 MySQL是一个关系型数据库管理系统&#xff0c;由瑞典MySQL AB 公司开发&#xff0c;属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一&#xff0c;在 WEB 应用方面&#xff0c;MySQL是最好的 RDBMS (Relational Databa…

学习pytorch7 神经网络的基本骨架--nn,module的使用

神经网络的基本骨架--nn,module的使用 官网Module介绍Python父类子类继承关系前向神经网络pycharm快捷键重写类方法codedebug B站小土堆视频学习笔记 官网Module介绍 https://pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module Python父类子类继承关系…

自动化运维:Ansible脚本之playbook剧本

目录 一、理论 1.playbooks 2.YAML 3.使用ansible批量安装apache服务 4.定义、引用变量 5.指定远程主机sudo切换用户 6.when条件判断 7.迭代 8.Templates 模块 9.tags 模块 10.Roles 模块 二、实验 1.使用ansible批量安装apache服务 2.定义、引用变量…

对称加密 非对称加密 AC认证 https原理

文章目录 对称加密及漏洞非对称加密及漏洞什么是数据摘要&#xff08;也称数据指纹&#xff09;什么是CA认证CA证书签发过程https通信方案 对称加密及漏洞 对称加密是一种加密算法&#xff0c;使用相同的密钥&#xff08;也称为对称密钥&#xff09;用于加密和解密数据。在对称…

c++ lambda

Lambda Lambda 表达式一般用于定义匿名函数&#xff0c;使得代码更加灵活简洁&#xff0c;优点&#xff1a; 声明式编程风格&#xff1a;就地匿名定义目标函数或函数对象&#xff0c;不需要额外写一个命名函数或者函数对象。以更直接的方式去写程序&#xff0c;好的可读性和可…

Spring与Mybatis集成且Aop整合

目录 一、集成 1.1 集成的概述 1.2 集成的优点 1.3 代码示例 二、整合 2.1 整合概述 2.2 整合进行分页 一、集成 1.1 集成的概述 集成是指将不同的组件、部分或系统组合在一起&#xff0c;以形成一个整体功能完整的解决方案。它是通过连接、交互和协调组件之间的关系来实…

python的异步编程async

一、介绍 在Python 3.5中引入了async和await关键字&#xff0c;用于异步编程。async关键字用于定义一个协程&#xff08;coroutine&#xff09;&#xff0c;而await关键字则用于等待一个协程完成。 注&#xff1a;协程&#xff08;coroutine&#xff09;是是一种轻量级的线程…

LeetCode——回溯篇(三)

刷题顺序及思路来源于代码随想录&#xff0c;网站地址&#xff1a;https://programmercarl.com 目录 46. 全排列 47. 全排列 II 332. 重新安排行程 51. N 皇后 37. 解数独 46. 全排列 给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任…

Linux命令查看CPU、内存、IO使用情况简单介绍

文章目录 1. CPU相关介绍1.1 物理CPU1.2 物理CPU内核1.3 逻辑CPU1.4 几核几线程1.5 CPU设计图 2. top 查看系统负载、CPU使用情况2.1 系统整体的统计信息2.2 进程信息2.3 top命令使用 3. lscpu 显示有关 CPU 架构的信息4. free 查看内存信息5. iostat 查看io信息 1. CPU相关介绍…

雅思写作 三小时浓缩学习顾家北 笔记总结(一)

目录 饥饿网翻译100个句子记录 There are some economically deprived communities in large cities. there is no clear link between grouping student by ability and their levels of attainment. young people without tertiary education qualification normally hav…

python-数据可视化-下载数据-CSV文件格式

数据以两种常见格式存储&#xff1a;CSV和JSON CSV文件格式 comma-separated values import csv filename sitka_weather_07-2018_simple.csv with open(filename) as f:reader csv.reader(f)header_row next(reader)print(header_row) # [USW00025333, SITKA AIRPORT, A…

高等职业学校物联网实训室建设方案

一、概述 1.1专业背景 物联网&#xff08;Internet of Things&#xff09;被称为继计算机、互联网之后世界信息产业第三次浪潮&#xff0c;它并非一个全新的技术领域&#xff0c;而是现代信息技术发展到一定阶段后出现的一种聚合性应用与技术提升&#xff0c;是随着传感网、通…

解决博客不能解析PHP直接下载源码问题

背景&#xff1a; 在网站设置反向代理后&#xff0c;网站突然不能正常访问&#xff0c;而是会直接下载访问文件的PHP源码 解决办法&#xff1a; 由于在搞完反向代理之后&#xff0c;PHP版本变成了纯静态&#xff0c;所以网站不能正常解析&#xff1b;只需要把PHP版本恢复正常…

SQL注入漏洞复现(CVE-2017-8917)

文章目录 搭建环境启动环境漏洞复现报错注入使用sqlmap 前提条件&#xff1a; 1.安装docker docker pull medicean/vulapps:j_joomla_22.安装docker-compose docker run -d -p 8000:80 medicean/vulapps:j_joomla_23.下载vulhub Docker Compose是 docker 提供的一个命令行工具&…

springboot docker

在Spring Boot中使用Docker可以帮助你将应用程序与其依赖的容器化&#xff0c;并简化部署和管理过程。 当你在Spring Boot中使用Docker时&#xff0c;你的代码不需要特殊的更改。你可以按照通常的方式编写Spring Boot应用程序。 java示例代码&#xff0c;展示了如何编写一个基…

直播预告!生鲜与零售商品识别系统产业实践与部署详解

生鲜零售作为民生消费的重要一环&#xff0c;在促进行业新消费升级的进程中有着至关重要的作用。在超市等无人零售场景中&#xff0c;目前结算方式主要有以下几种&#xff1a; 但是以上几种方法存在如下缺点&#xff1a; 条形码方式&#xff1a;对于成品包装的商品较为成熟&a…

WPF_布局基础

布局容器 Grid 定义由列和行组成的灵活的网格区域。 行 <Grid.RowDefinitions><RowDefinition/><RowDefinition/></Grid.RowDefinitions> 列 <Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDe…

指针与空间按钮的交互

文章目录 原理案例&#xff1a;“直线指针”和“点击按钮”的交互1、效果2、步骤 原理 指针不能直接和空间按钮交互&#xff0c;得借助一个中间层——分发器——它分发指针的进入、退出、选择事件&#xff0c;空间按钮自动监听这些事件 案例&#xff1a;“直线指针”和“点击…