小米二面
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
char* Serialize(TreeNode *root) {
queue<TreeNode*> q;
q.push(root);
string res;
while(!q.empty()){
int n=q.size();
for(int i=0;i<n;i++){
TreeNode *cur=q.front();
q.pop();
if(cur==nullptr){
res+="#";
res+=",";
continue;
}else{
res+=to_string(cur->val);
res+=",";
}
q.push(cur->left);
q.push(cur->right);
}
}
char *ret=new char[res.size()+1];
strcpy(ret, res.c_str());
return ret;
}
TreeNode* Deserialize(char *str) {
string s=str;
if(s[0]=='#')
return nullptr;
queue<TreeNode*> q;
TreeNode* head=new TreeNode(stoi(s));
s=s.substr(s.find_first_of(',')+1);
q.push(head);
while(!q.empty()){
TreeNode* cur=q.front();
q.pop();
if(s[0]=='#')
cur->left=nullptr;
else{
cur->left=new TreeNode(stoi(s));
q.push(cur->left);
}
s=s.substr(s.find_first_of(',')+1);
if(s[0]=='#')
cur->right=nullptr;
else{
cur->right=new TreeNode(stoi(s));
q.push(cur->right);
}
s=s.substr(s.find_first_of(',')+1);
}
return head;
}
};
在使用new申请空间分配时,系统会有记录表记录两个信息:分配空间的地址和分配空间的大小(以字节为单位),在使用delete收回内存空间时,首先系统会在记录表中找需要delete的地址:如果找到,就收回相应大小的内存空间,并在记录表中删除该条记录;如果未找到,则delete失败,运行报错。
对于类对象的delete操作,进行delete操作时首先会调用该类的析构函数,然后再收回内存空间。如果类对象是数组,那么如果使用delete,那么就只会析构数组首地址,然后当程序运行结束后收回内存;如果使用delete [],那么就会依次调用类对象数组中的析构函数,然后收回内存空间。
#include
using namespace std;
int main(){
int i=97;
char c='c';
cout<<i<<" "<<c<<" ";
c=static_cast<char>(i);
cout<<c<<endl;
return 0;
}
2)const_cast:用于去除变量的const属性;
3)ynamic_cast:主要用于类层次间的转换,还可以用于类之间的交叉转换;dynamic_cast具有类型检查的功能,比static_cast更安全;
4)reinterpret_cast(直接从二进制位进行复制,不安全的转换):用于指针类型间的强制转换;用于整数和指针类型间的强制转换;
#include
template<class T>
class SharedPtr{
private:
T* _ptr;
int* _count;
mutex* _mt;//防止多线程安全问题
private:
void AddCount(){
_mt->lock();
(*_count)++;
_mt->unlock();
}
void ReleasePtr(){
//是否需要删除锁
bool flag = true;
//加锁,防止线程安全
_mt->lock();
(*_count)--;
if ((*_count) == 0){
delete _ptr;
delete _count;
flag = false;//锁要在外面删除,需要解锁
}
_mt->unlock();
//删除锁
if (flag == false){
cout << "delete" << endl;
delete _mt;
}
}
public:
//将外面申请的资源,托管给类的成员
SharedPtr(T* ptr = nullptr)
:_ptr(ptr)
, _count(new int(1))//申请一份资源,初始化为1
, _mt(new mutex)
{}
SharedPtr(SharedPtr<T>& sp){
_ptr = sp._ptr;
_count = sp._count;
_mt = sp._mt;
AddCount();
}
SharedPtr<T>& operator=(SharedPtr<T>& sp){
//防止自己给自己赋值
if (this != &sp){
//是否管理资源
if (_ptr){
ReleasePtr();
}
_ptr = sp._ptr;
_count = sp._count;
_mt = sp._mt;
AddCount();
}
return *this;
}
T& operator*(){
return *_ptr;
}
T* operator->(){
return _ptr;
}
//在对象析构时,自动释放资源
~SharedPtr(){
ReleasePtr();
}
};
中兴一面
你对C++面向对象的理解
见链接
深拷贝和浅拷贝
浅拷贝:也称位拷贝,编译器只是将对象中的值拷贝过来。如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放,以为还有效,所以 当继续对资源进项操作时,就会发生发生了访问违规。
stl中的数据结构和算法之间用什么进行连接
迭代器
迭代器你怎么理解的
迭代器:提供一种方法,使之能够依序寻访某个容器所含的各个元素,而又无需暴露该容器的内部表示方式。每个容器都有自己专属的迭代器。
一个map
#include
#include
using namespace std;
int main(){
map<int, map<int, int> > val;
int Max=INT_MIN;
map<int, int> res;
for(map<int, map<int, int> >::iterator it=val.begin();it!=val.begin();it++){
if(Max<it->first){
Max=it->first;
res=it->second;
}
}
for(map<int, int>::iterator iter=res.begin();iter!=res.end();iter++){
cout<<iter->first<<" "<<iter->second<<endl;
}
return 0;
}