数据结构学习笔记(七)搜索结构

文章目录

  • 1. 前言
  • 2. 概念
  • 3 静态搜索结构
    • 3.1 静态搜索表
    • 3.2 顺序搜索表
      • 3.2.1 基于有序顺序表和顺序搜索和折半搜索
  • 4 二叉搜索树
    • 4.1 搜索二叉树的类定义
    • 4.2 搜索二叉树的搜索
    • 4.3 搜索二叉树的插入
    • 4.4 搜索二叉树的删除
  • 5 AVL树
    • 5.1 平衡化旋转
      • 5.1.1 右旋:LL型状态
      • 5.1.2 左旋:RR型状态
      • 5.1.3 右旋(LL)的例子
      • 5.1.4 先左旋再右旋(LR)的操作
      • 5.1.5 先右旋再左旋(RL)的操作
      • 5.1.6 RL操作的例子
      • 5.1.7 代码实现
    • 5.2 AVL树的插入
    • 5.3 AVL树的删除
  • 6 伸展树
    • 6.1 插入
    • 6.2 查找
      • 6.3 删除
  • 7 红黑树
    • 7.1 红黑树搜索
    • 7.2 插入和删除


1. 前言

本系列笔记基于 清华大学出版社的《数据结构:用面向对象方法与C++语言描述》第二版进行学习。

2. 概念

使用基于关键码的搜索,搜索结果应该是唯一的。使用基于属性的搜索方法,搜索结果可能不唯一。
搜索的环境有两种,静态环境和动态环境。区别在于插入和删除后搜索结构会不会变化。
衡量搜索的时间效率的标准是:
在搜索过程中关键码的平均比较次数或平均读写磁盘次数,成为平均搜索长度ASL。

3 静态搜索结构

3.1 静态搜索表

最简单的基于数组的数据表类。

#include <iostream>
#include<assert.h>
using namespace std;
const int defaultSize = 100;
class dataList;

class dataNode {
    friend class dataList;
public:
    dataNode(const int x = 99):key(x),data(0){}
    int getKey() const { return key; }
    void setKey(int k) { key = k; }
private:
    int key;                  // 关键码
    int data;
};

class dataList {
public:
    dataList(int sz = defaultSize) :ArraySize(sz), CurrentSize(0) {
        Element = new dataNode[sz];
        assert(Element != NULL);
    }
    dataList(dataList& R);
    virtual ~dataList() { delete[]Element; }                    
    virtual int Length() { return CurrentSize; }               
    virtual int getKey(int i)const {
    // 提取第i个元素值(从1开始)
        assert(i > 0 || i <= CurrentSize);
        return Element[i - 1].key;
    }         
    virtual void setKey(int x, int i) {         // 修改第i个元素的值
        assert(i > 0 || i <= CurrentSize);
        Element[i - 1].key = x;
    }
    virtual int SeqSearch(const int x) const;       // 搜索
    virtual bool Insert(int& e1);                       // 插入
    virtual bool Remove(const int x, int& e1);      // 删除
    friend ostream& operator<<(ostream& out, const dataList& OutList);
    friend ostream& operator>>(istream in, dataList& InList);
protected:
    dataNode* Element;
    int ArraySize;
    int CurrentSize;
};

class searchList :public dataList {
public:
    searchList(int sz = defaultSize) :dataList(sz){}
    virtual int SeqSearch(const int x)const;
};

int main()
{
    std::cout << "Hello World!\n";
}

bool dataList::Insert(int& e1)
{
    if (CurrentSize == ArraySize) return false;   // 表满,无法插入
    Element[CurrentSize] = e1;
    CurrentSize++;
    return true;
}

bool dataList::Remove(const int x, int& e1)
{
    if (CurrentSize == 0)return false;
    int i;
    for (i = 0; i < CurrentSize && Element[i].key != x; i++);
    if (i == CurrentSize) return false;
    e1 = Element[i].data;
    Element[i] = Element[CurrentSize - 1];
    CurrentSize--; return true;
}

