基于树的存储数据结构demo

news2024/11/19 22:36:25

一.简介

由于之前博主尝试Java重构redis,在redis中的的字典数据结构底层也是采用数组实现,字典中存在两个hash表,一个是用于存储数据,另一个被用于rehash扩容为前者两倍。但是我注意到了在redis的数据结构中,并没有像Java集合类中的hashmap一样的树化机制,即当链表数大于8,且通过线性搜索法查找后续hash槽,发现占用了64个了,就会将拉链上的链表转化为红黑树,涉及到自平衡等等操作。是比较麻烦的,于是博主尝试使用二叉搜索树来实现一个基础的树的存储数据的数据结构。

二.准备代码

先定义两个接口,里面是我们准备实现的一些必须的方法,

IMember 接口

这个接口的实现类是该存储数据结构中的每个对象。

package partA;

/**
 *
 * an objects of a class implementing this interface holds a
 * database of member information

 * DO NOT CHANGE THIS INTERFACE
 * You must create a class that implements this interface
 *
 */

public interface IMemberDB {

    /**
     * Empties the database.
     * @pre true
     */
    public void clearDB();

    /**
     * Determines whether a member's name exists as a key inside the database
     * @pre name is not null and not empty string
     * @param name the member name (key) to locate
     * @return true if the name exists as a key in the database
     */
    public boolean containsName(String name);

    /**
     * Returns a Member object mapped to the supplied name.
     * @pre name not null and not empty string
     * @param name The Member name (key) to locate
     * @return the Member object mapped to the key name if the name
    exists as key in the database, otherwise null
     */
    public Member get(String name);

    /**
     * Returns the number of members in the database
     * @pre true
     * @return number of members in the database.
     */
    public int size();

    /**
     * Determines if the database is empty or not.
     * @pre true
     * @return true iff the database is empty
     */
    public boolean isEmpty();

    /**
     * Inserts a Member object into the database, with the key of the supplied
     * member's name.
     * Note: If the name already exists as a key, then the original entry
     * is overwritten.
     * This method must return the previous associated value
     * if one exists, otherwise null
     *
     * @pre member not null and member name not empty string
     */
    public Member put(Member member);

    /**
     * Removes and returns a member from the database, with the key
     * the supplied name.
     * @param name The name (key) to remove.
     * @pre name not null and name not empty string
     * @return the removed member object mapped to the name, or null if
     * the name does not exist.
     */
    public Member remove(String name);

    /**
     * Prints the names and affiliations of all the members in the database in
     * alphabetic order.
     * @pre true
     */
    public void displayDB();
}


IMemberDB 接口

该接口就是定义一些 crud方法

package partA;

/**
 *
 * an objects of a class implementing this interface holds a
 * database of member information

 * DO NOT CHANGE THIS INTERFACE
 * You must create a class that implements this interface
 *
 */

public interface IMemberDB {

    /**
     * Empties the database.
     * @pre true
     */
    public void clearDB();

    /**
     * Determines whether a member's name exists as a key inside the database
     * @pre name is not null and not empty string
     * @param name the member name (key) to locate
     * @return true if the name exists as a key in the database
     */
    public boolean containsName(String name);

    /**
     * Returns a Member object mapped to the supplied name.
     * @pre name not null and not empty string
     * @param name The Member name (key) to locate
     * @return the Member object mapped to the key name if the name
    exists as key in the database, otherwise null
     */
    public Member get(String name);

    /**
     * Returns the number of members in the database
     * @pre true
     * @return number of members in the database.
     */
    public int size();

    /**
     * Determines if the database is empty or not.
     * @pre true
     * @return true iff the database is empty
     */
    public boolean isEmpty();

    /**
     * Inserts a Member object into the database, with the key of the supplied
     * member's name.
     * Note: If the name already exists as a key, then the original entry
     * is overwritten.
     * This method must return the previous associated value
     * if one exists, otherwise null
     *
     * @pre member not null and member name not empty string
     */
    public Member put(Member member);

