移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——13.mapset(模拟实现)

1.对红黑树进行改造

1.1treenode模板参数改变

之前构建treenode模板参数传的是class k,class v(set为k,k;map是k,v),现在直接用T代替

template<class T>  //这里直接传了T作为模板参数,T可能是pair<k,t>,也可能是k
struct RBTtreenode
{RBTtreenode<T>* _left;RBTtreenode<T>* _right;RBTtreenode<T>* _parent;//pair<K, V> kv;T data;color col;RBTtreenode(const T& _data):_left(nullptr), _right(nullptr), _parent(nullptr), data(_data), col(RED){}
};

 

2.构建红黑树的迭代器 

因为要构建const_iterator(不可修改内容) 和iterator(可修改内容)所以需要三个模板参数

//<T,T&,T*> iterator;//普通迭代器
//<T, const T&, const T*> const_iterator;//指向的东西不能改变

template<class T,class Ref,class Ptr>

 iterator内存的是node*类型的数据!!!!

2.1 重载operator*()   (set)

因为set传模板参数只传K,没有Vdata类型是K,

所以用*直接取得data即可

Ref operator*()
{return _node->data;
}

 2.2 重载operator->()   (map)

因为map模板参数传的是K,pair<const K,T>,data类型是pair<const K,T>

想取到K,则需要传回&data,再用->first取得K

Ptr operator->()
{return &_node->data;
}

 2.3operator++()与operator--()

 这里以operator++()做解释:

分三种情况:

1.如果右子树不为空,则找到右子树的最左节点

2.//如果右子树为空,且cur是parent的右子树,则先parent回溯至parent->_parent,再_node变为parent
3.//如果右子树为空,且cur是parent的左子树,则_node变为parent

 

