《数据结构、算法与应用C++语言描述》-代码实现键值有序链表跳表

跳表

定义

在一个用有序链表描述的 n 个数对的字典中进行查找,至多需要 n 次关键字比较。如果在链表的中部节点加一个指针,则比较次数可以减少到 n/2+1。这时,为了查找一个数对,首先与中间的数对比较。如果查找的数对关键字比较小,则仅在链表的左半部分继续查找,否则,在链表右半部分继续查找。

在跳表结构中有一组等级链表。0 级链表包含所有数对,1 级链表的数对是 0 级链表数对的一个子集。i级链表的数对是i-1 级链表数对的子集。

在插入时级的分配

在规则的跳表结构中,i-1 级链表的数对个数与i级链表的数对个数之比是一个分数 p。因此,属于 i-1 级链表的数对同时属于 i 级链表的概率为 p。假设用一个统一的随机数生成器产生0和1间的实数,产生的随机数<=p的概率为p。若下一个随机数<=p,则新数对应在1级链表上。要确定该数对是否在 2 级链表上,要由下一个随机数来决定。若新的随机数<= p,则该元素也属于2级链表。重复这个过程,直到一随机数>p为止。

这种方法有潜在的缺点,某些数对被分配的级数可能特别大,远远超过 l o g 1 / p N log_{1/p}N log1/pN,其中N为字典数对的最大预期数目。为避免这种情况,可以设定一个级数的上限maxLevel,最大值为: ⌈ l o g 1 / p N ⌉ − 1 \lceil log_{1/p}N \rceil-1 log1/pN1

这种方法还有一个缺点,即使采用了级数的上限 maxLevel,还可能出现这样的情况:在插入一个新数对之前有 3 个链表,而在插入之后就有了 10 个链表。也就是说,尽管 3 ~8 级链表没有数对,新数对却被分配到9级链表。换句话说,在插入前后,没有3~8级链表。因为这些空级链表并没有什么好处,我们可以把新记录的链表等级调整为3。

在这里插入图片描述

练习题

【练习9】扩充类skipList,增加删除方法,删除关键字最小的节点,删除关键字最大的节点。计算每个方法的复杂度?

代码

每个node有值,还有一个数组,存储了该键值对每级的指针,键值对最高属于几级,那么该键值对也属于最高级一下的其他级;所以每个node的指针数组为最高级+1(还有0级)大小。

main.cpp
#include <iostream>
#include "_24skipList.h"

int main() {
    skipListTest();
    return 0;
}
_24skipList.h
/*
Project name :			allAlgorithmsTest
Last modified Date:		2022年8月23日10点18分
Last Version:			V1.0
Descriptions:			跳表类---随机决定是几级,插入的时候是几级,现在就是几级---头文件
                        查找时可以节省时间
*/
#pragma once
#ifndef _SKIPLIST_H_
#define _SKIPLIST_H_
#include <iostream>
#include <cmath>
#include <sstream>
#include <string>
#include <cstdlib>
#include "_1myExceptions.h"
#include "_23dictionary.h"
#include "_24skipNode.h"
using namespace std;
/*测试函数*/
void skipListTest();

template<class K, class E>
class skipList : public dictionary<K, E>
{
public:
    skipList(K largeKey, int maxPairs = 10000, float prob = 0.5);
    ~skipList();

    bool empty() const { return dSize == 0; }
    int size() const { return dSize; }
    pair<const K, E>* find(const K&) const;
    void erase(const K&);
    void insert(const pair<const K, E>&);
    void deleteFront();
    void deleteBack();
    /*友元函数*/
    /*输入字典*/
    istream& input(istream& in);
//    friend istream& operator>> <K, E>(istream& in, skipList<K, E>& m);
    /*输出字典*/
    ostream& output(ostream& out) const;
//    friend ostream& operator<< <K, E>(ostream& out, const skipList<K, E>& m);

protected:
    float cutOff;          // used to decide level number--用于确定层数
    int level() const;     // generate a random level number
    int levels;            // max current nonempty chain
    int dSize;             // number of pairs in dictionary
    int maxLevel;          // max permissible chain level
    K tailKey;             // a large key
    skipNode<K, E>* search(const K&) const;
    // search saving last nodes seen
    skipNode<K, E>* headerNode;  // header node pointer
    skipNode<K, E>* tailNode;    // tail node pointer
    skipNode<K, E>** last;       // last[i] = last node seen on level i
};

