集合篇11:leetcode-特殊篇1

目录

  • 1.LRU内存缓冲的实现
  • 2.LFU缓存结构设计
  • 3.C++ 实现字节对齐
  • 4.C++智能指针的实现
  • 5. itoa()函数和atoi()函数的底层实现
  • 6.手写string类
  • 7. 饿汉和懒汉单例模式

1.LRU内存缓冲的实现

题目

看来半天没有理解题意,懂了题意就还行:

  • get(key) - 如果键存在于缓存中,则获取键的值(总是正数,并将其调整到最前面),否则返回 -1。
  • put(key, value) - 如果键已存在,则变更其值;如果键不存在,请插入键值对。
  • 当缓存达到其容量时,则应该在插入新项之前,使最不经常使用的项无效。在此问题中,当存在平局(即两个或更多个键具有相同使用频率)时,应该去除最久未使用的键。

方法一:我使用双向链表实现,其双向链表实现类似于STL源码中的双向链表;
待优化;

class LRUCache {
     
public:
    struct  lruNode
    {
     
        int k;
        int v;
        lruNode * next;
        lruNode *pre;
        lruNode(int i,int j):k(i),v(j),next(nullptr),pre(nullptr){
     }
    };
    LRUCache(int capacity) {
     
        cap=capacity;
        head->next=head;
        head->pre=head;
    }
    
    int get(int key) {
     
        p=head->next;
        while(p!=head)
        {
     
            if(p->k==key)
            {
     
                p->next->pre=p->pre;
                p->pre->next=p->next;
                
                p->next=head->next;
                head->next=p;
                p->next->pre=p;
                p->pre=head;
                return p->v;
            }
            p=p->next;
        } 
        return -1;
    }
    
    void put(int key, int value) {
     
        lruNode * node=new lruNode(key,value);
        int temp=get(key);
        if(temp!=-1)
        {
     
            head->next->v=value;
            return ;
        }
        if(counts==cap)
        {
     
            if(counts==1)
            {
     
                head->next=head;
                head->pre=head;
            }
            else
            {
     
                head->pre=head->pre->pre;
                head->pre->next=head;
            }
            counts--;
        }
        node->next=head->next;
        node->pre=head;
        node->next->pre=node;
        head->next=node;
        counts++;
    }
private:
    int cap;
    lruNode * head=new lruNode(0,0);
    lruNode * p;
    int counts=0;
};

方法二:直接使用STL容器

struct node
{
     
    int key;
    int val;
    node(int k,int v):key(k),val(v){
     }
};
class LRUCache
{
     
private:
    int capacity;
    map<int,list<node>::iterator> mp;
    list<node> clist;
public:
    LRUCache(int c):capacity(c){
     };
    void set(int key,int value)
    {
     
        if(capacity==0) return ;
        if(mp.find(key)==mp.end())
        {
     
            if(capacity==mp.size())
            {
     
                mp.erase(clist.back().key);
                clist.pop_back();
            }
            clist.push_front(node(key,value));
            mp[key]=clist.begin();
        }
        else
        {
     
            clist.erase(mp[key]);
            mp[key]->val=value;
            clist.push_front(node(key,value)); 
        }
    }
    int get(int key)
    {
     
        if(capacity==0) return -1;
        if(mp.find(key)==mp.end()) return -1;
        int val=mp[key]->val;
        clist.erase(mp[key]);
        clist.push_front(node(key,val));
        return val;
    }
};
class Solution {
     
public:
    vector<int> LRU(vector<vector<int> >& operators, int k) {
     
        vector<int> res;
        LRUCache cache(k);
        for(int i=0;i<operators.size();++i)
        {
     
            if(operators[i].size()==3)
                cache.set(operators[i][1],operators[i][2]);
            else
                res.push_back(cache.get(operators[i][1]));
        }
        return res;
    }
};

2.LFU缓存结构设计

题目

方法1:使用一个双哈希表实现;(下面只是一个理清思路稍后修改)

//C++ list中begin指向第一个元素;
//push_back() 尾部插  push_front()头部插入 empty()判断list是否为空   clear()清空list中的所有元素
//pop_back() 尾部删除  pop_front()头部删除   reverse()完成list逆置
struct node
{
     