ostream& operator<<(ostream& out, const dataList& OutList)
{
    cout << "Array Contents:\n";
    for (int i = 1; i < OutList.CurrentSize; i++) {
        cout << OutList.CurrentSize; 
        i++;
    }
    cout << endl;
    cout << "Array Current Size:" << OutList.CurrentSize << endl;
    return out;
}

ostream& operator>>(istream in, dataList& InList)
{
    cout << "Enter array Current Size:" << endl;
    in >> InList.CurrentSize;
    cout << "Enter array Elements:\n";
    for (int i = 1; i <= InList.CurrentSize; i++) {
        cout << "Element" << i << ":";
        in >> InList.Element[i - 1];
    }
    return in;
}

编译不过,因为Elements中没有设置接触到数据的函数,可以自行添加

3.2 顺序搜索表

int searchList::SeqSearch1(const int x, int loc) const
{
    if (loc > CurrentSize) return 0;
    else if (Element[loc - 1].key == x) return loc;
    else return SeqSearch1(x, loc + 1);
}

3.2.1 基于有序顺序表和顺序搜索和折半搜索

①顺序搜索

class SortedList : public searchList {
public:
    SortedList(int sz=100):searchList(sz){}
    ~SortedList(){}
    int SequentSearch(const int x)const;            // 顺序搜索
    int BinarySearch(const int x)const;                // 折半搜索
    bool Insert(const int& e1);                            // 插入
    int Begin() { return (CurrentSize == 0) ? 0 : 1; }      // 定位第一个
    int Next(int i) { return(i >= 1 && i <= CurrentSize) ? i + 1 : 0; } // 定位下一个
};

int SortedList::SequentSearch(const int x) const
{
    for (int i = 1; i <= CurrentSize; i++)
        if (Element[i - 1].key == x) return i;            // 成功,停止搜索
        else if (Element[i - 1].key > x)break;          // 不成功,停止搜索
    return 0;
}

②折半搜索
折半搜索又称二分搜索法
在这里插入图片描述
在这里插入图片描述
非递归算法

int SortedList::BinarySearch(const int x) const
{
    // 非递归算法
    int high = CurrentSize - 1;
    int low = 0;
    int mid;

    while (low <=high)          // 如果没有,最后搜索的一次是low<=high
    {
        mid = (low + high) / 2;
        if (x > Element[mid].key) low = mid + 1;            // 把中间的元素的后一位变成low
        else if (x < Element[mid].key) high = mid - 1;      // 把中间元素的前一位变成high
        else return mid + 1;
    }

    return 0;
}


递归算法

int SortedList::BinarySearch1(const int x, int low, int high) const
{
    int mid = 0;
    if (low <= high) {
        mid = (low + high) / 2;
        if (x > Element[mid - 1].key)
            mid = BinarySearch1(x, mid + 1, high);          
        else if (x < Element[mid - 1].key)
            mid = BinarySearch1(x, low, mid - 1);
    }
    return mid;
}

③插入算法

void SortedList::Insert(const dataNode& e1)
{
    assert(CurrentSize == ArraySize);
    int i = 1;
    while (i <= CurrentSize && Element[i - 1].key <= e1.key)i++;            // 找到小于插入的结点的最大的结点
    for (int j = CurrentSize; j >= i; j--) Element[j] = Element[j - 1];          // 前面的赋值给另一个
    Element[i - 1] = e1;
    CurrentSize ++;
}

4 二叉搜索树

在这里插入图片描述
简单来说,就是如果找到二叉树的中序遍历,他的中序遍历一定是从小到大排序的
在这里插入图片描述
如上图,其中序遍历均位123

4.1 搜索二叉树的类定义

struct BSTNode
{
    int data;               // 二叉树节点类
    BSTNode* left, * right; // 左右子女
    BSTNode():left(NULL),right(NULL){}
    BSTNode(const int d, BSTNode* L = NULL, BSTNode*R =NULL):data(d),left(L),right(R){}
    ~BSTNode(){}
    void SetData(int d) { data = d; }
    int getData() { return data; }
};