/*输入字典*/
template<class K, class E>
istream& skipList<K, E>::input(istream& in)
//istream& operator>>(istream& in, skipList<K, E>& m)
{
    int numberOfElement = 0;
    cout << "Please enter the number of element:";
    while (!(in >> numberOfElement))
    {
        in.clear();//清空标志位
        while (in.get() != '\n')//删除无效的输入
            continue;
        cout << "Please enter the number of element:";
    }
    K first;
    E second;
    for (int i = 0; i < numberOfElement; i++)
    {
        cout << "Please enter the element " << i + 1 << ":";
        while (!(in >> first >> second))
        {
            in.clear();//清空标志位
            while (in.get() != '\n')//删除无效的输入
                continue;
            cout << "Please enter the element " << i + 1 << ":";
        }
        const pair<const K, E> element(first, second);
        insert(element);
    }
    return in;
}
template<class K, class E>
istream& operator>>(istream& in, skipList<K, E>& m){
    m.input(in);
    return in;
}
/*输出字典*/
template<class K, class E>
ostream& skipList<K, E>::output(ostream& out) const
//ostream& operator<<(ostream& out, const skipList<K, E>& m)
{
    skipNode<K, E>* currentNode = headerNode->next[0];
    while (currentNode != tailNode)
    {
        out << *currentNode;
        currentNode = currentNode->next[0];
    }
    cout << endl;
    return out;
}
template<class K, class E>
ostream& operator<<(ostream& out, const skipList<K, E>& m){
    m.output(out);
    return out;
}
/*构造函数*/
template<class K, class E>
skipList<K, E>::skipList(K largeKey, int maxPairs, float prob)
{
    /*RAND_MAX这是一个宏定义,就是产生随机数的最大值,在stdlib头文件中*/
    /*prob一般是0.5*/
    cutOff = prob * RAND_MAX;
    /*ceil()函数表示向下取整,logf()函数表示取对数,maxPairs表示数对个数的最大数*/
    maxLevel = (int)ceil(logf((float)maxPairs) / logf(1 / prob)) - 1;//允许的最大层数
    levels = 0;  //初始非空层数为0
    dSize = 0;//初始跳表大小为0
    tailKey = largeKey;//表示最大键值

    // create header & tail nodes and last array
    pair<K, E> tailPair;
    tailPair.first = tailKey;
    headerNode = new skipNode<K, E>(tailPair, maxLevel + 1);//创建头节点
    tailNode = new skipNode<K, E>(tailPair, 0);//创建尾节点
    last = new skipNode<K, E> *[maxLevel + 1];//last[i]表示i层的最后结点

    // 初始状态下所有的i级链表的头节点指向尾节点
    for (int i = 0; i <= maxLevel; i++)
        headerNode->next[i] = tailNode;
}
/*删除所有结点和 指针数组last*/
template<class K, class E>
skipList<K, E>::~skipList()
{// Delete all nodes and array last.
    skipNode<K, E>* nextNode;

    /*一定会让它执行一次,因为有头节点。*/
    while (headerNode != tailNode)
    {
        nextNode = headerNode->next[0];
        delete headerNode;
        headerNode = nextNode;
    }
    delete tailNode;
    delete[] last;
}
/*返回匹配的数对的指针;如果没有匹配的数对,则返回nullptr*/
template<class K, class E>
pair<const K, E>* skipList<K, E>::find(const K& theKey) const
{
    if (theKey >= tailKey)
        return nullptr;  // no matching pair possible

    // position beforeNode just before possible node with theKey
    skipNode<K, E>* beforeNode = headerNode;
    for (int i = levels; i >= 0; i--)          // go down levels
        // follow level i pointers
        while (beforeNode->next[i]->element.first < theKey)
            beforeNode = beforeNode->next[i];

    // check if next node has theKey
    if (beforeNode->next[0]->element.first == theKey)
        return &beforeNode->next[0]->element;

    return nullptr;  // no matching pair
}

template<class K, class E>
int skipList<K, E>::level() const
{// Return a random level number <= maxLevel.
    int lev = 0;
    while (rand() <= cutOff)
        lev++;
    return (lev <= maxLevel) ? lev : maxLevel;
}
/*搜索关键字theKey,把每一级链表中要查看的最后一个结点存储在数组last中*/
/*返回包含关键字theKey的结点*/
/*位置beforeNode是关键字为theKey的结点之前最右边的位置*/
template<class K, class E>
skipNode<K, E>* skipList<K, E>::search(const K& theKey) const
{
    skipNode<K, E>* beforeNode = headerNode;
    for (int i = levels; i >= 0; i--)
    {
        while (beforeNode->next[i]->element.first < theKey)
            beforeNode = beforeNode->next[i];
        last[i] = beforeNode;  //theKey关键字之前的结点
    }
    return beforeNode->next[0];//返回值是0级中 很有可能是theKey为关键字的结点,或比它的key值更大的结点
}