iterator& operator++()
{if (_node->_right){//如果右子树不为空,则找到右子树的最左节点node* cur = _node->_right;while (cur && cur->_left){cur = cur->_left;}_node = cur;}else{//如果右子树为空,且cur是parent的右子树,则先parent回溯至parent->_parent,再_node变为parent//如果右子树为空,且cur是parent的左子树,则_node变为parentnode* cur = _node;node* parent = cur->_parent;while (parent && cur == parent->_right){cur = parent;parent = parent->_parent;}_node = parent;}return *this;
}

2.4.begin()&&end() 

iterator begin()
{node* flag = root;while (flag&&flag->_left)//flag可能为nullptr{flag = flag->_left;}return iterator(flag);
}iterator end()
{return iterator(nullptr); //end用nullptr去构造!!!!!!!!
}const_iterator begin() const
{node* flag = root;while (flag && flag->_left)//flag可能为nullptr{flag = flag->_left;}return const_iterator(flag);
}const_iterator end() const
{return const_iterator(nullptr); //end用nullptr去构造!!!!!!!!
}

3.set.h封装

https://cplusplus.com/reference/set/set/?kw=set

#include"rbt.h"
namespace zone
{template<class K>class set{public:struct setkeyoft //仿函数,用来取出红黑树节点data中的key{const K& operator()(const K& key){return key;}};//set这里的迭代器本质都是const_iterator,因为k要求无法修改typedef typename RBTtree<K, K, setkeyoft>::const_iterator iterator;//记得要使用typename告诉编译器RBTtree<K, K, setkeyoft>::iterator这个是类型,不是函数typedef typename RBTtree<K, K, setkeyoft>::const_iterator const_iterator;iterator begin()const{return it.begin();}iterator end()const{return it.end();}pair<iterator,bool> insert(const K& key){return it.insert(key);}void inorder(){it.inorder();}private:RBTtree<K,K,setkeyoft> it;};
}

3.1 仿函数setkeyoft

仿函数,用来取出红黑树节点data中的key,用于insert函数!!!!

3.2 iterator和const_iterator

//set这里的迭代器本质都是const_iterator,因为k要求无法修改
        typedef typename RBTtree<K, K, setkeyoft>::const_iterator iterator;
        typedef typename RBTtree<K, K, setkeyoft>::const_iterator const_iterator;

4.map.h封装 

https://cplusplus.com/reference/map/map/?kw=map

#include"rbt.h"
namespace zone
{template<class K,class T>class map{public:struct setkeyoft{const K& operator()(const pair<K, T>& key){return key.first;}};//map这里的迭代器则使用的是iterator,因为k要求无法修改,但v可以修改,所以可以直接初始化时用pair<const K, T>typedef typename RBTtree<K, pair<const K, T>, setkeyoft>::iterator iterator;typedef typename RBTtree<K, pair<const K, T>, setkeyoft>::const_iterator const_iterator;pair<iterator, bool> insert(const pair<K, T>& key){return it.insert(key);}T& operator[](const K& key){pair<iterator, bool>ret = insert(make_pair(key,T()));//insert返回一个pair,first是iterator,second是bool类型return ret.first->second;}iterator begin(){return it.begin();}iterator end(){return it.end();}void inorder(){it.inorder();}private:RBTtree<K,pair<const K,T>, setkeyoft> it;};
}

5.insert函数 !!!!!!!

RBT.h里insert函数的返回值是 pair<node*, bool>

但封装过后的map.h,set.h里

pair<iterator,bool> insert(const K& key)
{return it.insert(key);
}

 返回值是pair<iterator,bool>

可见 pair<node*, bool>pair<iterator(这里的iterator已经重命名了,本质是const_iteratir),bool>并不是同一类型,该如何解决呢?

 

 

1.如果T1和U类型一致,T2和V类型一致,那么就是拷贝构造!!!

2.如果不一致,也可以进行普通构造前提是有可以用first来构建T1的函数!!!!!

回到刚才的问题:

可见 pair<node*, bool>pair<iterator(这里的iterator已经重命名了,本质是const_iteratir),bool>并不是同一类型,该如何解决呢?

bool类型肯定可以用bool类型初始化,

iterator可以用node*进行初始化吗?

答案是可以的

treeiterator(node* it):_node(it)
{}

相当于使用了隐式类型转换

 6.杂谈

 

类比指针:

1.iterator 可修改指向的数据,也可改变自身

2.const iterator  可修改指向的数据,但不可改变自身

3.const_iterator 不可修改指向的数据,但能改变自身

 7.代码全览

RBT.h

#include<iostream>using namespace std;enum color
{RED,BLACK
};  //列举color的各种可能情况template<class T>  //这里直接传了T作为模板参数,T可能是pair<k,t>,也可能是k
struct RBTtreenode
{RBTtreenode<T>* _left;RBTtreenode<T>* _right;RBTtreenode<T>* _parent;//pair<K, V> kv;T data;color col;RBTtreenode(const T& _data):_left(nullptr), _right(nullptr), _parent(nullptr), data(_data), col(RED){}
};//<T,T&,T*> iterator;//普通迭代器
//<T, const T&, const T*> const_iterator;//指向的东西不能改变:const_iterator,本身不能改变:const iterator
template<class T,class Ref,class Ptr>
struct treeiterator
{typedef RBTtreenode<T> node;typedef treeiterator<T,Ref,Ptr> iterator;node* _node;treeiterator(node* it):_node(it){}Ref operator*(){return _node->data;}Ptr operator->(){return &_node->data;}iterator& operator++(){if (_node->_right){//如果右子树不为空,则找到右子树的最左节点node* cur = _node->_right;while (cur && cur->_left){cur = cur->_left;}_node = cur;}else{//如果右子树为空,且cur是parent的右子树,则先parent回溯至parent->_parent,再_node变为parent//如果右子树为空,且cur是parent的左子树,则_node变为parentnode* cur = _node;node* parent = cur->_parent;while (parent && cur == parent->_right){cur = parent;parent = parent->_parent;}_node = parent;}return *this;}iterator& operator--()   //和++反着来即可{if (_node->_left){node* cur = _node->_left;while (cur && cur->_right){cur = cur->_right;}_node = cur;}else{node* cur = _node;node* parent = cur->_parent;while (parent && cur == parent->_left){cur = parent;parent = parent->_parent;}_node = parent;}return *this;}bool operator!=(const iterator&s){return _node != s._node;}
};template<class K, class T,class keyoft>
class RBTtree
{
public:typedef treeiterator<T,T&,T*> iterator;typedef treeiterator<T, const T&, const T*> const_iterator;//指向的东西不能改变typedef RBTtreenode<T> node;iterator begin(){node* flag = root;while (flag&&flag->_left)//flag可能为nullptr{flag = flag->_left;}return iterator(flag);}iterator end(){return iterator(nullptr); //end用nullptr去构造!!!!!!!!}const_iterator begin() const{node* flag = root;while (flag && flag->_left)//flag可能为nullptr{flag = flag->_left;}return const_iterator(flag);}const_iterator end() const{return const_iterator(nullptr); //end用nullptr去构造!!!!!!!!}pair<node*, bool> insert(const T& _data)//!!!!!!!!!{if (root == nullptr){root = new node(_data);root->col = BLACK;//规定根必须是黑的return make_pair(root, true);}node* parent = nullptr; //比bst多了一个parentnode* cur = root;keyoft type;//取出data的K类型的数据while (cur){parent = cur;if (type(cur->data) < type(_data)) //这里取出key再进行比较{cur = cur->_right;}else if (type(cur->data) > type(_data)){cur = cur->_left;}else{return make_pair(cur,false);}}cur = new node(_data);cur->col = RED;//因为如果插入黑色的会使很多节点的一条路径上的黑色节点增多(相当于得罪了所有人),而插入红色则有可能只得罪父亲(如果父亲是红色的话)if (type(parent->data) < type(_data)){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;node* newnode = cur;//开始调整while (parent && parent->col == RED)//parent为黑不需要调整,如果cur变成root,parent就不存在退出循环{node* grandparent = parent->_parent;//祖父一定存在,因为只有根节点是没有祖父的,而根节点一定是黑色的if (parent == grandparent->_left){//      g//    p   unode* uncle = grandparent->_right;  //父亲在左则叔叔在右if (uncle && uncle->col == RED)     //情况一.如果叔叔存在且为红色{//变色parent->col = uncle->col = BLACK;grandparent->col = RED;//重置cur,parent,继续向上处理cur = grandparent;//变为祖父parent = cur->_parent;}else //叔叔不存在或为黑色,旋转加变色{//   g//  p// cif (cur == parent->_left)  //情况二.单旋{rotateR(grandparent);parent->col = BLACK;grandparent->col = RED;}//   g//  p//   celse      //情况三.cur==parent->_right,双旋{rotateL(parent);//经历一次左旋后变成情况二!!!!!!!!!!!(cur和parent换位置)rotateR(grandparent);cur->col = BLACK;grandparent->col = RED;}break;//调整一次就结束了,所以经历过旋转后不需要重置cur,parent,grandparent}}else{//      g//    u   p//node* uncle = grandparent->_left;  //父亲在右则叔叔在左if (uncle && uncle->col == RED){parent->col = uncle->col = BLACK;grandparent->col = RED;//cur = grandparent;parent = cur->_parent;}else{//    g//  u   p//        cif (cur == parent->_right){rotateL(grandparent);parent->col = BLACK;grandparent->col = RED;}else{//   g// u   p//    crotateR(parent);rotateL(grandparent);cur->col = BLACK;grandparent->col = RED;}break;//调整一次就结束了,所以经历过旋转后不需要重置cur,parent,grandparent}}}//1.如果parent和uncle都为RED,则可以一起变黑// 2.parent为黑不处理// 3.uncle为黑或不存在,parent为红,旋转+变色root->col = BLACK;//最后以防万一让根变为黑return make_pair(newnode, true);}void rotateL(node* parent)//左旋,(新节点插入到较高右子树的右侧)//   1.右右{node* subr = parent->_right;node* subrl = subr->_left;parent->_right = subrl;subr->_left = parent;node* ppnode = parent->_parent;parent->_parent = subr;if (subrl) //subrl可能为空!!!!!!!{subrl->_parent = parent;}if (parent == root) //即如果parent->_parent==nullptr{root = subr;subr->_parent = nullptr;}else{if (ppnode->_left == parent){ppnode->_left = subr;}else if (ppnode->_right == parent){ppnode->_right = subr;}subr->_parent = ppnode;}}void rotateR(node* parent)//右旋,(新节点插入到较高左子树的左侧)//   2.左左{node* subl = parent->_left;node* sublr = subl->_right;parent->_left = sublr;if (sublr)               //sublr可能为空!!!!!!!sublr->_parent = parent;node* ppnode = parent->_parent;subl->_right = parent;parent->_parent = subl;if (root == parent){root = subl;subl->_parent = nullptr;}else{if (ppnode->_left == parent){ppnode->_left = subl;}else if (ppnode->_right == parent){ppnode->_right = subl;}subl->_parent = ppnode;}}void inorder(){_inorder(root);}void _inorder(node* root){keyoft type;if (root == nullptr)return;_inorder(root->_left);cout << type(root->data)<< " ";_inorder(root->_right);}bool check(node* it, int blacknum, int flag){if (it == nullptr){if (blacknum == flag)return true;elsereturn false;}else if (it->col == RED && it->_parent->col == RED)//十分巧妙,因为孩子的情况有很多,但父亲不是红就是黑,所以判断父亲更合适return false;else if (it->col == BLACK)blacknum++;return check(it->_left, blacknum, flag) && check(it->_right, blacknum, flag);}bool isbalance(){return _isbalance(root);}bool _isbalance(node* root){if (root == nullptr)return true;else if (root->col == RED)return false;int blacknum = 0;int flag = 0;node* k = root;while (k){if (k->col == BLACK)flag++;k = k->_left;//这里十分巧妙,因为如果为红黑树,从某一节点到空的所有路径上的黑节点数量是一致的,所以可以先随便选一条路径,算出这一条路径上的黑节点数作为基准值,在由递归去和其他路径比较}return check(root, blacknum, flag);}private:node* root = nullptr;
};

myset.h

#include"rbt.h"
namespace zone
{template<class K>class set{public:struct setkeyoft //仿函数,用来取出红黑树节点data中的key{const K& operator()(const K& key){return key;}};//set这里的迭代器本质都是const_iterator,因为k要求无法修改typedef typename RBTtree<K, K, setkeyoft>::const_iterator iterator;//记得要使用typename告诉编译器RBTtree<K, K, setkeyoft>::iterator这个是类型,不是函数typedef typename RBTtree<K, K, setkeyoft>::const_iterator const_iterator;iterator begin()const{return it.begin();}iterator end()const{return it.end();}pair<iterator,bool> insert(const K& key){return it.insert(key);}void inorder(){it.inorder();}private:RBTtree<K,K,setkeyoft> it;};
}

mymap.h

#include"rbt.h"
namespace zone
{template<class K,class T>class map{public:struct setkeyoft{const K& operator()(const pair<K, T>& key){return key.first;}};//map这里的迭代器则使用的是iterator,因为k要求无法修改,但v可以修改,所以可以直接初始化时用pair<const K, T>typedef typename RBTtree<K, pair<const K, T>, setkeyoft>::iterator iterator;typedef typename RBTtree<K, pair<const K, T>, setkeyoft>::const_iterator const_iterator;pair<iterator, bool> insert(const pair<K, T>& key){return it.insert(key);}T& operator[](const K& key){pair<iterator, bool>ret = insert(make_pair(key,T()));//insert返回一个pair,first是iterator,second是bool类型return ret.first->second;}iterator begin(){return it.begin();}iterator end(){return it.end();}void inorder(){it.inorder();}private:RBTtree<K,pair<const K,T>, setkeyoft> it;};
}

test.cpp

#include<iostream>
#include<vector>
#include<string>using namespace std;#include"myset.h"
#include"mymap.h"void test1()
{zone::set<int> it;it.insert(1);it.insert(3);it.insert(5);it.insert(2);it.insert(4);zone::set<int>::iterator arr = it.begin();while (arr!=it.end() ){cout << *arr << " ";++arr;}//it.inorder();}void test2()
{zone::map<string,string> it;it.insert(make_pair("sort","排序"));it.insert(make_pair("right", "右"));it.insert(make_pair("left", "左"));it.insert(make_pair("middle", "中"));zone::map<string,string>::iterator arr = it.begin();while (arr != it.end()){arr->second += 'x';//map的v可修改cout << arr->first << " ";++arr;}//it.inorder();}void test3()
{string arr[] = { "香蕉","苹果","西瓜","苹果","苹果","西瓜","苹果"};zone::map<string, int> it;for (auto e : arr){it[e]++;}for (auto k : it){++k.second;cout << k.first << ":" << k.second << endl;}
}
int main()
{test3();return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

19.第二阶段x86游戏实战2-寻找寻路call

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要…

什么是reactor以及其三种版本

写在前面 本文来看下什么是reactor以及其三种版本。 1&#xff1a;什么是reactor以及其三种版本 为了更好的理解什么是reactor&#xff0c;我们结合现实生活中的例子来看下。 翠花是个貌美如花的姑娘&#xff0c;人称赛东施&#xff0c;她的梦想是嫁给王子&#xff0c;可是天…

hystrix微服务部署

目录 一.启动nacos和redis 1.查看是否有nacos和redis 二.开始项目 1.hystrix1工程&#xff08;修改一下工程的注册名字&#xff09; 2.运行登录nacos网站查看运行效果&#xff08;默认密码nacos,nacos&#xff09; 3.开启第二个项目 hystrix2工程 4.关闭第二个项目 hyst…

SpringBoot学习笔记(2)

1.静态文件访问 使用IDEA创建Spring Boot项目&#xff0c;会默认创建出classpath:/static/目录&#xff0c;静态资源一般放在这个目录下即可。 如果默认的静态资源过滤策略不能满足开发需求&#xff0c;也可以自定义静态资源过滤策略。 1.1直接访问 在application.properties中…

Coze:如何使用主页对话框?

你好&#xff0c;我是三桥君 我们今天要介绍的功能模块是“主页对话框”。 目录 访问官网 登录首页 基本功能 主页对话框 第一个功能&#xff1a;如何与自己收藏的机器人进行对话&#xff1f; 第二个功能&#xff1a;如何请求主页对话框的机器人帮助创建一个新的机器人&#x…

【北京迅为】《STM32MP157开发板嵌入式开发指南》- 第十八章 Linux编写第一个自己的命令

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7单核cortex-M4异构处理器&#xff0c;既可用Linux、又可以用于STM32单片机开发。开发板采用核心板底板结构&#xff0c;主频650M、1G内存、8G存储&#xff0c;核心板采用工业级板对板连接器&#xff0c;高可靠&#xff0c;牢固耐…

【算法系列-数组】螺旋矩阵(模拟)

【算法系列-数组】螺旋矩阵(模拟) 文章目录 【算法系列-数组】螺旋矩阵(模拟)1. 螺旋矩阵II(LeetCode 59)1.1 思路分析&#x1f3af;1.2 解题过程&#x1f3ac;1.3 代码示例&#x1f330; 2. 螺旋矩阵(LeetCode 54)2.1 思路分析&#x1f3af;2.2 解题过程&#x1f3ac;2.3 代码…

如何使用ssm实现基于web的网站的设计与实现+vue

TOC ssm756基于web的网站的设计与实现vue 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&#xff0c;规范…

极端天气道路目标检测数据集 3400张 带标注 VOC YOLO 6类

分类名: (图片张数&#xff0c;标注个数) car: (3210&#xff0c; 13654) truck: (1168&#xff0c;1629) per son: (1517&#xff0c;4359) bicyc le: (334, 589) bus: (381&#xff0c; 439) motorcycle: (164, 214) 总数: (3404, 20884) 总类(nc): 6类 极端天气道路目标检测…

09_OpenCV彩色图片直方图

import cv2 import numpy as np import matplotlib.pyplot as plt %matplotlib inlineimg cv2.imread(computer.jpeg, 1) img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) plt.imshow(img) plt.show()plot绘制直方图 plt.hist(img.ravel(), 256) #ravel() 二维降一维 256灰度级…

pycharm汉化插件无法使用也无法卸载的解决方法

pycharm汉化插件无法使用也无法卸载的解决方法 本文目录&#xff1a; 一、故障描述 二、故障解决 零、时光宝盒 学习没有可能一帆风顺&#xff0c;我们都是在不断遇到的各种突发问题&#xff0c;不断努力解决的过程中成长。 前几天&#xff0c;我发现家里的网络晚上12点左右开…

初识算法 · 双指针(3)

目录 前言&#xff1a; 和为s的两数之和 题目解析&#xff1a; ​编辑 算法原理&#xff1a; 算法编写&#xff1a; 三数之和 题目解析 算法原理 算法编写 前言&#xff1a; 本文通过介绍和为S的两数之和&#xff0c;以及三数之和&#xff0c;对双指针算法进行深一步…

欧科云链OKLink相约TOKEN2049:更全面、多元与安全

过去几日&#xff0c;OKLink 与全球 Web3 从业者与爱好者们相约狮城。在多场激动人心的活动上分享了我们的产品进展、有关于链上数据的专家观点以及打磨产品的经验。同时也听到了很多来自行业的宝贵声音。跟随我们的脚步&#xff0c;捕捉这充实一周的精彩瞬间&#xff1a; 1、…

netty之基础aio,bio,nio

前言 在Java中&#xff0c;提供了一些关于使用IO的API&#xff0c;可以供开发者来读写外部数据和文件&#xff0c;我们称这些API为Java IO。IO是Java中比较重要知识点&#xff0c;且比较难学习的知识点。并且随着Java的发展为提供更好的数据传输性能&#xff0c;目前有三种IO共…

5G NR SSB简介

文章目录 SSB介绍SSB波束扫描 SSB介绍 5G NR 引入了SSB 这个概念&#xff0c;同步信号和PBCH块(Synchronization Signal and PBCH block, 简称SSB) 它由主同步信号(Primary Synchronization Signals, 简称PSS)、辅同步信号(Secondary Synchronization Signals, 简称SSS)、PBCH…

【分页】Spring Boot 列表分页 + javaScript前台展示

后端&#xff1a; 准备好查询实体与分页实体 1、分页工具实体 package com.ruoyi.dms.config;import com.alibaba.nacos.api.model.v2.Result; import lombok.Data;import java.io.Serializable; import java.util.List;/*** author 宁兴星* description: 列表返回结果集*/ …

【10】纯血鸿蒙HarmonyOS NEXT星河版开发0基础学习笔记-泛型基础全解(泛型函数、泛型接口、泛型类)及参数、接口补充

序言&#xff1a; 本文详细讲解了关于ArkTs语言中的泛型&#xff0c;其中包含泛型函数、泛型接口、泛型约束、泛型类及其中参数的使用方法&#xff0c;补充了一部分接口相关的知识&#xff0c;包括接口的继承和具体实现&#xff0c;也写到了一些边边角角的小知识&#xff0c;剩…

详细介绍:API 和 SPI 的区别

文章目录 Java SPI (Service Provider Interface) 和 API (Application Programming Interface) 的区别详解目录1. 定义和目的1.1 API (Application Programming Interface)1.2 SPI (Service Provider Interface) 2. 使用场景2.1 API 的应用场景2.2 SPI 的应用场景 3. 加载和调…

jmeter学习(1)线程组与发送请求

1、线程组 执行顺序 &#xff1a;setUp线程组 > 线程组 > tearDown线程组 2、 发送请求 可以发送http、java、dubbo 请求等 下面讲解发送http 1&#xff09;Http请求默认值 作用范围是该线程组下的所有HTTP请求&#xff0c;如果http请求设置的与默认值冲突&#xff0…

PC端微信小程序如何调试?

向往常一样运行开微信小程序开发者工具 如果只弹出pc端小程序&#xff0c;没有出现调试的界面&#xff1a;点击胶囊按钮的三个…选择重新进入小程序 即可依次展开相应的功能调试&#xff0c;改完代码没反应再刷新看看&#xff0c;再没反应就再次重新点击编译并自动调试。