class BST {
public:
    BST() :root(NULL) {}                                                
    BST(int Value);                               
    ~BST() {};
    bool Search(const int x) {
        return (search(x, root) != NULL) ? true : false;
    }
    BST& oprator = (const BST & R);         // 赋值
    void makeEmpty() { makeEmpty(root); root = NULL; }
    void PrintTree()const { PrintTree(root); }
    int Min() { return Min(root)->data; }
    int Max() { return Max(root)->data; }
    bool Insert(const int& e1) { return Insert(e1, root); }
    bool Remove(const int x) { return Remove(x, root); }

private:
    BSTNode* root;
    int RefValue;               // 停止标志
    BSTNode* search(const int x, BSTNode* ptr);         // 搜索
    void makeEmpty(BSTNode*& ptr);                          // 置空
    void PrintTree(BSTNode* ptr)const;                          // 打印
    BSTNode* Copy(const BSTNode* ptr);                      // 复制
    BSTNode* Min(BSTNode* ptr)const;                                  // 求最小
    BSTNode* Max(BSTNode* ptr)const;                                 // 求最大
    bool Insert(const int& e1, BSTNode*& ptr);                      // 递归插入
    bool Remove(const int x, BSTNode*& ptr);                        // 删除
};

4.2 搜索二叉树的搜索

在这里插入图片描述
超级好理解

BSTNode* BST::search(const int x, BSTNode* ptr)
{
    if (ptr == NULL) return NULL;
    else if (x < ptr->data) return search(x, ptr->left);
    else if (x > ptr->data) return search(x, ptr->right);
    else return ptr;
}

4.3 搜索二叉树的插入

在这里插入图片描述

bool BST::Insert(const int& e1, BSTNode*& ptr)
{
    if (ptr == NULL) {
        ptr = new BSTNode(e1);
        if (ptr = NULL) { cout << "out of space" << endl; exit(1); }
    }
    else if (e1 < ptr->data) Insert(e1, ptr->left);         // 比结点小存左边
    else if (e1 > ptr->data)Insert(e1, ptr->right);   // 比节点小存右边
    else return false;              
}

4.4 搜索二叉树的删除

在这里插入图片描述

bool BST::Remove(const int x, BSTNode*& ptr)
{
    BSTNode* temp;
    if (ptr != NULL) {
        if (x < ptr->data) Remove(x, ptr->left);            // 左子树执行删除
        else if (x > ptr->data) Remove(x, ptr->right);    // 在右子树执行删除
        else if (ptr->left != NULL && ptr->right != NULL) { // 有两个子女节点
            temp = ptr->right;                                              // 右子树搜寻中序的第一个结点
            while (temp->left != NULL) temp = temp->left;
            ptr->data = temp->data;     // 用该节点数据代替根节点数据
            Remove(ptr->data, ptr->right);
        }
        else {      // 只有一个子女结点(左子结点或右子结点)           这部分是为了链接删除部分缺掉的那条线
            temp = ptr;
            if (ptr->left == NULL) ptr = ptr->right;
            else ptr = ptr->left;
            delete temp;
            return true;
        }
        }
    return false;
    }

5 AVL树

任一结点的右子树的高度减去左子树的高度差只能为-1,0,1

在这里插入图片描述

5.1 平衡化旋转

使不平衡的二叉搜索树变得平衡
先说插入
这里有四种情况

5.1.1 右旋:LL型状态

在这里插入图片描述
就是插入根节点的子结点的左子结点,
右旋相当于把树往顺时针旋转以下,把B点做成根结点,再把B结点的右子结点变成原根节点的左子节点,

旋转后变成:
在这里插入图片描述

5.1.2 左旋:RR型状态

左旋和右旋差不多,就是插入了根节点的右子结点的右子树中。
在这里插入图片描述
左旋相当于将整个树逆时针旋转了一下,将C点置为根结点,然后将A点作为C点的左子树,把原来的左子树3作为原根节点的右子树
在这里插入图片描述

5.1.3 右旋(LL)的例子