    /**
     * Removes and returns a member from the database, with the key
     * the supplied name.
     * @param name The name (key) to remove.
     * @pre name not null and name not empty string
     * @return the removed member object mapped to the name, or null if
     * the name does not exist.
     */
    public Member remove(String name);

    /**
     * Prints the names and affiliations of all the members in the database in
     * alphabetic order.
     * @pre true
     */
    public void displayDB();
}


三.实现类

package partA;

import java.util.Objects;

public class Member implements IMember{
    String fullName;
    String affiliation;

    public Member(String name, String affiliation){
        this.fullName = name;
        this.affiliation = affiliation;
    }
    public String getName() {
        return fullName;
    }
    public String getAffiliation() {
        return affiliation;
    }

    public void setAffiliation(String affiliation) {
        this.affiliation = affiliation;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Member member = (Member) o;
        return Objects.equals(fullName, member.fullName) && Objects.equals(affiliation, member.affiliation);
    }

    @Override
    public int hashCode() {
        return Objects.hash(fullName, affiliation);
    }
}
package partA;

import java.util.ArrayList;
import java.util.List;
public class MemberBST implements IMemberDB{

    private Node root;

    private static class Node {
        Member member;
        String name;
        Node left, right;

        Node(Member member) {
            this.member = member;
            this.name = member.getName();
            left = right = null;
        }
    }

    // constructor
    public MemberBST() {
        System.out.println("Binary Search Tree");
        this.root = null;
    }

    @Override
    public void clearDB() {
        root = null;
    }

    @Override
    public boolean containsName(String name) {
        return recursionTree(root, name);
    }

    // if two string is same,compare() method will return 0
    private boolean recursionTree(Node node, String name) {
        if (node == null) return false;
        if (node.name.compareTo(name) == 0) return true;

        return recursionTree(node.left, name) || recursionTree(node.right, name);
    }

    @Override
    public Member get(String name) {
        List<String> sequence = new ArrayList<>();
        Member result = recursionGetter(root, name, sequence);
        if (result != null) {
            System.out.println("the sequence of nodes of the tree visited: " + sequence);
        }
        return result;
    }

    private Member recursionGetter(Node node, String name, List<String> sequence) {
        if (node == null){
            return null;
        }
        sequence.add(node.member.getName()); // Add the node to the sequence

        if (node.name.compareTo(name) == 0) {
            System.out.println("the Member name: " + node.member.getName());
            return node.member;
        }

        // recursion
        Member leftResult = recursionGetter(node.left, name, sequence);
        if (leftResult != null) {
            return leftResult;
        }
        return recursionGetter(node.right, name, sequence);
    }



    @Override
    public int size() {
        int cnt = 0;
        return calculator(root, cnt);
    }

    private int calculator(Node node, int cnt) {
        if (node == null) return cnt;
        cnt++;

        cnt = calculator(node.left, cnt);
        cnt = calculator(node.right, cnt);

        return cnt;
    }

    @Override
    public boolean isEmpty() {
        return root == null;
    }

    @Override
    public Member put(Member member) {
        if ((member == null) || member.getName().isEmpty()) {
            throw new IllegalArgumentException("member and " +
                    "member's name can not be null");
        }
        // exist?
        Member meb = get(member.getName());
        if (meb != null) {
            meb.setAffiliation(member.affiliation);
            System.out.println("the Member name: " + meb.getName());
            return meb;
        }
        if (isEmpty()) {
            root = new Node(member);
            System.out.println("Visited node: " + root.member.getName());
        } else {
            recursionAdder(root, member);
        }
        return member;
    }

    private void recursionAdder(Node node, Member member) {
        int gap = member.getName().compareTo(node.name);
        if (gap < 0) {
            // The new member's name comes before the current node's name, go left
            if (node.left == null) {
                node.left = new Node(member);
                System.out.println("Visited node: " + node.member.getName());
            } else {
                recursionAdder(node.left, member);
            }
        } else if (gap > 0) {
            // The new member's name comes after the current node's name, go right
            if (node.right == null) {
                node.right = new Node(member);
                System.out.println("Visited node: " + node.member.getName());
            } else {
                recursionAdder(node.right, member);
            }
        }
    }