/*向链表中插入元素thePair,如果链表中不存在与thePair的关键字相同的元素则插入,否则更新该关键字相应的值*/
template<class K, class E>
void skipList<K, E>::insert(const pair<const K, E>& thePair)
{
    /*key值超过最大key值时*/
    if (thePair.first >= tailKey) // key too large
    {
        ostringstream s("");
        s << "Key = " << thePair.first << " Must be < " << tailKey;
        throw illegalParameterValue(s.str());
    }

    /*thePair的key值已经存在时,更新该key对应的值*/
    skipNode<K, E>* theNode = search(thePair.first);
    if (theNode->element.first == thePair.first)
    {
        theNode->element.second = thePair.second;
        return;
    }

    /*当不存在该key值时,决定等级i*/
    int theLevel = level(); //随机计算新节点的等级
    /*如果等级大于非空等级的个数,则修正*/
    if (theLevel > levels)
    {
        theLevel = ++levels;
        last[theLevel] = headerNode;
    }

    /*将新节点存储到theNode之后*/
    skipNode<K, E>* newNode = new skipNode<K, E>(thePair, theLevel + 1);
    for (int i = 0; i <= theLevel; i++)
    {// insert into level i chain
        newNode->next[i] = last[i]->next[i];
        last[i]->next[i] = newNode;
    }

    dSize++;
    return;
}

template<class K, class E>
void skipList<K, E>::erase(const K& theKey)
{// Delete the pair, if any, whose key equals theKey.
    if (theKey >= tailKey) // too large
        return;

    // see if matching pair present
    skipNode<K, E>* theNode = search(theKey);
    if (theNode->element.first != theKey) // not present
        return;

    // delete node from skip list
    for (int i = 0; i <= levels && last[i]->next[i] == theNode; i++)
        last[i]->next[i] = theNode->next[i];

    // update levels
    while (levels > 0 && headerNode->next[levels] == tailNode)
        levels--;

    delete theNode;
    dSize--;
}
/*练习9:删除关键字最小的结点*/
template<class K, class E>
void skipList<K, E>::deleteFront()
{
    if (dSize == 0)
        return;
    /*找到关键字最小的结点*/
    skipNode<K, E>* frontNode = headerNode->next[0];
    /*删除各个级的 该结点*/
    for(int i = 0;i <= levels && headerNode->next[i] == frontNode;i++)
        headerNode->next[i] = frontNode->next[i];
    /*更新levels*/
    while (levels > 0 && headerNode->next[levels] == tailNode)
        levels--;
    delete frontNode;
    dSize--;
}
/*练习9:删除关键字最大的结点*/
template<class K, class E>
void skipList<K, E>::deleteBack()
{
    /*找到关键字最大的结点*/
    skipNode<K, E>* deleteBack = headerNode;
    for (int i = levels; i >= 0; i--)
    {
        while (deleteBack->next[i]->element.first < tailKey)
            deleteBack = deleteBack->next[i];
    }
    /*找到各个级的 deleteBack 之前的元素地址*/
    search(deleteBack->element.first);
    /*删除各个级的 该结点*/
    for (int i = 0; i <= levels && last[i]->next[i] == deleteBack; i++)
        last[i]->next[i] = deleteBack->next[i];
    /*更新levels*/
    while (levels > 0 && headerNode->next[levels] == tailNode)
        levels--;
    delete deleteBack;
    dSize--;
}
#endif
_24skipList.cpp
/*
Project name :			allAlgorithmsTest
Last modified Date:		2022年8月23日10点18分
Last Version:			V1.0
Descriptions:			跳表类---随机决定是几级,插入的时候是几级,现在就是几级---cpp文件
*/
#include <iostream>
#include "_24skipList.h"
using namespace std;