在这里插入图片描述
本次是插入0到原来的平衡树中,如图,属于LL情况,所以进行右旋操作。
找到不平衡的根结点4。所以我们要调整的树就是
在这里插入图片描述
将原有的左子树,以2为根节点的树往上提,作为这棵树的新根节点,并把原有根节点4作为2的右子树,把2的原右子变为原根节点4的左子树
在这里插入图片描述
再把2作为原来根节点4,进行连接
在这里插入图片描述

5.1.4 先左旋再右旋(LR)的操作

在这里插入图片描述

元素落到56都是一样的处理,把
D转换成新的根结点,把原有不平衡树的根节点A的左子女结点作为D的左子女结点,根节点A作为D的右子女结点。并把D的左子树当作B的右子树,把D的右子树当作A的左子树。
在这里插入图片描述

5.1.5 先右旋再左旋(RL)的操作

在这里插入图片描述

插入56所作的操作都一样,原理与LR差不多,把D作为新的根节点,把不平衡树的根节点A作为D的左子树,A的右子女结点C作为D的右子树。并把D的左子树转换成A的右子树,D的右子树转换为C的左子树。
在这里插入图片描述

5.1.6 RL操作的例子

在这里插入图片描述
把4当作新父结点,将不平衡树的根节点2作为4的左子树,根节点的右结点5作为4的右子树。把4的左子树赋给2作为其右子女结点。

在这里插入图片描述
结果
在这里插入图片描述

5.1.7 代码实现

void AVLTree::RotateL(AVLNode*& ptr)
{
    // 右子树高RR型状态
    AVLNode* subL = ptr;        // 要旋转的结点,即不平衡的树的根结点
    ptr = subL->right;              // 原根节点的右结点
    subL->right = ptr->left;     // 原根子树的右子女转化成其右结点的左子树
    ptr->left = subL;                 // 把原根节点作为原根节点右结点的左子树,此时ptr为新根节点
    ptr->bf = subL->bf = 0;

}

void AVLTree::RotateR(AVLNode*& ptr)
{
    // 左子树高LL型状态
    AVLNode* subR = ptr;
    ptr = subR->left;
    subR->left = ptr->right;
    ptr->right = subR;
    ptr->bf = subR->bf = 0;
}
void AVLTree::RotateRL(AVLNode*& ptr)
{
    AVLNode* subL = ptr;                // 最后根节点的左子树
    AVLNode* subR = subL->right;    // 最后根节点的右子树
    ptr = subR->left;                           
    subR->left = ptr->right;                // subR的左子树变为其左子女节点的左子女节点
    ptr->right = subR;                          // 新根节点的右子女结点变为最终右子女结点
    if (ptr->bf >= 0) subR->bf = 0;
    else subR->bf = 1;
    subL->right = ptr->left;                // subL的右子女变为新根节点的左子女结点
    ptr->left = subL;                           // 新根结点的变为最终的左子女结点
    if (ptr->bf == 1) subL->bf = -1;
    else subL->bf = 0;
    ptr->bf = 0;
}

void AVLTree::RotateLR(AVLNode*& ptr)
{
    AVLNode* subR = ptr;
    AVLNode* subL = subR->left;
    ptr = subL->right;
    subL->right = ptr->left;
    ptr->left = subL;
    if (ptr->bf <= 0) subL->bf = 0;
    else subL->bf = -1;
    subR->left = ptr->right;
    ptr->right = subR;
    if (ptr->bf = -1) subR->bf = 1;
    else subR->bf = 0;
    ptr->bf = 0;
}

5.2 AVL树的插入

沿着其插入路线查各结点的平衡度
各结点会有三种情况
①bf = 0,不需要处理,结束平衡化
②bf = 1,不需要处理,继续回溯
③bf = 2,bf = 2,右子树高,需要结合右子女q的bf做处理
1)q的bf = 1,执行左单旋转,插入位置为RR
2)q的bf=-1,执行先右后左旋转,插入位置为RL
bf=-2,左子树高,需要结合左子女q的bf做处理
1)q的bf=1,执行右单旋转,插入位置为LL
2) q的bf=-1,执行先右旋后左旋,插入位置为LR