    @Override
    public Member remove(String name) {
        if (name == null || name.isEmpty()) {
            throw new IllegalArgumentException("Name cannot be null or an empty string.");
        }
        MemberWrapper removedMemberWrapper = new MemberWrapper();
        root = removeRecursive(root, name, removedMemberWrapper);
        System.out.println("Removed member: " + removedMemberWrapper.member.getName());
        return removedMemberWrapper.member;
    }

    private Node removeRecursive(Node node, String name, MemberWrapper removedMemberWrapper) {
        if (node == null) {
            return null;
        }

        int cmp = name.compareTo(node.name);
        if (cmp < 0) {
            System.out.println("Visited node: " + node.member.getName());
            node.left = removeRecursive(node.left, name, removedMemberWrapper);
        } else if (cmp > 0) {
            System.out.println("Visited node: " + node.member.getName());
            node.right = removeRecursive(node.right, name, removedMemberWrapper);
        } else {
            // Found the node to remove
            System.out.println("Removing node: " + node.member.getName());
            removedMemberWrapper.member = node.member;
            if (node.left == null) {
                return node.right;
            } else if (node.right == null) {
                return node.left;
            }

            // Node has two children, find the inorder successor
            node.member = findMin(node.right).member;
            node.name = findMin(node.right).name;
            node.right = removeRecursive(node.right, node.name, null);
        }
        return node;
    }

    private Node findMin(Node node) {
        while (node.left != null) {
            System.out.println("Visited node: " + node.member.getName());
            node = node.left;
        }
        return node;
    }


    @Override
    public void displayDB() {
        disRecDB(root);
    }

    private void disRecDB(Node node) {
        if (node == null) return;
        String name = node.name;
        String affiliation = node.member.affiliation;
        System.out.println("fullName:\t" + name + "\t" + affiliation);
        disRecDB(node.left);
        disRecDB(node.right);
    }
}

包装类:用于值传递

package partA;

public class MemberWrapper {
    Member member;
}

四.解释及测试类

APIs

First we need to build the inner class of the node and define the root node.

private Node root;

private static class Node {
    Member member;
    String name;
    Node left, right;

    Node(Member member) {
        this.member = member;
        this.name = member.getName();
        left = right = null;
    }
}

And then in the constructor, it says "Binary Search Tree"

// constructor

public MemberBST() {

    System.out.println("Binary Search Tree");

    this.root = null;

}

Next we will implement all the apis defined in the MemberBST class inheritance interface:

  1. clearDB()
public void clearDB() {

    root = null;

}

Emptying a tree simply requires setting its root node to 0, and the jvm's gc automatically frees up memory.

  1. containsName()
public boolean containsName(String name) {

    return recursionTree(root, name);

}



// if two string is same,compare() method will return 0

private boolean recursionTree(Node node, String name) {

    if (node == null) return false;

    if (node.name.compareTo(name) == 0) return true;



    return recursionTree(node.left, name) || recursionTree(node.right, name);

}

This is done using a simple depth-first traversal in the middle order traversal.

  1. get()
@Override

public Member get(String name) {

    List<String> sequence = new ArrayList<>();

    Member result = recursionGetter(root, name, sequence);

    if (result != null) {

        System.out.println("the sequence of nodes of the tree visited: " + sequence);

    }

    return result;

}



private Member recursionGetter(Node node, String name, List<String> sequence) {

    if (node == null){

        return null;

    }

    sequence.add(node.member.getName()); // Add the node to the sequence



    if (node.name.compareTo(name) == 0) {

        System.out.println("the Member name: " + node.member.getName());

        return node.member;

    }



    // recursion

    Member leftResult = recursionGetter(node.left, name, sequence);

    if (leftResult != null) {

        return leftResult;

    }

    return recursionGetter(node.right, name, sequence);

}