    int key;
    int val;
    int fre;
    node(int k,int v,int f):key(k),val(v),fre(f){
     }
};
class LFUCache
{
     
private:
    map<int,list<node>::iterator> mp;
    map<int,list<node> > frenode;
    int capacity;
    int minfre;
public:
    LFUCache(int c):capacity(c),minfre(0){
     }
    void set(int key,int value)
    {
     
        if(capacity==0)
            return ;
        if(mp.find(key)==mp.end())
        {
     
            if(capacity==mp.size())
            {
     
                mp.erase(frenode[minfre].back().key);
                frenode[minfre].pop_back();
                if(frenode[minfre].size()==0)
                {
     
                    frenode.erase(minfre);
                }
            }
            frenode[1].push_front(node(key,value,1));
            mp[key]=frenode[1].begin(); //注意迭代器和元素节点不一样
            minfre=1;
        }
        else
        {
     
            int val=mp[key]->val;
            int fre=mp[key]->fre;
            frenode[fre].erase(mp[key]); //这里注意,而不是释放fre对于链表的头或尾
            if(frenode[fre].size()==0)
            {
     
                frenode.erase(fre);
                if(fre==minfre)
                    minfre++;
            }
            frenode[fre+1].push_front(node(key,value,fre+1)); 
            mp[key]=frenode[fre+1].begin(); 
        }
    }
    int get(int key)
    {
     
        if(capacity==0) return -1;
        if(mp.find(key)==mp.end()) return -1;
        int val=mp[key]->val;
        int fre=mp[key]->fre;
        frenode[fre].erase(mp[key]);
        if(frenode[fre].size()==0)
        {
     
            frenode.erase(fre);
            if(fre==minfre) //为什么这里不用判断相等;
                minfre++; 
        }
        frenode[fre+1].push_front(node(key,val,fre+1));
        mp[key]=frenode[fre+1].begin();
        return val;
    }
};

class Solution {
     
public:
    vector<int> LFU(vector<vector<int> >& operators, int k) {
     
        LFUCache cache(k);
        vector<int> res;
        for(int i=0;i<operators.size();++i)
        {
     
            if(operators[i].size()==3)
            {
     
                cache.set(operators[i][1],operators[i][2]);
            }
            else
            {
     
                res.push_back(cache.get(operators[i][1]));
            }
        }
        return res;
    }
};

3.C++ 实现字节对齐

#include
using namespace std;

void* aligned_malloc(size_t required_bytes, size_t alignment)
{
      // 17            16 
//sizeof(void*)取决于编译器 分配内存的时候需要多分配一些空间用以调整指针的开头,使得指针的地址是对齐的
    int offset = alignment - 1 + sizeof(void*); //offset这个是内存对齐需要的内存大小
//void* 是一个指针,用来指向对象未知;
    void* p1 = (void*)malloc(required_bytes + offset);
    if (p1 == NULL)
        return NULL;
//void** 一个指针,它指向一个void*型的数据结构
    void** p2 = (void**)( ( (size_t)p1 + offset ) & ~(alignment - 1) ); 
//任何一个数与~(a-1)按位与就是该数变为a的倍数;
//左半部分保证处理后的值,这个值除以a得到的商,右半部分相当于把余数给去除掉;
//二级指针-1表示往前移动void*大小地址;
    p2[-1] = p1;
    return p2; //返回实例对象真正的地址;
}
void aligned_free(void *p2)
{
     
    void* p1 = ((void**)p2)[-1];
    free(p1);
}

4.C++智能指针的实现

#include
using namespace std;

template<class T>
class smartPtr
{
     
public:
    smartPtr(T *p);
    ~smartPtr();
    smartPtr(const smartPtr<T> &obj);
    smartPtr<T>& operator=(const smartPtr<T> &obj);
private:
    T* ptr;
    int *count;
};

template<class T>
smartPtr<T>::smartPtr(T* p):ptr(p)
{
     
    count=new int(1);
    cout<<"init is called!"<<endl;
}
template<class T>
smartPtr<T>::~smartPtr()
{
     
    if(--(*count)==0)
    {
     
        delete ptr;
        delete count;
        cout<<"Destructor is called!"<<endl;
    }
}
template<class T>
smartPtr<T>::smartPtr(const smartPtr<T> &obj)
{
     
    ptr=obj.ptr;
    count=obj.count;
    ++(*count);
    cout<<"copy constructor is called!"<<endl;
}
template<class T>
smartPtr<T>& smartPtr<T>::operator=(const smartPtr<T> &obj)
{
     
    ++(*obj.count);
    if(--(*count)==0)
    {
     
        delete ptr;
        delete count;
        cout<<"left side object is deleted!"<<endl;
    }
    ptr=obj.ptr;
    count=obj.count;
    cout<<"assignment operator overloaded is called!"<<endl;
    return *this;
} 

int main()
{
     
   smartPtr<int> p1(new int(0)); //构造析构函数
   p1=p1; //重载赋值运算符号
   smartPtr<int> p2(p1); //重载赋值运算符函数
   smartPtr<int> p3(new int(1)); //
   p3=p1; //语义转移
   return 0;
}