bool AVLTree::Insert(AVLNode*& ptr, int& e1)
{
    AVLNode* pr = NULL;
    AVLNode* p = ptr;
    AVLNode* q;
    int d;

    Stack st;
    while (p!=NULL)
    {
        if (e1 == p->data) return false;        // 找到了e1的结点,不插入
        pr = p;
        st.push(pr);                                        // 用栈记录查找路径,并找到插入的父结点pr
        if (e1 < p->data) p = p->left;
        else p = p->right;
    }

    p = new AVLNode(e1);
    if (p == NULL) { cout << "error when allocate memory!"; exit(1); }
    if (pr == NULL) { ptr = p; return true; }
    if (e1 < pr->data) pr->left = p;
    else pr->right = p;                             // 新结点插入
    while (st.Isempty() == false) {         // 重新平衡化
        st.Pop(pr);                                 // 调查父结点的平衡因子 
        if (p == pr->left) pr->bf--;        // 如果插入左边,则平衡因子-1
        else pr->bf++;                          // 插入右边则+1,平衡因子高度右边-左边
        if (pr->bf == 0) break;              // 第一种情况,平衡退出
        if (pr->bf == 1 || pr->bf == -1)
            p = pr;                                     // 第二种情况,继续向上搜寻
        else {                                              // 第三种情况,|bf| =2;
            d = (pr->bf < 0) ? -1 : 1;          // 区别单双旋
            if (p->bf == d) {                       // 两节点的平衡因子同号,单旋转
                if (d == -1) RotateR(pr);       // bf ==-1
                else RotateL(pr);                   // bf =1
            }
            else {
                if (d == -1) RotateLR(pr);
                else RotateRL(pr);
            }
            break;

        }
        if (st.IsEmpty() == true) ptr = pr;     // 调整到树的根节点
        else {
            st.getTop(q);
            if (q->data > pr->data) p->left = pr;
            else q->right = pr;
        }

    }

    return true;
}

这是>>和<<的重载:

istream& operator>>(istream in, AVLTree& Tree)
{
    int item;
    cout << "Construct AVL tree:\n";
    cout << "Input Data(end with" << Tree.RefValue << "):";
    in >> item;
    while (item != Tree.RefValue) {
        Tree.Insert(item);
        cout << "Input Data(end with" << Tree.RefValue << "):";
        in >> item;
    }
    return in;
}

ostream& operator<<(ostream& out, const AVLTree& Tree)
{
    out << "Inorder Traversal of AVL tree.\n";
    Tree.Traverse(Tree.root, out);              // 以中序次序输出个各节点的数据
    out << endl;
    return out;
}

在这里插入图片描述
看懂这个基本就学会了插入了

5.3 AVL树的删除

AVL树的删除算法与二叉搜索树类似,删除后如果破坏平衡性质,还需要做旋转
(1)如果被删结点p有两个子女,p的中序次序下找到直接前驱q,把q的内容传给p,把结点q当作被删结点p,他是只有一个子女的结点,此时看第二种情况
(2)如果被删结点p最多只有一个子女q。可以当p的父结点pr中原来指向p的指针改到q,如果结点p没有子女,p父结点pr的相应指针置位NULL。将原来的结点pr为根的子树的高度-1,并沿pr通向根的路径考量一路上各个结点的影响。
考查结点q的父结点pr。如果q是pr的左子女,则因子bf+1,否则bf-1
此时有三种情况
【1】bf的原来的平衡因子为0,则不需要调整了,结束重新平衡
在这里插入图片描述

