【集合系列】TreeMap 集合

TreeMap 集合

    • 1. 概述
    • 2. 方法
    • 3. 遍历方式
    • 4. 排序方式
    • 5. 代码示例1
    • 6. 代码示例2
    • 7. 代码示例3
    • 8. 注意事项
    • 9. 源码分析

其他集合类

父类 Map

集合类的遍历方式

TreeSet 集合

具体信息请查看 API 帮助文档

1. 概述

TreeMap 是 Java 中的一个集合类,它实现了 SortedMap 接口。它是基于红黑树的数据结构实现的,它能够保持其中的元素处于有序状态。

  • TreeMap 集合中的元素是以键值对的形式存储的,其中的键用于排序和唯一性的保证,而值则用于存储具体的数据。

  • TreeMap 根据键的自然顺序或者自定义的比较器来进行排序,使得在遍历 TreeMap 集合时能够有序地访问其中的元素。

TreeMap 集合的特点

  1. TreeMap 中的键必须是可比较的,要么实现了 Comparable 接口,要么在构造 TreeMap 时提供了自定义的比较器。

  2. TreeMap 中的键是唯一的,不允许重复的键存在。

  3. TreeMap 是基于红黑树实现的,因此在插入、删除和查找操作的时间复杂度均为 O(logn),具有较高的效率。

  4. TreeMap 中的元素是有序的,可以根据键来进行排序。

  5. TreeMap 不是线程安全的,如果需要在多线程环境下使用,需要进行额外的同步处理。

2. 方法

TreeMap集合是Map集合的子类,因此Map集合的方法TreeMap集合都能使用。

Map集合

方法名说明
V put(K key,V value)添加元素
V remove(Object key)根据键删除键值对元素
void clear()移除所有的键值对元素
boolean containsKey(Object key)判断集合是否包含指定的键
boolean containsValue(Object value)判断集合是否包含指定的值
boolean isEmpty()判断集合是否为空
int size()集合的长度,也就是集合中键值对的个数

3. 遍历方式

与共有的 集合遍历方式 一样

4. 排序方式

TreeMap集合和TreeSet集合一样,底层都是红黑树,因此排序方式一样

TreeSet 集合排序方式详解

  • 默认排序规则/自然排序

  • 比较器排序

5. 代码示例1

  • 代码示例
    需求:键:整数表示id;值:字符串表示商品名称
    要求:按照id的升序排列,按照id的降序排列
package text.text02;
/*TreeMap基本应用:
需求:
    键:整数表示id
    值:字符串表示商品名称
要求:按照id的升序排列,按照id的降序排列
*/

import java.util.Comparator;
import java.util.TreeMap;

public class text52 {
    public static void main(String[] args) {
        //自然排序(升序排列)
        System.out.println("方法一:自然排序");
        method1();        //{1001=平板, 1002=汽车, 1003=手机, 1004=飞机, 1005=电脑}

        //比较器排序(降序排列)
        System.out.println("方法二:比较器排序");
        method2();        //{1005=电脑, 1004=飞机, 1003=手机, 1002=汽车, 1001=平板}
    }

    //自然排序(Java底层默认的自然排序就是按照升序排列)
    public static void method1() {
        //创建集合并添加数据
        TreeMap<Integer, String> tm = new TreeMap<>();
        tm.put(1003, "手机");
        tm.put(1005, "电脑");
        tm.put(1001, "平板");
        tm.put(1002, "汽车");
        tm.put(1004, "飞机");
        System.out.println(tm);
    }

    //比较器排序(当Java底层默认的自然排列不能满足需求时,采用比较器排列)
    public static void method2() {
        //创建集合(在创建对象的时候指定比较器规则)
        TreeMap<Integer, String> tm = new TreeMap<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
        //添加数据
        tm.put(1003, "手机");
        tm.put(1005, "电脑");
        tm.put(1001, "平板");
        tm.put(1002, "汽车");
        tm.put(1004, "飞机");

        System.out.println(tm);
    }
}

  • 输出结果
    • 方法一:自然排序
      在这里插入图片描述

    • 方法二:比较器排序
      在这里插入图片描述