Since I need to return the order of access in task3, I create a variable-length array to store the locations of the accessed nodes and add them to the dynamic array whenever a node is accessed.

We also use recursion to implement the depth-first algorithm's mid-order pass to get the member of the specified name. Comparing two strings we use the compareTo() method, which converts the string to a char array and then determines whether the two strings are equal by adding the asc code. If 0 is equal, 1 means that the former is greater, and 2 means that the latter is greater.

  1. size()
public int size() {

    int cnt = 0;

    return calculator(root, cnt);

}



private int calculator(Node node, int cnt) {

    if (node == null) return cnt;

    cnt++;



    cnt = calculator(node.left, cnt);

    cnt = calculator(node.right, cnt);



    return cnt;

}

dfs is also implemented using recursion. By defining a cnt counter to record the number of nodes and objects.

isEmpty()
@Override

public boolean isEmpty() {

    return root == null;

}
Very simple no introduction.



put()
public Member put(Member member) {

    if ((member == null) || member.getName().isEmpty()) {

        throw new IllegalArgumentException("member and " +

                "member's name can not be null");

    }

    // exist?

    Member meb = get(member.getName());

    if (meb != null) {

        meb.setAffiliation(member.affiliation);

        System.out.println("the Member name: " + meb.getName());

        return meb;

    }

    if (isEmpty()) {

        root = new Node(member);

        System.out.println("Visited node: " + root.member.getName());

    } else {

        recursionAdder(root, member);

    }

    return member;

}



private void recursionAdder(Node node, Member member) {

    int gap = member.getName().compareTo(node.name);

    if (gap < 0) {

        // The new member's name comes before the current node's name, go left

        if (node.left == null) {

            node.left = new Node(member);

            System.out.println("Visited node: " + node.member.getName());

        } else {

            recursionAdder(node.left, member);

        }

    } else if (gap > 0) {

        // The new member's name comes after the current node's name, go right

        if (node.right == null) {

            node.right = new Node(member);

            System.out.println("Visited node: " + node.member.getName());

        } else {

            recursionAdder(node.right, member);

        }

    }

}
First we need to determine if a member of that name exists in the tree. Now add setAffiliation() to the Member class. Because we need to modify the operation, we need to get the member object so we can use the GET method here. If it exists, call setAffiliation() and modify the Affiliation corresponding to name.

If it is empty, create a new node to store the new member.

If it does not exist, we call the auxiliary method recursionAdder() to determine whether a member is placed in the left or right subtree by compartTo's gap.



desplyDB()
public void displayDB() {

    disRecDB(root);

}



private void disRecDB(Node node) {

    if (node == null) return;

    String name = node.name;

    String affiliation = node.member.affiliation;

    System.out.println("fullName:\t" + name + "\t" + affiliation);

    disRecDB(node.left);

    disRecDB(node.right);

}
Recursive depth traversal, just print.



remove()
public Member remove(String name) {

    if (name == null || name.isEmpty()) {

        throw new IllegalArgumentException("Name cannot be null or an empty string.");

    }

    MemberWrapper removedMemberWrapper = new MemberWrapper();

    root = removeRecursive(root, name, removedMemberWrapper);

    System.out.println("Removed member: " + removedMemberWrapper.member.getName());

    return removedMemberWrapper.member;

}



private Node removeRecursive(Node node, String name, MemberWrapper removedMemberWrapper) {

    if (node == null) {

        return null;

    }



    int cmp = name.compareTo(node.name);

    if (cmp < 0) {

        System.out.println("Visited node: " + node.member.getName());

        node.left = removeRecursive(node.left, name, removedMemberWrapper);

    } else if (cmp > 0) {

        System.out.println("Visited node: " + node.member.getName());

        node.right = removeRecursive(node.right, name, removedMemberWrapper);

    } else {

        // Found the node to remove

        System.out.println("Removing node: " + node.member.getName());

        removedMemberWrapper.member = node.member;

        if (node.left == null) {

            return node.right;

        } else if (node.right == null) {

            return node.left;

        }



        // Node has two children, find the inorder successor

        node.member = findMin(node.right).member;

        node.name = findMin(node.right).name;

        node.right = removeRecursive(node.right, node.name, null);

    }

    return node;

}