【2】bf不为0,需要考察结点pr的父结点的平衡状态,
在这里插入图片描述
【3】需要平衡化
考察父结点pr的更高的子树的根为q(未被缩短的树),根据q的平衡因子,有三种操作
①如果q的平衡因子为0,执行一个单旋(未被缩短的树,结束后可以结束平衡的过程
在这里插入图片描述
②如果q的平衡因子与pr的平衡因子正负号相同,则执行一个单旋来恢复,结束后需要沿上继续评估平衡状态,相当LL型和RR型
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
③如果pr与q的平衡因子正负号相反,则需要执行双旋q,相当于LR和RL型,同时继续向上评估
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

bool AVLTree::Remove(AVLNode*& ptr, int x, int& e1)
{
    // 删除关键码为x的结点
    AVLNode* pr = NULL;
    AVLNode *p = ptr;
    AVLNode* q;
    AVLNode* ppr;
    int d;
    int dd = 0;

    Stack* st;

    while (p != NULL) {
        // 寻找删除位置
        if (x == p->data) break;
        pr = p;
        st.push(pr);
        if (x < p->data) p = p->left;
        else p = p->right;
    }
    if (p == NULL) return false;            // 未找到,删除
    if (p->left != NULL && p->right != NULL) {  // 有两各子女的情况
        pr = p;
        st.push(pr);
        q = p->left;                // 再p左子树找到中序遍历直接前驱
        while (q->right != NULL) {
            pr = q;
            st.push(pr); 
            q = q->right;      
        }
        p->data = q->data;                  // 用q的值填补p
        p = q;                                      // 被删结点转为q,此时是只有一个子女结点q的情况
    }


    if (p->left != NULL) q = p->left;       // 被删结点只有一个子女
    else q = p->right;                              // 找到这个子女
    if (pr == NULL) ptr = q;    // 被删结点为根节点
    else {                                  // 被删结点不是根节点
        if (pr->left == p) pr->left = q;        // 把父结点连接到被删结点的子女结点
        else pr->right = q;
        while (st.IsEmpty()== false)            // 重新平衡化
        {
            st.Pop(pr);             
            if (pr->right == q) pr->bf--;       // 调整父结点的平衡因子
            else pr->bf++;
            if (st.IsEmpty() == false) {
                st.getTop(ppr);
                dd = (ppr->left == pr) ? -1 : 1;        // 旋转后和上层连接方向
            }
            else dd = 0;                                          // 旋转后不与上层连接
            if (pr->bf == 1 || pr->bf == -1) break;     // 不需要旋转,直接退出
            if (pr->bf != 0) {
                if (pr->bf < 0) { d = -1; q = pr->left; }
                else { d = 1; q = pr->right; }
                if (q->bf == 0) {
                    if (d == -1) {
                        RotateR(pr);
                        pr->bf = 1;
                        pr->left->bf = -1;
                    }
                    else {
                        RotateL(pr);
                        pr->bf = -1;
                        pr->right->bf = 1;
                    }
                    break;

                }
                if (q->bf == d) {
                    if (d == -1) RotateR(pr);
                    else RotateL(pr);
                }
                else {
                    if (d == -1) RotateLR(pr);
                    else RotateRL(pr);
                }
                if (dd == -1) ppr->left = pr;
                else if (dd == 1) ppr->right = pr;

            }
            q = pr;


        }
        if (st.IsEmpty() == true) ptr = pr;


    }

    delete p;

    return true;
}

不懂这段代码,真的很痛苦看的我

6 伸展树

每次插入结点,所有结点都要调整到根结点。
伸展树

6.1 插入

插入位置为根的左节点,右旋
插入位置为根的右结点,左旋
最左边LL情况,对中间结点进行右旋,在对结点进行右旋,直到变成根节点
最右边RR情况,对中间结点进行左旋,在对结点进行左旋,直到变成根节点
LR情况,中间结点先左旋后右旋,再对结点左旋右旋,直到变为根节点
RL情况,中间结点先右旋后左旋,再对结点右旋左旋,直到变为根节点

6.2 查找

插入和查找操作,查找后把查找到的结点变为根节点,情况跟插入类似

6.3 删除

和二叉搜索树相同,但需要把被删除结点的父结点展开到根节点。

7 红黑树

在这里插入图片描述
1)外部结点是黑色(空指针们
2)没有两个连续结点是红色,(可以两个连续结点是黑色
3)根到外部节点的路径上都有相同的黑色结点
在这里插入图片描述
也可以从指针看
在这里插入图片描述