6. 代码示例2

  • 代码示例
    需求:键:学生对象;值:籍贯
    要求:按照学生年龄的升序排列,年龄一样按照姓名的字母排列,同姓名同年龄视为同一个人
package text.text02;

import java.util.*;

/*
需求:
    键:学生对象
    值:籍贯
要求:按照学生年龄的升序排列,年龄一样按照姓名的字母排列,同姓名同年龄视为同一个人
 */
public class text53 {
    public static void main(String[] args) {
        //自然排序
        System.out.println("方法一:自然排序");
        method1();
        //比较器排序
        System.out.println("方法二:比较器排序");
        method2();
    }

    //自然排序 (Java底层默认的自然排序就是按照升序排列,自定义对象时,需要在Javabean类中实现Comparable接口并重写里面的CompareTo方法)
    public static void method1() {
        //创建学生对象
        Student8 student1 = new Student8("zhangsan", 10);
        Student8 student2 = new Student8("lisi", 10);
        Student8 student3 = new Student8("wangwu", 11);
        Student8 student4 = new Student8("liubei", 9);
        Student8 student5 = new Student8("guanyu", 13);
        Student8 student6 = new Student8("guanyu", 13);

        //创建集合对象
        TreeMap<Student8, String> tm = new TreeMap<>();

        //添加数据
        tm.put(student1, "陕西");
        tm.put(student2, "湖南");
        tm.put(student3, "河北");
        tm.put(student4, "江苏");
        tm.put(student5, "北京");
        tm.put(student6, "湖南");

        //遍历输出集合
        Set<Map.Entry<Student8, String>> entries = tm.entrySet();
        for (Map.Entry<Student8, String> entry : entries) {
            Student8 key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + " = " + value);
        }
    }

    //比较器排序(当Java底层默认的自然排列不能满足需求时,采用比较器排列,在创建对象时,指定比较规则)
    public static void method2() {
        //创建学生对象
        Student8 student1 = new Student8("zhangsan", 10);
        Student8 student2 = new Student8("lisi", 10);
        Student8 student3 = new Student8("wangwu", 11);
        Student8 student4 = new Student8("liubei", 9);
        Student8 student5 = new Student8("guanyu", 13);
        Student8 student6 = new Student8("guanyu", 13);

        //创建集合对象
        TreeMap<Student8, String> tm = new TreeMap<>(new Comparator<Student8>() {
            @Override
            //按照学生年龄的升序排列,年龄一样按照姓名的字母排列,同姓名同年龄视为同一个人
            public int compare(Student8 o1, Student8 o2) {
                //o1:表示当前要添加的元素
                //o2:表示已经在红黑树存在的元素
                //返回值:
                //负数:表示当前要添加的数据是小的,存左边
                //正数:表示当前要添加的数据是大的,存右边
                //0:表示当前要添加的元素已经存在,舍弃
                int i = o1.getAge() - o2.getAge();
                i = i == 0 ? o1.getName().compareTo(o2.getName()) : i;
                return i;
            }
        });

        //添加数据
        tm.put(student1, "陕西");
        tm.put(student2, "湖南");
        tm.put(student3, "河北");
        tm.put(student4, "江苏");
        tm.put(student5, "北京");
        tm.put(student6, "湖南");

        //遍历输出集合
        Set<Map.Entry<Student8, String>> entries = tm.entrySet();
        for (Map.Entry<Student8, String> entry : entries) {
            Student8 key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + " = " + value);
        }
    }
}

//学生对象
class Student8 implements Comparable<Student8> {
    private String name;
    private int age;


    public Student8() {
    }