void skipListTest()
{
    cout << endl << "*********************************skipListTest()函数开始***************************************" << endl;
    //测试输入和输出
    cout << endl << "测试输入输出*******************************************" << endl;
    cout << "输入输出************************" << endl;
    skipList<int, int> a(20);
    cin >> a;
    cout << "The dictionary is " << a;
    cout << endl << "测试成员函数*******************************************" << endl;
    cout << "empty()*************************" << endl;
    cout << "a.empty() = " << a.empty() << endl;
    cout << "size()**************************" << endl;
    cout << "a.size() = " << a.size() << endl;
    cout << "find()**************************" << endl;
    cout << "Element associated with 1 is " << a.find(1)->second << endl;
    cout << "insert()************************" << endl;
    pair<const int, int> insertData(4, 4);
    a.insert(insertData);
    cout << "The dictionary is " << a;
    cout << "erase()*************************" << endl;
    a.erase(1);
    cout << "The dictionary is " << a;
    cout << "deleteFront()*******************" << endl;
    a.deleteFront();
    cout << "The dictionary is " << a;
    cout << "deleteBack()********************" << endl;
    a.deleteBack();
    cout << "The dictionary is " << a;

    cout << "**********************************skipListTest()函数结束**************************************" << endl;
}
_23dictionary.h
/*
Project name :			allAlgorithmsTest
Last modified Date:		2022年8月22日09点17分
Last Version:			V1.0
Descriptions:			字典的抽象类
*/
/*
pair:
	介绍:是将2个数据组合成一组数据,是一个结构体,主要的两个成员变量first和second,分别存储两个数据.
	使用:使用std命名空间引入对组std::pair
*/
#pragma once
#ifndef _DICTIONARY_H_
#define _DICTIONARY_H_
using namespace std;
template<class K,class E>
class dictionary
{
public:
    virtual ~dictionary() {}
    /*返回为true,当且仅当字典为空*/
    virtual bool empty() const = 0;
    /*返回字典中数对的数目*/
    virtual int size() const = 0;
    /*返回匹配数对的指针*/
    virtual pair<const K, E>* find(const K&) const = 0;
    /*删除匹配的数对*/
    virtual void erase(const K&) = 0;
    /*往字典中插入一个数对*/
    virtual void insert(const pair<const K, E>&) = 0;
};
#endif
_24skipNode.h
/*
Project name :			allAlgorithmsTest
Last modified Date:		2022年8月23日10点18分
Last Version:			V1.0
Descriptions:			跳表结构
// node type used in skip lists
// node with a next and element field; element is a pair<const K, E>
// next is a 1D array of pointers
*/
#pragma once
#ifndef _SKIPNODE_H_
#define _SKIPNODE_H_

template <class K, class E>
struct skipNode
{
    typedef pair<const K, E> pairType;
    pairType element;
    skipNode<K, E>** next;   // 1D array of pointers

    skipNode(const pairType& thePair, int size)
            :element(thePair) {
        next = new skipNode<K, E>*[size];
    }
    friend ostream& operator<<(ostream& out, skipNode<K, E>& m)
    {
        out << "(" << m.element.first << " ," << m.element.second << ")" << " ";
        return out;
    }
};

#endif
_1myExceptions.h
/*
Project name :			allAlgorithmsTest
Last modified Date:		2022年8月13日17点38分
Last Version:			V1.0
Descriptions:			综合各种异常
*/
#pragma once
#ifndef _MYEXCEPTIONS_H_
#define _MYEXCEPTIONS_H_
#include <string>
#include<iostream>

using namespace std;

// illegal parameter value
class illegalParameterValue
{
public:
    illegalParameterValue(string theMessage = "Illegal parameter value")
    {message = theMessage;}
    void outputMessage() {cout << message << endl;}
private:
    string message;
};

// illegal input data
class illegalInputData
{
public:
    illegalInputData(string theMessage = "Illegal data input")
    {message = theMessage;}
    void outputMessage() {cout << message << endl;}
private:
    string message;
};

// illegal index
class illegalIndex
{
public:
    illegalIndex(string theMessage = "Illegal index")
    {message = theMessage;}
    void outputMessage() {cout << message << endl;}
private:
    string message;
};

// matrix index out of bounds
class matrixIndexOutOfBounds
{
public:
    matrixIndexOutOfBounds
            (string theMessage = "Matrix index out of bounds")
    {message = theMessage;}
    void outputMessage() {cout << message << endl;}
private:
    string message;
};

// matrix size mismatch
class matrixSizeMismatch
{
public:
    matrixSizeMismatch(string theMessage =
    "The size of the two matrics doesn't match")
    {message = theMessage;}
    void outputMessage() {cout << message << endl;}
private:
    string message;
};