在这里插入图片描述

7.1 红黑树搜索

和二叉搜索树完全相同

7.2 插入和删除

这个书上标**了,我这边先不学,看了下内容挺多的,后面再补

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

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

相关文章

专业、好用的跨网文件摆渡产品,需要具备哪些功能特性?

为了确保内部核心资产的安全性&#xff0c;很多企业和机构都会选择将网络进行隔离划分&#xff0c;比如内外网隔离&#xff0c;办公网、研发网隔离等。但网络隔离后&#xff0c;在日常工作中&#xff0c;仍存在用户需求把文件数据从内网到外网&#xff0c;从办公网到研发网终端…

中学老师招聘条件和要求

如果想当老师&#xff0c;这些条件和要求你一定得知道&#xff0c;那就是中学老师的招聘条件和要求&#xff01;想成为一名优秀的中学老师吗&#xff1f; 1学历要求&#xff1a;本科及以上学历&#xff0c;师范类专业优先考虑哦&#xff01;毕竟专业的事还是要交给专业的人来做…

JVM-10-类加载

Java虚拟机把描述类的数据从Class文件加载到内存&#xff0c;并对数据进行校验、转换解析和初始化&#xff0c;最终形成可以被虚拟机直接使用的Java类型&#xff0c;这个过程被称作虚拟机的类加载机制。 一个类型从被加载到虚拟机内存中开始&#xff0c;到卸载出内存为止&#…

论文笔记:Bilinear Attention Networks

更精简的论文学习笔记 1、摘要 多模态学习中的注意力网络提供了一种选择性地利用给定视觉信息的有效方法。然而&#xff0c;学习每一对多模态输入通道的注意力分布的计算成本是非常昂贵的。为了解决这个问题&#xff0c;共同注意力为每个模态建立了两个独立的注意分布&#x…

Flutter ios 使用ListView 。滚动时 AppBar 改变颜色问题

在Ios 中 列表滚动条向下滚动一段距离后 会导致 AppBar 颜色改变 可以给 AppBar 或者 AppBarTheme。 scrolledUnderElevation: 0.0 属性 全局&#xff1a; MaterialApp(theme: ThemeData(appBarTheme: AppBarTheme(scrolledUnderElevation: 0.0)) ) 局部&#xff1a; App…

wms管理软件在电子行业的应用

wms管理软件在电子行业的应用主要体现在以下几个方面&#xff1a; 优化仓库管理流程&#xff1a;通过WMS系统&#xff0c;电子企业可以优化仓库管理流程&#xff0c;提高仓储效率和准确率&#xff0c;提升客户满意度。 实现精细化管理&#xff1a;WMS系统可以帮助电子企业实现精…

word下划线空格不延长对齐

空格下划线不延长 文件-》选项-》常规与保存-》勾选“为尾部空格添加下划线”-》确定 下划线对齐 首行&#xff1a;把第一行的下划线调到满意位置&#xff0c;按tab键下面的行&#xff1a;删到比首行短一丢丢&#xff0c;按tab键

计算机组成原理-硬布线控制器与微程序控制器

文章目录 内容回顾总览硬布线控制器硬布线控制器的设计分析每个阶段的微操作序列安排微操作时序的原则安排微操作时序-取指周期安排微操作时序-间址周期安排微操作时序-执行周期组合逻辑设计小结 微程序控制器微程序控制器的设计思路微程序控制器的基本结构微程序控制器的工作原…

Jmeter基础和概念(超详细整理)

JMeter 介绍&#xff1a; 一个非常优秀的开源的性能测试工具。 优点&#xff1a;你用着用着就会发现它的重多优点&#xff0c;当然不足点也会呈现出来。 从性能工具的原理划分&#xff1a; Jmeter工具和其他性能工具在原理上完全一致&#xff0c;工具包含4个部分&#xff1a…

ChatGPT凉了,打工人的饭碗保住了