    public Student8(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /**
     * 获取
     *
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     *
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     *
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     *
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student8 student8 = (Student8) o;
        return age == student8.age && Objects.equals(name, student8.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    public String toString() {
        return "Student8{name = " + name + ", age = " + age + "}";
    }

    @Override
    //按照学生年龄的升序排列,年龄一样按照姓名的字母排列,同姓名同年龄视为同一个人
    public int compareTo(Student8 o) {
        //this:表示当前要添加的元素
        //o:表示已经在红黑树中的元素
        //返回值:
        //负数:表示当前要添加的数据是小的,存左边
        //正数:表示当前要添加的数据是大的,存右边
        //0:表示当前要添加的元素已经存在,舍弃
        int i = this.getAge() - o.getAge();
        i = i == 0 ? this.getName().compareTo(o.getName()) : i;
        return i;
    }
}

  • 输出结果
    • 方法一:自然排序
      在这里插入图片描述

    • 方法二:比较器排序
      在这里插入图片描述

7. 代码示例3

  • 代码示例
    统计个数:
    需求:字符串“aababcabcdabcde”,请统计字符串中每一个字符出现的次数,并按照如下格式输出。
    输出结果:a(5)b(4)c(3)d(2)e(1)
package text.text02;

import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import java.util.TreeMap;

/*
统计个数:
需求:字符串“aababcabcdabcde”,请统计字符串中每一个字符出现的次数,并按照如下格式输出。
    输出结果:a(5)b(4)c(3)d(2)e(1)

新的统计思想:利用Map集合进行统计      (键:表示要统计的内容;值:表示次数)
    如果题目中没有要求对结果进行排序,默认使用HashMap
    如果题目中要求对结果进行排序,则使用TreeMap

 */
public class text54 {
    public static void main(String[] args) {
        //创建数组存储每一个字符
        char[] arr = {'a', 'b', 'c', 'd', 'e'};

        //定义一个变量用于记录字符串
        String str = "aababcabcdabcde";

        //创建集合
        TreeMap<Character, Integer> tm = new TreeMap<>();

        for (int i = 0; i < str.length(); i++) {
            //如果双列集合中存在该字符,则获取双列集合中该字符的次数并将次数+1
            if (tm.containsKey(str.charAt(i))) {
                //获取双列集合中该字符的次数
                Integer value = tm.get(str.charAt(i));
                //将次数+1
                value++;
                //用新次数覆盖原次数
                tm.put(str.charAt(i), value);
            }
            //如果双列集合中存在该字符,则添加该字符并将次数改为1
            else {
                tm.put(str.charAt(i), 1);
            }
        }
        //遍历集合
        //1.利用StringBuilder修改输出格式
        //创建StringBuilder对象
        StringBuilder sb = new StringBuilder();
        Set<Map.Entry<Character, Integer>> entries = tm.entrySet();
        for (Map.Entry<Character, Integer> entry : entries) {
            //获取集合里的键
            Character key = entry.getKey();
            //获取集合里的值
            Integer value = entry.getValue();
            //将数据按照需求格式添加进StringBuilder集合
            sb.append(key).append("(").append(value).append(")");
        }
        System.out.println("1.利用StringBuilder修改输出格式:");
        System.out.println(sb);                  //a(5)b(4)c(3)d(2)e(1)

        //2.利用StringJoiner修改输出格式
        //创建StringJoiner对象
        StringJoiner sj = new StringJoiner("", "", "");
        Set<Character> set = tm.keySet();
        for (Character key : set) {
            Integer value = tm.get(key);
            //将数据按照需求格式添加进StringJoiner集合
            sj.add(key + "").add("(").add(value + "").add(")");//+" "是为了将key和value转换成字符串
        }
        System.out.println("2.利用StringJoiner修改输出格式:");
        System.out.println(sj);       //a(5)b(4)c(3)d(2)e(1)
    }
}

  • 输出结果
    • 1.利用StringBuilder修改输出格式:
      在这里插入图片描述

    • 2.利用StringJoiner修改输出格式:
      在这里插入图片描述

8. 注意事项

  1. 键的唯一性:TreeMap 中的键是唯一的,不允许重复的键存在。如果尝试插入一个已经存在的键,新的值将会覆盖旧的值。如果需要存储允许重复键的情况,可以考虑使用其他集合类如 ArrayList 或者 HashMap。

  2. 键的可比较性:TreeMap 要求集合中的键必须是可比较的,要么实现了 Comparable 接口,要么在构造 TreeMap 时提供了自定义的比较器。如果键没有实现 Comparable 接口,并且没有提供自定义的比较器,则在插入元素或者进行比较操作时会抛出 ClassCastException 异常。

  3. 线程安全性:TreeMap 不是线程安全的,如果需要在多线程环境下使用 TreeMap,需要进行额外的同步处理。可以考虑使用 Collections 类的 synchronizedSortedMap 方法包装 TreeMap,或者使用并发集合类如 ConcurrentHashMap。

  4. 迭代顺序:TreeMap 中的元素是有序的,可以根据键来进行排序。通过 iterator 或者 forEach 遍历 TreeMap 时,元素会按照键的顺序以升序进行遍历。

  5. 性能开销:由于 TreeMap 的底层是红黑树,插入、删除和查找操作的时间复杂度均为 O(logn),相比于其他集合类可能会有较高的性能开销。如果对性能有较高要求,可以考虑使用其他集合类。

9. 源码分析

  1. TreeMap中每一个节点的内部属性

    K key;					//键
    V value;				//值
    Entry<K,V> left;		//左子节点
    Entry<K,V> right;		//右子节点
    Entry<K,V> parent;		//父节点
    boolean color;			//节点的颜色
    
  2. TreeMap类中中要知道的一些成员变量

    public class TreeMap<K,V>{
       
        //比较器对象
        private final Comparator<? super K> comparator;
    
    	//根节点
        private transient Entry<K,V> root;
    
    	//集合的长度(节点的个数)
        private transient int size = 0;
    
    
  3. 空参构造

    //空参构造就是没有传递比较器对象
    public TreeMap() {
    	comparator = null;
    }
    
  4. 带参构造

    	//带参构造就是传递了比较器对象。
    	public TreeMap(Comparator<? super K> comparator) {
            this.comparator = comparator;
        }
    
  5. 添加元素

    	public V put(K key, V value) {
            return put(key, value, true);
        }
    
    	//参数一:键
    	//参数二:值
    	//参数三:当键重复的时候,是否需要覆盖值
    	//		true:覆盖
    	//		false:不覆盖
    		
    	private V put(K key, V value, boolean replaceOld) {
    		//获取根节点的地址值,赋值给局部变量t
            Entry<K,V> t = root;
    		//判断根节点是否为null
    		//如果为null,表示当前是第一次添加,会把当前要添加的元素,当做根节点
    		//如果不为null,表示当前不是第一次添加,跳过这个判断继续执行下面的代码
            if (t == null) {
    			//方法的底层,会创建一个Entry对象,把他当做根节点
                addEntryToEmptyMap(key, value);
    			//表示此时没有覆盖任何的元素
                return null;
            }
    		//表示两个元素的键比较之后的结果
            int cmp;
    		//表示当前要添加节点的父节点
            Entry<K,V> parent;
    		
    		//表示当前的比较规则
    		//如果我们是采取默认的自然排序,那么此时comparator记录的是null,cpr记录的也是null
    		//如果我们是采取比较器排序方式,那么此时comparator记录的是就是比较器
            Comparator<? super K> cpr = comparator;
    		//表示判断当前是否有比较器对象
    		//如果传递了比较器对象,就执行if里面的代码,此时以比较器的规则为准
    		//如果没有传递比较器对象,就执行else里面的代码,此时以自然排序的规则为准
            if (cpr != null) {
                do {
                    parent = t;
                    cmp = cpr.compare(key, t.key);
                    if (cmp < 0)
                        t = t.left;
                    else if (cmp > 0)
                        t = t.right;
                    else {
                        V oldValue = t.value;
                        if (replaceOld || oldValue == null) {
                            t.value = value;
                        }
                        return oldValue;
                    }
                } while (t != null);
            } else {
    			//把键进行强转,强转成Comparable类型的
    			//要求:键必须要实现Comparable接口,如果没有实现这个接口
    			//此时在强转的时候,就会报错。
                Comparable<? super K> k = (Comparable<? super K>) key;
                do {
    				//把根节点当做当前节点的父节点
                    parent = t;
    				//调用compareTo方法,比较根节点和当前要添加节点的大小关系
                    cmp = k.compareTo(t.key);
    				
                    if (cmp < 0)
    					//如果比较的结果为负数
    					//那么继续到根节点的左边去找
                        t = t.left;
                    else if (cmp > 0)
    					//如果比较的结果为正数
    					//那么继续到根节点的右边去找
                        t = t.right;
                    else {
    					//如果比较的结果为0,会覆盖
                        V oldValue = t.value;
                        if (replaceOld || oldValue == null) {
                            t.value = value;
                        }
                        return oldValue;
                    }
                } while (t != null);
            }
    		//就会把当前节点按照指定的规则进行添加
            addEntry(key, value, parent, cmp < 0);
            return null;
        }	
    	
    	
    	
    	 private void addEntry(K key, V value, Entry<K, V> parent, boolean addToLeft) {
            Entry<K,V> e = new Entry<>(key, value, parent);
            if (addToLeft)
                parent.left = e;
            else
                parent.right = e;
    		//添加完毕之后,需要按照红黑树的规则进行调整
            fixAfterInsertion(e);
            size++;
            modCount++;
        }
    	
    	
    	
    	private void fixAfterInsertion(Entry<K,V> x) {
    		//因为红黑树的节点默认就是红色的
            x.color = RED;
    
    		//按照红黑规则进行调整
    		
    		//parentOf:获取x的父节点
    		//parentOf(parentOf(x)):获取x的爷爷节点
    		//leftOf:获取左子节点
            while (x != null && x != root && x.parent.color == RED) {
    			
    			
    			//判断当前节点的父节点是爷爷节点的左子节点还是右子节点
    			//目的:为了获取当前节点的叔叔节点
                if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {
    				//表示当前节点的父节点是爷爷节点的左子节点
    				//那么下面就可以用rightOf获取到当前节点的叔叔节点
                    Entry<K,V> y = rightOf(parentOf(parentOf(x)));
                    if (colorOf(y) == RED) {
    					//叔叔节点为红色的处理方案
    					
    					//把父节点设置为黑色
                        setColor(parentOf(x), BLACK);
    					//把叔叔节点设置为黑色
                        setColor(y, BLACK);
    					//把爷爷节点设置为红色
                        setColor(parentOf(parentOf(x)), RED);
    					
    					//把爷爷节点设置为当前节点
                        x = parentOf(parentOf(x));
                    } else {
    					
    					//叔叔节点为黑色的处理方案
    					
    					
    					//表示判断当前节点是否为父节点的右子节点
                        if (x == rightOf(parentOf(x))) {
    						
    						//表示当前节点是父节点的右子节点
                            x = parentOf(x);
    						//左旋
                            rotateLeft(x);
                        }
                        setColor(parentOf(x), BLACK);
                        setColor(parentOf(parentOf(x)), RED);
                        rotateRight(parentOf(parentOf(x)));
                    }
                } else {
    				//表示当前节点的父节点是爷爷节点的右子节点
    				//那么下面就可以用leftOf获取到当前节点的叔叔节点
                    Entry<K,V> y = leftOf(parentOf(parentOf(x)));
                    if (colorOf(y) == RED) {
                        setColor(parentOf(x), BLACK);
                        setColor(y, BLACK);
                        setColor(parentOf(parentOf(x)), RED);
                        x = parentOf(parentOf(x));
                    } else {
                        if (x == leftOf(parentOf(x))) {
                            x = parentOf(x);
                            rotateRight(x);
                        }
                        setColor(parentOf(x), BLACK);
                        setColor(parentOf(parentOf(x)), RED);
                        rotateLeft(parentOf(parentOf(x)));
                    }
                }
            }
    		
    		//把根节点设置为黑色
            root.color = BLACK;
        }
    
  6. 课堂思考问题:

    1. TreeMap添加元素的时候,键是否需要重写hashCode和equals方法?

    此时是不需要重写的。

    1. HashMap是哈希表结构的,JDK8开始由数组,链表,红黑树组成的。
      既然有红黑树,HashMap的键是否需要实现Compareable接口或者传递比较器对象呢?

    不需要的。
    因为在HashMap的底层,默认是利用哈希值的大小关系来创建红黑树的

    1. TreeMap和HashMap谁的效率更高?

    如果是最坏情况,添加了8个元素,这8个元素形成了链表,此时TreeMap的效率要更高
    但是这种情况出现的几率非常的少。
    一般而言,还是HashMap的效率要更高。

    1. 你觉得在Map集合中,java会提供一个如果键重复了,不会覆盖的put方法呢?

    此时putIfAbsent本身不重要。

    传递一个思想:
    代码中的逻辑都有两面性,如果我们只知道了其中的A面,而且代码中还发现了有变量可以控制两面性的发生。
    那么该逻辑一定会有B面。

     习惯:
     boolean类型的变量控制,一般只有AB两面,因为boolean只有两个值
     int类型的变量控制,一般至少有三面,因为int可以取多个值。	
    
    1. 三种双列集合,以后如何选择?
      HashMap LinkedHashMap TreeMap

    默认:HashMap(效率最高)
    如果要保证存取有序:LinkedHashMap
    如果要进行排序:TreeMap

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

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

相关文章

ChatGPT高效提问—prompt常见用法(续篇九)

ChatGPT高效提问—prompt常见用法(续篇九) ​ 如何准确地向大型语言模型提出问题,使其更好地理解我们的意图,从而得到期望的答案呢?编写有效的prompt的技巧,精心设计的prompt,获得期望的的答案。 1.1 增加条件 ​ 在各种prompt技巧中,增加条件是最常用的。在prompt中…

人工智能之大数定理和中心极限定理

大数定律 大数定律&#xff1a;是一种描述当试验次数很大时所呈现的概率性致的定律&#xff0c;由概率统计定义“频率收敛于概率”引申而来。换而言之&#xff0c;就是n个独立分布的随机变量其观察值的均值依概率收敛于这些随机变量所属分布的理论均值&#xff0c;也就是总体均…

精读《js 模块化发展》

1 引言 如今&#xff0c;Javascript 模块化规范非常方便、自然&#xff0c;但这个新规范仅执行了 2 年&#xff0c;就在 4 年前&#xff0c;js 的模块化还停留在运行时支持&#xff0c;10 年前&#xff0c;通过后端模版定义、注释定义模块依赖。对经历过来的人来说&#xff0c;…

区间dp 笔记

区间dp一般是先枚举区间长度&#xff0c;再枚举左端点&#xff0c;再枚举分界点&#xff0c;时间复杂度为 环形石子合并 将 n 堆石子绕圆形操场排放&#xff0c;现要将石子有序地合并成一堆。 规定每次只能选相邻的两堆合并成新的一堆&#xff0c;并将新的一堆的石子数记做该…

qt学习:串口

头文件 #include <QSerialPort> #include <QSerialPortInfo> 模块 QT core gui serialport 编程步骤 配置一个ui界面&#xff0c;五个QComboBox和一个按钮和一个QTextEdit 添加一个成员 private:QSerialPort *serial; 在构造函数中初始化ui端口列表和…

【数据结构和算法】--- 基于c语言排序算法的实现(2)

目录 一、交换排序1.1 冒泡排序1.2 快速排序1.2.1 hoare法1.2.2 挖坑法1.2.3 前后指针法 1.3 快速排序优化1.3.1 三数取中法选key1.3.2 递归到小的子区间使用插入排序 1.4 快排非递归版 二、归并排序2.1 归并排序2.1.1 递归版2.1.2 非递归版 一、交换排序 基本思想&#xff1a…

hexo 博客搭建以及踩雷总结

搭建时的坑 文章置顶 安装一下这个依赖 npm install hexo-generator-topindex --save然后再文章的上面设置 top: number&#xff0c;数字越大&#xff0c;权重越大&#xff0c;也就是越靠顶部 hexo 每次推送 nginx 都访问不到 宝塔自带的 nginx 的 config 里默认的角色是 …

磁盘分区和挂载

一、分区概念 1、基本概念 (1) 一块硬盘最多只能有4个主分区 (2) 其中一个(且最多只能有一个)主分区能作为扩展分区,而扩展分区不能写入数据,只能包含逻辑分区 2、格式化 分区之后的磁盘并不能直接使用&#xff0c;而是需要先进行格式化&#xff0c;又称为逻辑格式化。它是指…

掌握Go的加密技术:crypto/rsa库的高效使用指南

掌握Go的加密技术&#xff1a;crypto/rsa库的高效使用指南 引言crypto/rsa 库概览RSA 加密算法基本原理crypto/rsa 库的功能和应用 安装和基本设置在 Go 项目中引入 crypto/rsa 库基本环境设置和配置 密钥生成与管理生成 RSA 密钥对密钥存储和管理 加密和解密操作使用 RSA 加密…

【HTML+CSS】使用CSS中的Position与z-index轻松实现一个简单的自定义标题栏效果

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;web开发者、设计师、技术分享博主 &#x1f40b; 希望大家多多支持一下, 我们一起学习和进步&#xff01;&#x1f604; &#x1f3c5; 如果文章对你有帮助的话&#xff0c;欢迎评论 &#x1f4ac;点赞&a…

【数据结构与算法】【小白也能学的数据结构与算法】递归 分治 迭代 动态规划 无从下手?一文通!!!

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《数据结构与算法&#xff1a;初学者入门指南》&#x1f4d8;&am…

【计算机网络】Web HTTP

Web和HTTP HTTP 超文本传输协议 HyperText Transfer Protocol HTTP使用TCP作为支撑传输协议 由一个客户程序和一个服务器程序实现一些常见名词。。。无状态协议 stateless protocol 不保存关于客户的任何信息非持续/持续链接 non-persistent con…

【十三】【C++】vector简单实现

代码实现 /*vector类简单实现*/ #if 1 #define _CRT_SECURE_NO_WARNINGS#include <iostream> using namespace std; #include <vector> #include <algorithm> #include <crtdbg.h> #include <assert.h> #include <string.h>namespace MyVe…

寒假作业2024.2.11

请使用递归实现n! #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <unistd.h> int fun(int n) {if (n0) {return 1;} else {return n*fun(n-1);} } int main(int argc, const char *argv[]) {int n…

嵌入式系统学习指南:从入门到精通

如今嵌入式系统已经广泛应用于工控、消费电子、汽车电子、医疗设备等多个领域。越来越多的IT工程师选择进入嵌入式系统行业。那么作为新手,如何系统地学习嵌入式知识,从入门到精通呢?本文将为大家提供一份简单的自学路线。&#xff08;个人观点&#xff0c;仅供参考&#xff0…

代码随想录 Leetcode55. 跳跃游戏

题目&#xff1a; 代码(首刷自解 2024年2月9日&#xff09;&#xff1a; class Solution { public:bool canJump(vector<int>& nums) {int noz 0;for (int i nums.size() - 2; i > 0; --i) {if (nums[i] 0) {noz;continue;} else {if (nums[i] > noz) noz …

vtkActor 设置特定图层 显示及置顶显示

问题&#xff0c;有时我们需要显示某个 Actor 在相机最前面&#xff0c;可以遮盖后面的物体;显示在顶层有点不准确&#xff1b;因为这个还相机位置也有关系&#xff1b; 这里讲三种情况&#xff1a; 1. 设置 Mapper 顶层&#xff0c;尝试了一下&#xff0c;可以用于某些场景&…

《PCI Express体系结构导读》随记 —— 第II篇 第4章 PCIe总线概述(12)

接前一篇文章&#xff1a;《PCI Express体系结构导读》随记 —— 第II篇 第4章 PCIe总线概述&#xff08;11&#xff09; 4.2 PCIe体系结构的组成部件 PCIe总线作为处理器系统的局部总线&#xff0c;其作用与PCI总线类似&#xff0c;主要目的是为了连接处理器系统中的外部设备…

前后端分离nodejs+vue流浪狗宠物领养公益网站

1.发现公益&#xff1a;主要是根据社会上的调研&#xff0c;来收集的社会上有关流浪狗的公益活动&#xff0c;发布在公益网站上能被更多人发现&#xff0c;主要让更多人能参与到公益活动中来&#xff0c;并调动群众的同情心和爱心&#xff0c;借此希望在养宠物的主人能避免自己…

直播app开发,技术驱动的实时互动新纪元

随着互联网技术的快速发展&#xff0c;直播已成为我们日常生活的重要组成部分。从娱乐、教育到商业活动&#xff0c;直播的广泛应用正在改变着我们的生活和工作方式。在这一变革中&#xff0c;直播开发扮演着至关重要的角色。本文将探讨直播开发的核心理念、技术挑战以及未来的…