【数据结构】双向链表 C++

news2025/6/9 10:53:14

一、什么是双向链表

1、定义

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。

双向链表的结构如图(图片来源于网络):

2、时空复杂度

双向链表的空间复杂度是 O ( n ) O(n) O(n) 的,其时间复杂度如下:

操作时间复杂度
遍历 O ( n ) O(n) O(n)
访问指定节点 O ( 1 ) O(1) O(1)
删除指定编号节点 O ( n ) O(n) O(n)
删除指定位置节点 O ( 1 ) O(1) O(1)
在指定编号的节点后插入节点 O ( n ) O(n) O(n)
在指定位置的节点后插入节点 O ( 1 ) O(1) O(1)
查询前驱、后继 O ( 1 ) O(1) O(1)
修改指定编号节点的值 O ( n ) O(n) O(n)
修改指定位置节点的值 O ( 1 ) O(1) O(1)
交换两个 list 容器 O ( 1 ) O(1) O(1)

二、双向链表的基本操作

1. 定义双向链表节点

每个节点有三个值:

  1. val:存储每个节点的权值;
  2. last:指向每个节点的前面的第一个节点;
  3. next:指向每个节点的后面的第一个节点;

代码如下:

template<typename T>
struct ListNode{
    T value;
    ListNode<T>* last;
    ListNode<T>* next;
    ListNode():value(0){
        last=NULL,next=NULL;
    }
    ListNode(const T &x):value(x){
        last=NULL,next=NULL;
    }
    ~ListNode(){
        value=0;
        delete last;
        delete next;
    }
};

2. 创建双向链表类

类里面包含两个节点和一个变量:

  1. headnode:头节点,初始时前驱后继均为空,值为 − 1 -1 1
  2. endnode:尾节点,初始时前驱后继均为空,值为 − 1 -1 1
  3. listsize:记录双向链表的节点个数,不包含头尾节点;

代码如下:

template<typename T>
class list{
    private:
        unsigned listsize;
        ListNode<T>* headnode;
        ListNode<T>* endnode;
};

3. 初始化双向链表类

共有四种初始化方式:

  1. list<类型名> a;:此时创建一个空的双向链表;
  2. list<类型名> a(n);:此时创建一个大小为 n n n 的双向链表,并将所有点的初始值赋为 0 0 0
  3. list<类型名> a(n,m):此时创建一个大小为 n n n 的双向链表,并将所有点的初始值赋为 m m m
  4. list<类型名> a={a1,a2,a3,...,an};:此时创建一个大小为 n n n 的双向链表,并将第 i i i 个节点的初始值赋为 a i a_i ai

第一种初始化方式代码如下:

list():listsize(0){
    headnode=new ListNode<T>(-1);
    endnode=new ListNode<T>(-1);
}

第二种初始化方式代码如下:

list(const int &size_t):
    listsize(size_t) {
    headnode=new ListNode<T>(-1);
    endnode=new ListNode<T>(-1);
    ListNode<T>* now=headnode;
    for(int i=0;i<listsize;++i){
        ListNode<T>* newnode=new ListNode<T>(0);
        endnode->last=newnode;newnode->next=endnode;
        newnode->last=now;now->next=newnode;
        now=now->next;
    }
}

第三种初始化方式代码如下:

list(
    const int &size_t,
    const int &val
):listsize(size_t){
    headnode=new ListNode<T>(-1);
    endnode=new ListNode<T>(-1);
    ListNode<T>* now=headnode;
    for(int i=0;i<listsize;++i){
        ListNode<T>* newnode=new ListNode<T>(val);
        endnode->last=newnode;newnode->next=endnode;
        newnode->last=now;now->next=newnode;
        now=now->next;
    }
}

第四种初始化方式代码如下:

typedef std::initializer_list<T> lisval;
list(lisval vals){
    listsize=0;
    headnode=new ListNode<T>(-1);
    endnode=new ListNode<T>(-1);
    ListNode<T>* now=headnode;
    for(auto val:vals){
        ListNode<T>* newnode=new ListNode<T>(val);
        endnode->last=newnode;newnode->next=endnode;
        newnode->last=now;now->next=newnode;
        now=now->next; ++listsize;
    }
}

3. 一些基础的函数