您好&#xff01;我是YUAN哥。 如果你问我今年上半年印象最深的事物是什么&#xff1f; YUAN的回答绝对是&#xff1a;ChatGPT。 5天内&#xff0c;ChatGPT用户超过了100万。两个月内&#xff0c;ChatGPT的月活用户超过了1亿。 作为历史上增长最快的应用程序&#xff0c;Cha…

最新鸿蒙HarmonyOS 使用Progress、Toggle开发一个接单界面

Progress 进度条组件&#xff0c;用于显示内容加载或操作处理等进度。 接口 Progress(options: {value: number, total?: number, type?: ProgressType}) Toggle组件提供勾选框样式、状态按钮样式及开关样式。 接口 Toggle(options: { type: ToggleType, isOn?: boolean …

系统培训方案(直接套用)

1. 培训概述 2. 培训目的 3. 培训对象及要求 3.1. 培训对象 3.2. 培训人员基本要求 4. 培训方式 5. 培训内容 6. 培训讲师 7. 培训教材 8. 培训质量保证 8.1. 用户培训确认报告 8.2. 培训疑问解答 软件相关资料全获取&#xff1a;软件项目开发全套文档下载-CSDN博客

css3实现类似地图定位循环扩散光圈效果

1.效果图,重点opacity,animation,transform:scale 2.html <div class"icon-warnCom"><icon class"icon-warns"><i class"dot"></i><i class"pulse"></i></icon></div><div class…

epi 外延炉 简介

因半导体制造工艺复杂&#xff0c;各个环节需要的设备也不同&#xff0c;从流程工序分类来看&#xff0c;半导体设备主要可分为晶圆制造设备&#xff08;前道工序&#xff09;、封装测试设备&#xff08;后道工序&#xff09;等。 本文介绍影响着晶体管性能和可靠性的外延炉。 …

无损编码——Slepian-Wolf理论

在信息论中&#xff0c;无损编码是一种重要的编码技术&#xff0c;其目的是通过尽量少的比特数来表示一段信息&#xff0c;同时保证信息的完整性和准确性。传统的无损编码方法往往只考虑单个源的编码问题&#xff0c;比如哈夫曼编码和算术编码等。然而&#xff0c;在实际应用中…

易点易动打通OA系统,实现固定资产高效管理

近年来,随着信息化建设的不断深入,OA系统在企业管理工作中的应用也日趋广泛。传统的固定资产管理存在数据分散,管理效率低等问题。深度整合易点易动和OA系统,可以打通各系统之间的数据通道,实现固定资产通过OA系统的全流程管理。这不仅可以提升管理效率,减轻人工管理成本,也更方…

微博被封禁如何解决

1.电脑搜索互联网信息投诉平台&#xff0c;点击我要投诉 2.找到互联网企业&#xff0c;选择新浪微博 3.然后填写个人信息&#xff0c;这里正常填写就行 4.填写信息 5.截图 6.成功

静态路由及动态路由

文章目录 静态路由及动态路由一、静态路由基础1. 静态路由配置2. 负载分担3. 路由备份4. 缺省路由5. 静态路由实操 二、RIP 动态路由协议1. RIP 协议概述2. RIP 协议版本对比2.1 有类路由及无类路由 3. RIP 路由协议原理4. RIP 计时器5. 度量值6. 收敛7. 示例 静态路由及动态路…

linux路由

文章目录 网络拓扑配置route主机网卡配置查看路由表添加路由添加路由后的路由表添加路由添加路由 网络拓扑 配置route主机 R1 网卡配置 eth0 TYPEEthernet PROXY_METHODnone BROWSER_ONLYno BOOTPROTOstatic DEFROUTEyes IPV4_FAILURE_FATALno NAMEeth0 DEVICEeth0 ONBOOTy…

vscode dart语言出现蓝色波浪线

pubspec.yaml 注释掉&#xff1a;flutter_lints: ^2.0.0 analysis_options.yaml 注释掉&#xff1a;include: package:flutter_lints/flutter.yaml