// stack is empty
class stackEmpty
{
public:
    stackEmpty(string theMessage =
    "Invalid operation on empty stack")
    {message = theMessage;}
    void outputMessage() {cout << message << endl;}
private:
    string message;
};

// queue is empty
class queueEmpty
{
public:
    queueEmpty(string theMessage =
    "Invalid operation on empty queue")
    {message = theMessage;}
    void outputMessage() {cout << message << endl;}
private:
    string message;
};

// hash table is full
class hashTableFull
{
public:
    hashTableFull(string theMessage =
    "The hash table is full")
    {message = theMessage;}
    void outputMessage() {cout << message << endl;}
private:
    string message;
};

// edge weight undefined
class undefinedEdgeWeight
{
public:
    undefinedEdgeWeight(string theMessage =
    "No edge weights defined")
    {message = theMessage;}
    void outputMessage() {cout << message << endl;}
private:
    string message;
};

// method undefined
class undefinedMethod
{
public:
    undefinedMethod(string theMessage =
    "This method is undefined")
    {message = theMessage;}
    void outputMessage() {cout << message << endl;}
private:
    string message;
};
#endif

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

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

相关文章

【数据仓库】数仓分层方法

文章目录 一. 数仓分层的意义1. 清晰数据结构。2. 减少重复开发3. 方便数据血缘追踪4. 把复杂问题简单化5. 屏蔽原始数据的异常6. 数据仓库的可维护性 二. 如何进行数仓分层&#xff1f;1. ODS层2. DW层2.1. DW层分类2.2. DWD层2.3. DWS 3. ADS层 4、层次调用规范 一. 数仓分层…

全域全自主建设,亚信科技AntDB数据库助力广电5G业务上线运行

自2019年6月&#xff0c;中国广电成功获得5G牌照以来&#xff0c;迅速推进网络建设目标&#xff0c;成为5G网络覆盖广、应用场景多、用户体验出色的第四大运营商。其依托全球独有的700MHz频谱资源&#xff0c;具备覆盖能力强、容量足、速率高的优势。通过不断深化和中国移动的共…

【JavaEE】Servlet(创建Maven、引入依赖、创建目录、编写及打包、部署和验证、smart Tomcat)

一、什么是Servlet&#xff1f; Servlet 是一种实现动态页面的技术. 是一组 Tomcat 提供给程序猿的 API, 帮助程序猿简单高效的开发一个 web app 1.1 Servlet能干什么&#xff1f; &#x1f695;允许程序猿注册一个类, 在 Tomcat 收到某个特定的 HTTP 请求的时候, 执行这个类…

自动化测试项目:浅谈分层设计的思路

本文以笔者当前使用的自动化测试项目为例&#xff0c;浅谈分层设计的思路&#xff0c;不涉及到具体的代码细节和某个框架的实现原理&#xff0c;重点关注在分层前后的使用对比&#xff0c;可能会以一些伪代码为例来说明举例。 接口测试三要素&#xff1a; 参数构造发起请求&a…

通配符SSL证书:保护多个子域名的最佳选择

很多网站和应用程序采用了多个子域名来提供不同的服务或内容。为了确保这些子域名的安全性和数据加密&#xff0c;使用通配符SSL证书成为一个理想的解决方案。 首先&#xff0c;通配符SSL证书的最大优势在于其灵活性和经济性。不同于单个SSL证书只能保护一个特定的域名&#xf…