这些函数是除了加点删点之外最常见的几个函数。

  1. size():获取链表的大小,返回一个 unsigned 值,表示当前链表中普通节点(非头尾节点)的个数。

    代码如下:

    unsigned size() const {
        return listsize;
    }
    
  2. empty():返回当前链表是否为空,如果是,返回 true,否则返回 false。

    代码如下:

    bool empty() const {
        return listsize==0;
    }
    
  3. begin():返回第一个普通节点。

    代码如下:

    ListNode<T>* begin(
    ) const {
        return headnode->next;
    }
    
  4. end():返回尾指针。

    代码如下:

    ListNode<T>* end(
    ) const {
        return endnode;
    }
    
  5. rbegin():返回最后一个普通节点。

    代码如下:

    ListNode<T>* rbegin(
    ) const {
        return endnode->last;
    }
    
  6. rend():返回头指针。

    代码如下:

    ListNode<T>* rend(
    ) const {
        return headnode;
    }
    
  7. front():返回第一个普通节点的值。

    代码如下:

    T front() const {
        return begin()->value;
    }
    
  8. back():返回最后一个普通节点的值。

    代码如下:

    T back() const {
        return rbegin()->value;
    }
    
  9. print():遍历并输出链表中每个普通节点的值,结尾换行。

    代码如下:

    void print(
    ) const {
        if(empty()) return;
        ListNode<T>* now=headnode->next;
        while(now->next!=NULL){
            printf("%d ",now->value);
            now=now->next;
        } putchar('\n');
    }
    
  10. swap(list<类型名> &b):交换两个 list 容器,实际上是交换头尾指针和 l i s t s i z e listsize listsize

    代码如下:

    void swap(list<T> &b){
        ListNode<T>* temp;
        temp=headnode;
        headnode=b.headnode;
        b.headnode=temp;
        temp=endnode;
        endnode=b.endnode;
        b.endnode=temp;
        unsigned size_t=listsize;
        listsize=b.listsize;
        b.listsize=size_t;
    }
    

5. 插入节点

共四种方法,代码如下:

void push_back(
    const T &val
){ ++listsize;
    if(endnode->last==NULL){
        ListNode<T>* newnode=new ListNode<T>(val);
        endnode->last=newnode;newnode->next=endnode;
        headnode->next=newnode;newnode->last=headnode;
        return;
    }
    ListNode<T>* pre=endnode->last;
    ListNode<T>* newnode=new ListNode<T>(val);
    pre->next=newnode;newnode->last=pre;
    newnode->next=endnode;endnode->last=newnode;
}
void push_front(
    const T &val
){ ++listsize;
    if(headnode->next==NULL){
        ListNode<T>* newnode=new ListNode<T>(val);
        endnode->last=newnode;newnode->next=endnode;
        headnode->next=newnode;newnode->last=headnode;
        return;
    }
    ListNode<T>* suf=headnode->next;
    ListNode<T>* newnode=new ListNode<T>(val);
    headnode->next=newnode;newnode->last=headnode;
    newnode->next=suf;suf->last=newnode;
}
void insert(
    const T &pos,
    const T &val
){  
    int nowpos=0;
    if(pos==0){
        push_front(val);
        ++listsize; return;
    } else if(pos>=listsize){
        push_back(val);
        ++listsize; return;
    }
    ListNode<T>* now=headnode->next;
    while(now->next!=NULL){
        ++nowpos;
        if(nowpos==pos){
            ListNode<T>* newnode=new ListNode<T>(val);
            ListNode<T>* suf=now->next;
            newnode->next=suf;suf->last=newnode;
            newnode->last=now;now->next=newnode;
            ++listsize; return;
        }
        now=now->next;
    }
}
void insert(
    ListNode<T>* now,
    const T &val
){
    if(now==endnode){push_back(val); return;}
    ListNode<T>* newnode=new ListNode<T>(val);
    ListNode<T>* suf=now->next;
    newnode->next=suf;suf->last=newnode;
    newnode->last=now;now->next=newnode;
    ++listsize; return;
}

6. 修改指定位置的值

两种方法,代码如下:

void reassign(
    const T &pos,
    const T &val
){
    if(pos>listsize) return;
    if(empty()||!pos) return;
    ListNode<T>* now=headnode->next;
    int nowpos=0;
    while(now->next!=NULL){
        ++nowpos;
        if(nowpos==pos){
            now->value=val;
            return;
        } now=now->next;
    }
}
void reassign(
    ListNode<T>* now,
    const int &val
) const {
    now->value=val;
}

7.删除节点

和插入一样,共有四种,代码如下:

void pop_back(){
    if(empty()) return;
    ListNode<T>* now=endnode->last;
    ListNode<T>* pre=now->last;
    if(pre==headnode){
        endnode->last=NULL;
        headnode->last=NULL;
        --listsize; return;
    }
    endnode->last=pre;
    pre->next=endnode;
    --listsize;
}
void pop_front(){
    if(empty()) return;
    ListNode<T>* now=headnode->next;
    ListNode<T>* suf=now->next;
    if(suf==endnode){
        endnode->last=NULL;
        headnode->last=NULL;
        --listsize; return;
    }
    headnode->next=suf;
    suf->last=headnode;
    --listsize;
}
void erase(
    const int &pos
) {
    if(pos>listsize) return;
    if(empty()||!pos) return;
    ListNode<T>* now=headnode->next;
    int nowpos=0;
    while(now!=endnode){
        ++nowpos;
        if(nowpos==pos){
            ListNode<T>* pre=now->last;
            ListNode<T>* suf=now->next;
            if(pre==headnode||suf==endnode){
                endnode->last=NULL;
                headnode->next=NULL;
                delete now;
                --listsize; return;
            }
            pre->next=suf;
            suf->last=pre;
            delete now;
            --listsize; return;
        }
        now=now->next;
    }
}
void erase(
    ListNode<T>* now
){  
    if(now==headnode) return;
    if(now==endnode) return;
    if(empty()) return;
    ListNode<T>* pre=now->last;
    ListNode<T>* suf=now->next;
    if(pre==headnode||suf==endnode){
        endnode->last=NULL;
        headnode->last=NULL;
        --listsize; return;
    }
    pre->next=suf;
    suf->last=pre;
    --listsize; return;
}

8. 注销双向链表类

遍历一遍,然后将每个节点都删除就可以了。

代码如下:

~list(){
    ListNode<T>* now=headnode->next;
    while(now!=NULL){
        ListNode<T>* nxt=now->next;
        delete now;now=nxt;
    } delete headnode; listsize=0;
}

三、完整代码

我知道你们只看这个

码风丑陋,不喜勿喷