private Node findMin(Node node) {

    while (node.left != null) {

        System.out.println("Visited node: " + node.member.getName());

        node = node.left;

    }

    return node;

}

To implement value passing, we first create a wrapper class to hold the deleted member:

public class MemberWrapper {

    Member member;

}

The member with the specified name is then recursively found and deleted. If the current node is empty, it indicates that the subtree has been traversed and the target member is not found, and null is returned. If the node has no right subtree, simply return its left subtree as the new subtree (or null if there is no left subtree). Compare the name of the current node member with the name of the target, and decide whether the left subtree or the right subtree recursion based on the comparison results. If the node has no left subtree, simply return its right subtree as the new subtree (or null if there is no right subtree), for a node with two children, find the smallest node in the right subtree (via the findMin method), replace the current node with this node, and then recursively remove the smallest node.

Testcode

Download Junit for unit testing using Maven.

(In Java, we generally do not use assertion types directly in our code, we use more if conditions, and assertion types are required to be used in test classes as much as possible.)

/*

  Insertion structure:

    Alice

   /    \

Adam    Bob

       /   \

   Barbara  Charlie

           /     \

         null    null



   */

  private MemberBST memberBST;

  private Member member1;

  private Member member2;

  private Member member3;

  private Member member4;



  @Before

  public void setUp() {

      memberBST = new MemberBST();

      member1 = new Member("Alice", "Company A");

      member2 = new Member("Bob", "Company B");

      member3 = new Member("Charlie", "Company C");

      member4 = new Member("Adam", "Company D");



      memberBST.put(member1);

      memberBST.put(member2);

      memberBST.put(member3);

      memberBST.put(member4);

  }

First, insert the test data. See comments for the structure.

@Override

public boolean equals(Object o) {

    if (this == o) return true;

    if (o == null || getClass() != o.getClass()) return false;

    Member member = (Member) o;

    return Objects.equals(fullName, member.fullName) && Objects.equals(affiliation, member.affiliation);

}



@Override

public int hashCode() {

    return Objects.hash(fullName, affiliation);

}

Note that we need to override the equals and hashcode methods in the Member class because we need a time value comparison rather than a memory address comparison.

The unit test code is as follows:

 

 

 

 

 

 

 

 

 

 

Then we can allow the main use case to be given in actual code:

Display:

Apparently it's allowed.

Analyse

  1. put
    1. Average case: O(log n), because each insertion attempts to place a new node in the proper place in the tree so that the tree is balanced.
    2. Best case: O(1), when the tree is empty or a new node is always inserted as the last node (this can happen with ordered inserts, but is uncommon).
    3. Worst case: O(n), if the tree is extremely unbalanced (degenerates into a linked list), each insertion may require traversing the entire tree.
  2. get & containsName
    1. Average case: O(log n), similar to insertion because the search follows a path from root to leaf.
    2. Best case: O(1), if the target node happens to be the root node.
    3. Worst case: O(n), when the tree degenerates into a linked list.
  3. Remove
    1. Average case: O(log n), the node needs to be found, and then three cases (no child, one child, two children) are processed, most of the operations are concentrated in a small part of the tree.
    2. Best case: O(1), delete the leaf node.
    3. Worst case: O(n), also when the tree is reduced to a linked list, it takes linear time to find the node.
  4. size & displayDB

The recursive implementation results in a time complexity of O(n) because each node needs to be traversed

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

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

相关文章

linux系统硬盘读写慢的排查方法

如果服务器硬盘读写慢&#xff0c;可能会导致处理性能降低&#xff0c;用户响应慢。因此及时排除故障至关重要。下面是硬盘读写慢的排查思路。 1、top命令查看硬盘是否繁忙。 2、找出占用硬盘带宽高的进程。 通过iotop命令进行查看&#xff0c;iotop命令是用于展示硬盘读写操作…