Python实现WOA智能鲸鱼优化算法优化循环神经网络回归模型(LSTM回归算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 鲸鱼优化算法 (whale optimization algorithm,WOA)是 2016 年由澳大利亚格里菲斯大学的Mirjalili 等提…

【游戏开发算法每日一记】使用随机prime算法生成错综复杂效果的迷宫(C#和C++)

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…

Peter算法小课堂—自定义容器

太戈编程第308题 暴力法 cin>>n>>m; for(int i0;i<n;i) cin>>name[i]>>year[i]; for(int i0;i<m;i){int x;string y;cin>>x>>y;int OK0;for(int j0;j<n;j){if(name[j]y&&year[j]x){OK1;break;}}cout<<OK<<…

WH4530A可检测0-100cm环境光+距离检测功能

台湾旺泓推出的WH4530A是一款结合了先进环境光传感器&#xff08;ALS&#xff09;先进接近传感器&#xff08;PS&#xff09;和高效率的红外LED灯三合一为一体的光距感接近传感器&#xff1b;可测距范围0-100cm;采用I2C接口&#xff0c;可实现超高灵敏度、精准测距检测范围广等…

介绍公司的软文怎么写

软文推广成为企业提高知名度和市场竞争力的主要方式之一&#xff0c;通过软文推广&#xff0c;公司能够被更多消费者熟知并在他们心中留下深刻印象&#xff0c;一篇好的软文&#xff0c;不仅能传递公司的产品和服务信息&#xff0c;还可以传递出公司的理念、文化等&#xff0c;…

【Linux】进程等待

文章目录 tips一、进程等待是什么&#xff1f;二、为什么要有进程等待&#xff1f;三、怎么做到进程等待&#xff1f;先看看什么是进程等待wait和waitpidstatus参数options参数非阻塞轮询 进程等待的原理 总结 tips 下面的代码可以循环检测进程。 while :; do ps ajx | head …

ASK、PSK、FSK的调制与解调

ASK、PSK、FSK的调制与解调 本文主要涉及数字信号的调制与解调&#xff0c;内容包括&#xff1a;2ASK、2PSK、2FSK的调制与解调以及频谱分析 关于通信原理还有其他文章可参考&#xff1a; 1、信息量、码元、比特、码元速率、信息速率详细解析——实例分析 2、模拟系统的AM信号的…

在个人简历中为什么要写个人优势?

问题描述&#xff1a; 在个人简历中为什么要写个人优势&#xff1f; 解决方案&#xff1a; 在个人简历中写个人优势的目的是突出你作为求职者的独特优势和价值&#xff0c;一段精简且亮眼的介绍能够快速抓住HR的眼球&#xff0c;判断你与岗位的契合度&#xff0c;进而对你产生…

2023年阿里云服务器最新日常价、活动价格、可使用优惠券金额及券后价格参考

阿里云服务器最新实际购买价格参考&#xff0c;轻量应用服务器2核2G3M带宽配置日常价720.00元/1年&#xff0c;最新活动价格为87元/1年&#xff0c;订单满300元以上即可使用满减优惠券&#xff0c;例如经济型e实例2核4G2M带宽日常价格为1802.40元&#xff0c;最新的活动价格为8…

归并排序详解

&#x1f389;个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名乐于分享在学习道路上收获的大二在校生&#x1f43b;‍❄个人主页&#x1f389;&#xff1a;GOTXX &#x1f43c;个人WeChat&#xff1a;ILXOXVJE&#x1f43c;本文由GOTXX原创&#xff0c;首发CSDN&a…

彭州市民政局“四个聚焦” 推动未成年人保护工作

聚焦机制完善。以“六大保护”为主导&#xff0c;聚焦“27&#xff08;市级部门&#xff09;13&#xff08;镇、街道&#xff09;”整体联动&#xff0c;定期开展信息交流会、跨部门协同工作培训会等活动&#xff0c;不断健全协调机制、完善协同体系&#xff0c;进一步提升全市…

监控和数据采集软件架构和详细设计

介绍 监控和数据采集软件通过提供实时监控、数据收集和分析功能&#xff0c;在各个行业中发挥着至关重要的作用。这些软件应用程序可帮助企业收集有价值的见解、优化流程并做出明智的决策。在本文中&#xff0c;我们将探讨监测和数据采集软件的软件架构、编程技术和详细设计规范…

SpringBoot3基础特性

SpringBoot3基础特性 SpringApplication 自定义banner 类路径添加banner.txt或设置spring.banner.location就可以定制banner推荐网站:Spring Boot banner在线生成工具&#xff0c;制作下载英文banner.txt,修改替换banner.txt文字实现自定义。 提示&#xff1a; 可以通过修改配…

【C++ 学习 ㊱】- 智能指针详解

目录 一、为什么需要智能指针&#xff1f; 二、智能指针的原理及使用 三、auto_ptr 3.1 - 基本使用 3.2 - 模拟实现 四、unique_ptr 4.1 - 基本使用 4.2 - 模拟实现 五、shared_ptr 5.1 - 基本使用 5.2 - 模拟实现 六、weak_ptr 6.1 - shared_ptr 的循环引用问题 …

Amazon Bedrock | 大语言模型CLAUDE 2体验

这场生成式AI与大语言模型的饥饿游戏&#xff0c;亚马逊云科技也参与了进来。2023年&#xff0c;亚马逊云科技正式发布了 Amazon Bedrock&#xff0c;是客户使用基础模型构建和扩展生成式AI应用程序的最简单方法&#xff0c;为所有开发者降低使用门槛。在 Bedrock 上&#xff0…