#include<stdio.h>
#include<stdlib.h>
#include<initializer_list>
namespace STL{
    template<typename T>
    struct ListNode{
        T value;
        ListNode<T>* last;
        ListNode<T>* next;
        ListNode():value({}){
            last=NULL,next=NULL;
        }
        ListNode(const T &x):value(x){
            last=NULL,next=NULL;
        }
        ~ListNode(){
            // value={};
            last=NULL;
            next=NULL;
        }
    };
    template<typename T>
    class list{
        private:
            unsigned listsize;
            ListNode<T>* headnode;
            ListNode<T>* endnode;
        public:
            list():listsize(0){
                headnode=new ListNode<T>(T({-1}));
                endnode=new ListNode<T>(T({-1}));
            }
            list(const int &size_t):
                listsize(size_t) {
                headnode=new ListNode<T>(-1);
                endnode=new ListNode<T>(-1);
                ListNode<T>* now=headnode;
                for(int i=0;i<listsize;++i){
                    ListNode<T>* newnode=new ListNode<T>(0);
                    endnode->last=newnode;newnode->next=endnode;
                    newnode->last=now;now->next=newnode;
                    now=now->next;
                }
            }
            list(
                const int &size_t,
                const int &val
            ):listsize(size_t){
                headnode=new ListNode<T>(-1);
                endnode=new ListNode<T>(-1);
                ListNode<T>* now=headnode;
                for(int i=0;i<listsize;++i){
                    ListNode<T>* newnode=new ListNode<T>(val);
                    endnode->last=newnode;newnode->next=endnode;
                    newnode->last=now;now->next=newnode;
                    now=now->next;
                }
            }
            typedef std::initializer_list<T> lisval;
            list(lisval vals){
                listsize=0;
                headnode=new ListNode<T>(-1);
                endnode=new ListNode<T>(-1);
                ListNode<T>* now=headnode;
                for(auto val:vals){
                    ListNode<T>* newnode=new ListNode<T>(val);
                    endnode->last=newnode;newnode->next=endnode;
                    newnode->last=now;now->next=newnode;
                    now=now->next; ++listsize;
                }
            }
            unsigned size() const {
                return listsize;
            }
            bool empty() const {
                return listsize==0;
            }
            ListNode<T>* begin(
            ) const {
                return headnode->next;
            }
            ListNode<T>* end(
            ) const {
                return endnode;
            }
            ListNode<T>* rbegin(
            ) const {
                return endnode->last;
            }
            ListNode<T>* rend(
            ) const {
                return headnode;
            }
            T front() const {
                return begin()->value;
            }
            T back() const {
                return rbegin()->value;
            }
            void print(
            ) const {
                if(empty()) return;
                ListNode<T>* now=headnode->next;
                while(now->next!=NULL){
                    printf("%lld ",now->value);
                    now=now->next;
                } putchar('\n');
            }
            void push_back(
                const T &val
            ){ ++listsize;
                if(endnode->last==NULL){
                    ListNode<T>* newnode=new ListNode<T>(val);
                    endnode->last=newnode;newnode->next=endnode;
                    headnode->next=newnode;newnode->last=headnode;
                    return;
                }
                ListNode<T>* pre=endnode->last;
                ListNode<T>* newnode=new ListNode<T>(val);
                pre->next=newnode;newnode->last=pre;
                newnode->next=endnode;endnode->last=newnode;
            }
            void push_front(
                const T &val
            ){ ++listsize;
                if(headnode->next==NULL){
                    ListNode<T>* newnode=new ListNode<T>(val);
                    endnode->last=newnode;newnode->next=endnode;
                    headnode->next=newnode;newnode->last=headnode;
                    return;
                }
                ListNode<T>* suf=headnode->next;
                ListNode<T>* newnode=new ListNode<T>(val);
                headnode->next=newnode;newnode->last=headnode;
                newnode->next=suf;suf->last=newnode;
            }
            void insert(
                const T &pos,
                const T &val
            ){  
                int nowpos=0;
                if(pos==0){
                    push_front(val);
                    ++listsize; return;
                } else if(pos>=listsize){
                    push_back(val);
                    ++listsize; return;
                }
                ListNode<T>* now=headnode->next;
                while(now->next!=NULL){
                    ++nowpos;
                    if(nowpos==pos){
                        ListNode<T>* newnode=new ListNode<T>(val);
                        ListNode<T>* suf=now->next;
                        newnode->next=suf;suf->last=newnode;
                        newnode->last=now;now->next=newnode;
                        ++listsize; return;
                    }
                    now=now->next;
                }
            }
            void insert(
                ListNode<T>* now,
                const T &val
            ){
                if(now==endnode){push_back(val); return;}
                ListNode<T>* newnode=new ListNode<T>(val);
                ListNode<T>* suf=now->next;
                newnode->next=suf;suf->last=newnode;
                newnode->last=now;now->next=newnode;
                ++listsize; return;
            }
            void reassign(
                const T &pos,
                const T &val
            ){
                if(pos>listsize) return;
                if(empty()||!pos) return;
                ListNode<T>* now=headnode->next;
                int nowpos=0;
                while(now->next!=NULL){
                    ++nowpos;
                    if(nowpos==pos){
                        now->value=val;
                        return;
                    } now=now->next;
                }
            }
            void reassign(
                ListNode<T>* now,
                const int &val
            ) const {
                now->value=val;
            }
            void pop_back(){
                if(empty()) return;
                ListNode<T>* now=endnode->last;
                ListNode<T>* pre=now->last;
                if(pre==headnode){
                    endnode->last=NULL;
                    headnode->next=NULL;
                    delete now;
                    --listsize; return;
                }
                endnode->last=pre;
                pre->next=endnode;
                delete now;
                --listsize;
            }
            void pop_front(){
                if(empty()) return;
                ListNode<T>* now=headnode->next;
                ListNode<T>* suf=now->next;
                if(suf==endnode){
                    endnode->last=NULL;
                    headnode->next=NULL;
                    delete now;
                    --listsize; return;
                }
                headnode->next=suf;
                suf->last=headnode;
                delete now;
                --listsize;
            }
            void erase(
                const int &pos
            ) {
                if(pos>listsize) return;
                if(empty()||!pos) return;
                ListNode<T>* now=headnode->next;
                int nowpos=0;
                while(now!=endnode){
                    ++nowpos;
                    if(nowpos==pos){
                        ListNode<T>* pre=now->last;
                        ListNode<T>* suf=now->next;
                        if(pre==headnode||suf==endnode){
                            endnode->last=NULL;
                            headnode->next=NULL;
                            delete now;
                            --listsize; return;
                        }
                        pre->next=suf;
                        suf->last=pre;
                        delete now;
                        --listsize; return;
                    }
                    now=now->next;
                }
            }
            void erase(
                ListNode<T>* now
            ){  
                if(now==headnode) return;
                if(now==endnode) return;
                if(empty()) return;
                ListNode<T>* pre=now->last;
                ListNode<T>* suf=now->next;
                if(pre==headnode||suf==endnode){
                    endnode->last=NULL;
                    headnode->last=NULL;
                    delete now;
                    --listsize; return;
                }
                pre->next=suf;
                suf->last=pre;
                delete now;
                --listsize; return;
            }
            void swap(list<T> &b){
                ListNode<T>* temp;
                temp=headnode;
                headnode=b.headnode;
                b.headnode=temp;
                temp=endnode;
                endnode=b.endnode;
                b.endnode=temp;
                unsigned size_t=listsize;
                listsize=b.listsize;
                b.listsize=size_t;
            }
            ~list(){
                ListNode<T>* now=headnode->next;
                while(now!=NULL){
                    ListNode<T>* nxt=now->next;
                    delete now;now=nxt;
                } delete headnode;listsize=0;
            }
    };
}
using STL::list;