高中数学:平面向量-数乘运算

一、定义 顾名思义 向量的数乘运算&#xff0c;就是数量与向量相乘的运算 λ a → \mathop{a}\limits ^{\rightarrow} a→&#xff0c;λ∈R 二、λ a → \mathop{a}\limits ^{\rightarrow} a→的性质 1、长度 |λ|*| a → \mathop{a}\limits ^{\rightarrow} a→| |λ a …

设计模式6——单例模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用&#xff0c;主要是下面的UML图可以起到大作用&#xff0c;在你学习过一遍以后可能会遗忘&#xff0c;忘记了不要紧&#xff0c;只要看一眼UML图就能想起来了。同时也请大家多多指教。 单例模式&#xff08;Singleto…

python科研数据可视化之折线图

例如 &#xff1a; 下面的配色表画出的图很好看。选择喜欢的颜色&#xff0c;找到代码中颜色部分进行修改即可。 代码部分已经有详细的注释&#xff0c;就不一一解释了。另外&#xff0c;如果想要坐标轴从设定的值开始就把下面代码中的范围xlim&#xff0c;ylim进行注释。 imp…

Goby 漏洞发布|Sonatype Nexus Repository Manager 文件读取漏洞(CVE-2024-4956)

漏洞名称&#xff1a;Sonatype Nexus Repository Manager 文件读取漏洞&#xff08;CVE-2024-4956&#xff09; English Name&#xff1a; Sonatype Nexus Repository Manager File Read Vulnerability(CVE-2024-4956) CVSS core: 7.5 影响资产数&#xff1a;93784 漏洞描述…

QT--TCP网络通讯工具编写记录

QT–TCP网络通讯工具编写记录 文章目录 QT--TCP网络通讯工具编写记录前言演示如下&#xff1a;一、服务端项目文件&#xff1a;【1.1】server_tcp.h 服务端声明文件【1.2】thread_1.h 线程处理声明文件【1.3】main.cpp 执行源文件【1.4】server_tcp.cpp 服务端逻辑实现源文件【…

开箱测评!吸猫毛除味神器,希喂FreAir Lite宠物空气净化器实测

掉毛季又来了&#xff0c;猫咪的毛发满天飞&#xff0c;怎么办&#xff1f;我家掉毛怪一到季节就开始掉老多毛&#xff0c;关键还喜欢在家里打架跑酷&#xff01;天上地下都是毛&#xff01;为了减少家里空气中浮毛&#xff0c;你做过那些努力呢&#xff1f;最近猫掉毛掉的&…

02-结构型设计模式(共7种)

上一篇&#xff1a;01-创建型设计模式(共6种) 1. Adapter(适配器模式) 适配器模式是一种结构型设计模式&#xff0c;它允许将一个类的接口转换成客户端所期望的另一个接口。这种模式通常用于解决接口不兼容的情况&#xff0c;使得原本由于接口不匹配而无法工作的类可以一起工作…

20232810 2023-2024-2 《网络攻防实践》实验十

1.实践内容 1.1SEED SQL注入攻击与防御实验 &#xff08;1&#xff09;使用数据库熟悉SQL查询&#xff1a; 我们已经创建了一个名为Users的数据库&#xff0c;其中包含一个名为creditential的表。该表存储了每个员工的个人信息&#xff08;例如&#xff0c;eid&#xff0c;密…

DOS学习-目录与文件应用操作经典案例-rd

欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一.前言 二.使用 三.案例 一.前言 rd命令&#xff0c;全称Remove Directory&#xff0c;是DOS操作系统中的一个重要命令&#xff0c;用于删除指定的目录及其所有内容。 二.使用 命令格式…

Kubeblocks系列2-redis尝试之出师未捷身先死