5. itoa()函数和atoi()函数的底层实现

itoa(number, string, 10); 
//itos函数,整形转字符串,参数1,需要转换的value,参数2字符串指针,参数3进制;
int atoi(const char *nptr); 
//atoi函数, 字符串转为整数;
#include
using namespace std;
void intToString(int n,char str[])  //itoa函数
{
     
    int i=0;
    int sign=1;
    if(n<0)
    {
     
        sign=-sign;
        n=-n;
    }
    int temp=0;
    while(n>0)
    {
     
        temp=n%10;
        n=n/10;
        str[i++]= temp+'0';
    }
    if(sign==-1)
        str[i++]='-';
    str[i]='\0';
    i--;
    int j=0;
    while(j<i)
    {
     
        swap(str[j++],str[i--]);
    }
    return ;
}
int stringToInt(char ch[])  //atoi
{
     
    int i=0;
    int num=0;
    int sign=1;
    for(;isspace(ch[i]);++i);
    if(ch[i]== '+')
        i++;
    else if(ch[i]=='-')
    {
     
        i++;
        sign=-1;
    }
    while(ch[i]!='\0')
    {
     
        if(ch[i]>= '0' && ch[i]<='9')
        {
     
            int t=ch[i]-'0';
            num=num*10+t;
            i++;
        }
        else
        {
     
            return -1;
        }
        if(num<0)
            return -1;
    }
    return sign*num;
}

int main()
{
     
    int n;
    cin>>n;
    char *chs=new char(11);
    intToString(n,chs);
    int i=0;
    while(chs[i]!='\0')
    {
     
        cout<<chs[i++];
    }
    cout<<endl;
    int res=stringToInt(chs);
    cout<<res<<endl;
    return 0;
}

6.手写string类

实现四个函数即可
默认构造函数;
拷贝构造函数;
重载赋值运算符函数;
析构函数;

#include
using namespace std;
class myString
{
     
public:
    myString(const char* s=NULL);
    ~myString();
    myString(const myString &mystr); //注意1
    myString& operator=(const myString &mystr);
private:
    char *str; //注意2 而不是const
};
myString::myString(const char* s)
{
     
    if(s==NULL)
    {
     
        str=new char(1);
        str[0]='\0'; //注意3
    }
    else
    {
     
        str=new char(strlen(s)+1);
        strcpy(str,s);
    }
}
myString::~myString()
{
     
    delete [] str;
    str=NULL;
}
myString& myString::operator=(const myString& mystr)  //注意4
{
     
    if(this ==  &mystr)
        return *this;
    delete [] str;
    int len= strlen(mystr.str);
    str=new char(len+1);
    strcpy(str,mystr.str);
    return *this;
}
myString::myString(const myString& mystr)  //注意5
{
     
    int len=strlen(mystr.str);
    str=new char(len+1);
    strcpy(str,mystr.str);
}

7. 饿汉和懒汉单例模式

  • 饿汉模式
#include
using namespace std;
class singleTon
{
     
private:
    static singleTon* instance;
    int val;
    singleTon(int x):val(x)
    {
     
        cout<<"init successful..."<<endl;
    }
public:
    static singleTon* getInstance()
    {
     
        return instance;
    }
    static void Destroy()
    {
     
        delete instance;
        instance=NULL;
        cout<<"Destroy successful..."<<endl;
    }
};
//变量类型  作用域解析符号
singleTon* singleTon::instance=new singleTon(0);
int main()
{
     
    singleTon* test1=singleTon::getInstance();
    singleTon* test2=singleTon::getInstance();
    cout<<test1<<endl;
    cout<<test2<<endl;
    singleTon::Destroy();
    return 0;
}
  • 懒汉模糊
#include
using namespace std;

class singleTon
{
     
private:
    static singleTon* instance;
    //mutex mtx;
    singleTon()
    {
     
        cout<<"init successful..."<<endl;
    }
public:
    static singleTon* getInstance()
    {
     
        if(instance==NULL)
        {
     
            //lock_guard locker(mtx);
            if(instance==NULL)
                instance=new singleTon();
        }
        else
        {
     
            cout<<"init completed..."<<endl;
        }
        return instance;
    }
    static  void Destroy()
    {
     
        delete instance;
        cout<<"Destroy successful..."<<endl;
        instance=NULL;
    }
}; 
singleTon* singleTon::instance =NULL;
int main()
{
     
    singleTon* test1=singleTon::getInstance();
    singleTon* test2=singleTon::getInstance();
    cout<<test1<<endl;
    cout<<test2<<endl;
    singleTon::Destroy();
    return 0;
}

你可能感兴趣的:(编程集合篇)