signed main(){

    system("pause");
}

给个赞再走吧

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

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

相关文章

企业工商信息查询API接口有哪些

当今社会我们几乎每天都在和一些企业打交道&#xff0c;有时候需要确认下这家企业经营范围&#xff0c;注册地址等信息&#xff0c;那怎么办呢&#xff0c;这个时候就需要一些企业工商信息查询的API接口了。 有的时候你可以只知道这家公司的大概企业名称&#xff0c;比如数脉&…

Python中sort()函数、sorted()函数的用法深入讲解(具体实例:蓝桥杯数位排序)

前置知识&#xff1a; 可迭代对象的定义&#xff1a;可迭代对象是指可以被迭代或遍历的对象&#xff0c;即可以使用循环结构对其进行逐个访问的对象。 在Python中常见的可迭代对象有&#xff1a;列表(list)、元组&#xff08;tuple&#xff09;、字符串&#xff08;sting&…

【踩坑日记】Pop!OS中文输入法的坑

文章目录 前言一、编译安装最新的IBus-pinyin输入法1.卸载旧输入法2.安装编译依赖3.下载源码4.编译和安装libpinyin5.编译和安装ibus-libpinyin6.重启IBus服务二、安装Fcitx5前言 使用Linux时,特别是涉及到中文的时候,会遇到一些问题。我最近在使用Pop!OS 22.04,这是Ubuntu…

如何监控容器或K8s中的OpenSearch

概述 当前 OpenSearch 使用的越来越多, 但是 OpenSearch 生态还不尽完善. 针对如下情况: 监控容器化或运行在 K8s 中的 OpenSearch 我查了下, 官方还没有提供完备的方案. 这里如何监控 K8s 中的 OpenSearch, 包括安装 exporter 插件、采集、展示全环节。 OpenSearch 简介…

数据库数据恢复—Sql Server数据库文件丢失如何恢复数据?

服务器数据恢复环境&#xff1a; 一台安装windows server操作系统的服务器。一组由8块硬盘组建的RAID5&#xff0c;划分LUN供这台服务器使用。 在windows服务器内装有SqlServer数据库。存储空间LUN划分了两个逻辑分区。 服务器故障&初检&#xff1a; 由于未知原因&#xf…

git 删除本地分支 删除远程仓库分支

语法&#xff1a; 删除本地分支 git branch -D <分支名>删除远程分支 git push <remote名称> <分支名> --delete 示例&#xff1a; 删除本地分支 git branch -D feature/test_listview删除远程分支 git push origin feature/test_listview --delete 两个…

润色问题解惑

上博士为了毕业写学术论文头都大了&#xff0c;但更难受的是英语不咋地&#xff0c;投稿后经常会因为语言问题而惨遭拒稿&#xff0c;每每想起就令人心情郁郁&#xff0c;天台可期。有些审稿人也会直接告知需要专业的修改&#xff0c;那咋整呢&#xff0c;让润色呗&#xff0c;…

腾讯社交广告推广如何开户和费用攻略

腾讯社交广告平台&#xff0c;依托腾讯系庞大的用户基数与丰富的应用场景&#xff0c;为广告主提供了极具潜力的营销渠道。从微信朋友圈、QQ空间到腾讯新闻、腾讯视频等多款热门应用&#xff0c;腾讯社交广告覆盖了亿万级用户群体&#xff0c;是企业提升品牌知名度、推动产品销…