背景&#xff1a; 上一节&#xff0c;完成了Kubeblocks系列1-安装。现在就想拿一个简单的应用测试一下kubeblocks这个所谓的神器是否好用&#xff0c;是否可以应用与生产&#xff01; Kubeblocks系列2-redis尝试 参照官方文档&#xff1a;创建并连接到 Redis 集群 确保 Red…

ORACLE 资源管理参数与等待事件resmgr:cpu quantum

RESOURCE_MANAGER_PLAN 先来看下参数的含义 官网链接&#xff1a;RESOURCE_MANAGER_PLAN (oracle.com) 意思翻译过来这个参数用于资源计划。后边的看完也不是很明白具体的作用 于是参考了以下文章 Oracle 参数 RESOURCE_MANAGER_PLAN 官方解释&#xff0c;作用&#xff0c;…

RH850F1KM-S4-100Pin_ R7F7016453AFP MCAL Gpt 配置

1、Gpt组件包含的子配置项 GptDriverConfigurationGptDemEventParameterRefsGptConfigurationOfOptApiServicesGptChannelConfigSet2、GptDriverConfiguration 2.1、GptAlreadyInitDetCheck 该参数启用/禁用Gpt_Init API中的GPT_E_ALREADY_INITIALIZED Det检查。 true:开启Gpt_…

【计算机视觉(2)】

基于Python的OpenCV基础入门——视频的处理 视频OpenCV视频处理操作&#xff1a;创建视频对象判断视频是否成功初始化读取视频帧获取视频特征设置视频参数声明编码器保存视频释放视频对象 视频处理基本操作的代码实现&#xff1a; 视频 视频是由一系列连续的图像帧组成的。每一…

地平线-旭日X3派(RDK X3)上手基本操作

0. 环境 - win10笔记本 - RDK X3 1.0&#xff08;地平线旭日X3派&#xff0c;后来改名为代号RDK X3&#xff09; 1. 下载资料 https://developer.horizon.ai/resource 主要下载镜像 http://sunrise.horizon.cc/downloads/os_images/2.1.0/release/ 下载得到了 ubuntu-prei…

c# 将数据库连接字符串写到配置文件中,及获取

考虑到代码的安全性&#xff0c;已经修改起来的方便性&#xff0c;我们常常不会将数据库连接字符串直接放在代码中&#xff0c;而是将这个字符串放到一个App.config配置文件中&#xff0c;赋值给一个变量&#xff0c;然后再在代码中引用这个变量。 具体做法如下: ①展开项目名称…

星火大模型:服务升级,免费开放!

2023年9月5日&#xff0c;讯飞星火正式开放&#xff01;仅仅一个半月&#xff0c;讯飞星火在1024开发者节就实现用户规模突破1200万&#xff0c;成为人们获取知识、学习知识的“超级助手”&#xff0c;成为解放生产力、释放想象力的“超级杠杆”。从商业文案、软件代码、创意方…

BCD编码(8421)介绍

概念 BCD (Binary-Coded Decimal) 是一种二进制的数字编码形式&#xff0c;其特点每个十进制数位用4个二进制位来表示。 在网络IO中&#xff0c;你传输一个数字类型最少需要一字节&#xff0c;传输两个数字类型最少需要两字节&#xff0c;但是当你使用BCD编码后传输&#xff…

4款卸载软件测评,流氓软件克星!

正常卸载软件的方法&#xff0c;打开控制面板&#xff0c;点击程序-卸载程序&#xff0c;然后再选中软件卸载&#xff0c;但是这样往往注册表的内容还依然存在&#xff0c;今天分享4款卸载软件&#xff0c;都是专业卸载神器&#xff0c;简单说下我测评感受。 HiBit Uninstaller…

半导体测试基础 - AC 参数测试

AC 测试确保 DUT 的时特性序满足其规格需求。 基本 AC 参数 建立时间(Setup Time) 建立时间指的是在参考信号(图中为 WE)发生变化(取中间值 1.5V)前,为了确保能被正确读取,数据(图中为 DATA IN)必须提前保持稳定不变的最短时间。在最小建立时间之前,数据可以随意变…