如何做好谷歌广告投放?谷歌广告投放要点解析

市场是在不断变化的&#xff0c;搜索引擎上的网站排名也随着市场的变化而变化。如果你的广告战术一成不变&#xff0c;很容易花冤枉钱。从本质上来讲&#xff0c;谷歌广告的优化工作就是让商家在搜索引擎上保持长久的市场竞争力。 如果商家不经常优化Google广告&#xff0c;可能…

谈谈系列之OA又见OA

确实没想到&#xff0c;绕了一圈&#xff0c;居然又回到了OA&#xff0c;当年从HW从来&#xff0c;就是不想仅仅只做给内部人用的产品&#xff0c;没想到兜兜转转&#xff0c;又回到了给“内部人做产品”的“老路”。 当然&#xff0c;就像先哲赫拉克利特说的——人不能两次走进…

【随笔】Git 高级篇 -- 提交的技巧(下) cherry-pick commit --amend(十九)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

【CSS】CSS三大特性、盒子模型

目录 CSS三大特性 1、层叠性 2、继承性 3、优先级 盒子模型 1、网页布局的本质 2、盒子模型&#xff08;Box Model&#xff09;组成 3、边框&#xff08;border&#xff09; 3.1、边框的使用 3.2、表格的细线边框 3.3、边框会影响盒子实际大小 4、内边距&#xff0…

【AUTOSAR网络管理测试】PowerOn→BSM

&#x1f64b;‍♂️【AUTOSAR网络管理测试】系列&#x1f481;‍♂️点击跳转 文章目录 1.状态机分析2.环境搭建3.测试步骤4.结果分析 1.状态机分析 PowerOn→BSM&#xff1a;上电初始化的&#xff0c;会默认进入BSM状态 测试点&#xff1a;确认上电后&#xff0c;任何唤醒源…

C语言进阶课程学习记录-第29课 - 指针和数组分析(下)

C语言进阶课程学习记录-第29课 - 指针和数组分析&#xff08;下&#xff09; 数组名与指针实验-数组形式转换实验-数组名与指针的差异实验-转化后数组名加一的比较实验-数组名作为函数形参小结 本文学习自狄泰软件学院 唐佐林老师的 C语言进阶课程&#xff0c;图片全部来源于课…

Docker 安装MySql并操作日志

一、在Linux系统里新建这几个文件夹 1.1 在conf.d文件夹下新建一个my.cnf文件 1.2 用vscode 打开&#xff08;防止乱码&#xff09;&#xff0c;复制以下内容 [mysqld] log_timestampsSYSTEM default-time-zone8:00server-id1log-binmysql-binbinlog-do-db mall # 要监听的库…

python使用uiautomator2操作雷电模拟器9找图(二)

昨天写过一篇文章 python使用uiautomator2操作雷电模拟器9找图&#xff08;一&#xff09;-CSDN博客 今天在实际中有遇到了新的问题&#xff1a;一幅主图中&#xff0c;可能存在多个相同的子图&#xff0c;想要找到所有的子图&#xff0c;并操作。比如&#xff1a; 主图&…

头歌-机器学习 第1次实验 Python机器学习软件包Scikit-Learn的学习与运用

第1关&#xff1a;使用scikit-learn导入数据集 scikit-learn包括一些标准数据集&#xff0c;不需要从外部下载&#xff0c;可直接导入使用&#xff0c;比如与分类问题相关的Iris数据集和digits手写图像数据集&#xff0c;与回归问题相关的波士顿房价数据集。 以下列举一些简单…

计算机网络-浏览器解析到URL对应的IP地址的时间

声明&#xff1a;原文转载链接出自&#xff1a; 哈工大Mooc——计算机网络&#xff1a;作业3 假设你在浏览某网页时点击了一个超链接&#xff0c;URL为“https://www.kicker.com.cn/index.html”&#xff0c;且该URL对应的IP地址在你的计算机上没有缓存&#xff1b;文件index…

OCR常用识别算法综述

参考&#xff1a;https://aistudio.baidu.com/education/lessonvideo/3279888 语种&#xff1a;常用字符36与常用汉字6623&#xff0c;区别。 标注&#xff1a;文本型位置/单字符位置&#xff0c;后者标注成本大 挑战&#xff1a;场景文字识别&#xff1a;字符大小、颜色、字体…

智能网络新纪元:机器学习赋能未来计算机网络高速发展

&#x1f9d1; 作者简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导…