ARST第四周打卡

Algorithm : 做一个 leetcode 的算法题

/////////////////////////////////////////////////////////////////////////////////////////////
// 1.1 题目一:赋值运算符函数

class CMyString
{
public:
    // 默认函数
    CMyString();
    CMyString(const CMyString&);
    CMyString& operator=(const CMyString&);
    ~CMyString();

    void SetString(const char* pszStr)
    {
        // 释放旧数据
        Destroy();
        CopyData(pszStr);
    }

    void Print()
    {
        if (m_pszData)
        {
            cout << m_pszData << endl;
        }
    }

    void Destroy()
    {
        if (m_pszData)
        {
            delete [] m_pszData;
            m_pszData = NULL;
        }
    }

    void CopyData(const char* pszStr)
    {
        if (pszStr)
        {
            int iLen = strlen(pszStr);
            m_pszData = new char[iLen + 1];
            strncpy(m_pszData, pszStr, iLen + 1);
            m_pszData[iLen] = '\0';
        }
    }

private:
    char* m_pszData;
};

// 默认构造函数
CMyString::CMyString()
    :m_pszData(NULL)
{

}

//拷贝构造函数
CMyString::CMyString(const CMyString& other)
{
    cout << "CMyString Copy Constructor!!!!" << endl;
    // 释放旧数据
    //Destroy();    // 这里不能释放,因为没有初始化

    CopyData(other.m_pszData);
}

//赋值操作符
CMyString& CMyString::operator=(const CMyString& other)
{
    cout << "CMyString Assignment Operator!!!!" << endl;

#if 0   // 初级程序员!!!!
    if (this != &other)
    {
        Destroy();
        CopyData(other.m_pszData);
    }

#else 
    //高级程序员 需要考虑异常 --> 内存不足,导致new char 抛出异常
    // 实现异常安全性:
    // 1.先new分配新内容在使用delete释放旧内容 --> 确保抛出异常时原来的数据不会被改变!!!
    // 2.先创建一个临时实例,再交换临时实例和原来的内容  --> 推荐这种方法!!!!
    if (this != &other)
    {
        // 调用拷贝构造函数创建临时实例
        CMyString strTmp(other);
        char * pTmp = strTmp.m_pszData;
        strTmp.m_pszData = m_pszData;   // strTmp调用析构函数时,会释放原来实例中的m_pszData!!!!
        m_pszData = pTmp;
    }

#endif
    return *this;

}

//析构函数
CMyString::~CMyString()
{
    Destroy();
}


////////////////////////////////////////////////////////////////////////////////////////////////////////
// 1.2 题目二:单例模式测试

extern CMutex g_stMutex;    // 这个在ThreadTest.cpp中定义了,这个声明一下!!!!

class CSingletonTest
{
public:
    CSingletonTest() :m_iCount(0){}
    ~CSingletonTest(){}
    void AddCount() { m_iCount++; }
    void SubCount() { m_iCount--; }
    int GetCount() { return m_iCount; }

private:
    int m_iCount;
};

class CSingleton_1
{
protected:
    // 禁止外部调用这几个函数
    CSingleton_1(){}
    ~CSingleton_1(){}
    CSingleton_1(const CSingleton_1&);
    CSingleton_1& operator=(const CSingleton_1&);

};

///////////////////////////////////////////////////////
// 懒汉模式 
//类加载进来,没有对象,只有调用了getInstance方法时,才会创建对象。
//延迟加载形式。 并发过程中存在安全隐患。

template <typename TYPE>
class CSingleton_2 : public CSingleton_1
{
public:
    static TYPE* GetInstance()
    {
        if (NULL == m_pSingleton)
        {
            cout << "Try Lock --------------->" << endl;
            m_pSingleton = new CSingleton_2<TYPE>();
        }

        return &m_pSingleton->m_stInstance;
    }
private:
    static CSingleton_2<TYPE>* m_pSingleton;
    TYPE m_stInstance;

private:
    // 自动释放内存(不需要定义也可以,程序结束是系统会自动回收)
    class CGarbo
    {
    public:
        ~CGarbo()
        {
            if (m_pSingleton)
            {
                delete m_pSingleton;
                m_pSingleton = NULL;
            }
        }
    };

    static CGarbo garbo;
};

template <typename TYPE>
CSingleton_2<TYPE>* CSingleton_2<TYPE>::m_pSingleton;

typedef CSingleton_2<CSingletonTest> SingletonTest2;

////////////////////////////////////////////////////////////
// 加锁的懒汉实现
template <typename TYPE>
class CSingleton_3 : public CSingleton_1
{
public:
    static TYPE* GetInstance()
    {
        if (NULL == m_pSingleton)
        {
            cout << "Try Lock --------------->" << endl;
            CLock lock(g_stMutex);
            if (NULL == m_pSingleton)
            {
                m_pSingleton = new CSingleton_3<TYPE>();
            }
        }
        return &m_pSingleton->m_stInstance;
    }
private:
    static CSingleton_3<TYPE>* m_pSingleton;
    TYPE m_stInstance;
};

template <typename TYPE>
CSingleton_3<TYPE>* CSingleton_3<TYPE>::m_pSingleton;

typedef CSingleton_3<CSingletonTest> SingletonTest3;


////////////////////////////////////////////////////////////////
// 饿汉模式
template <typename TYPE>
class CSingleton_4 : public CSingleton_1
{
public:
    static TYPE* GetInstance()
    {
        //return &(const_cast<CSingleton2<TYPE>*>(m_pSingleton)->m_stInstance);
        return &(const_cast<CSingleton_4<TYPE>*>(m_pSingleton)->m_stInstance);
    }
private:
    const static CSingleton_4<TYPE>* m_pSingleton;
    TYPE m_stInstance;
};

template <typename TYPE>
const CSingleton_4<TYPE>* CSingleton_4<TYPE>::m_pSingleton = new CSingleton_4<TYPE>;
typedef CSingleton_4<CSingletonTest> SingletonTest4;


////////////////////////////////////////////////////////////////////////
// 多线程测试函数
template <typename TYPE>
class CSingletonThreadTest : public CThread
{
public:
    CSingletonThreadTest(const string& str) :m_szThreadName(str) {}
    ~CSingletonThreadTest(){}

    virtual void Run()
    {
        for (int i = 0; i < 5000; i++)
        {
            //CLock Lock(g_stMutex);
            TYPE::GetInstance()->AddCount();
            //cout << m_szThreadName << ": " << TYPE::GetInstance()->GetCount() << endl;
        }
    }

private:
    string m_szThreadName;
};

template <typename TYPE>
void SingletonTestFunc()
{
    //double dStart = clock();
    // 1.单线程测试
    TYPE::GetInstance()->AddCount();
    TYPE::GetInstance()->AddCount();
    cout << typeid(TYPE::GetInstance()).name() << ": Count = " << TYPE::GetInstance()->GetCount() << endl;

    CSingletonThreadTest<TYPE> Test1("Test1");
    Test1.Start();
    CSingletonThreadTest<TYPE> Test2("Test2");
    Test2.Start();
    CSingletonThreadTest<TYPE> Test3("Test3");
    Test3.Start();
    CSingletonThreadTest<TYPE> Test4("Test4");
    Test4.Start();
    CSingletonThreadTest<TYPE> Test5("Test5");
    Test5.Start();

    CT_SLEEP(10);

    cout << "SingletonTestFunc : " << TYPE::GetInstance()->GetCount() << endl;
    //cout << "花费时间: " << (clock() - dStart) / CONST_1000 << endl;
}

void SingletonPatternTestFunc()
{
    cout << "\n\n --------------- SingletonPatternTestFunc Start -------------->" << endl;
    
    //CSingleton_2TestFunc();

    SingletonTestFunc<SingletonTest2>();

    cout << "===================================================>>>" << endl;

    SingletonTestFunc<SingletonTest3>();

    cout << "===================================================>>>" << endl;
    SingletonTestFunc<SingletonTest4>();


    cout << "\n\n --------------- SingletonPatternTestFunc End -------------->" << endl;

}


//////////////////////////////////////////////////////////////////////////////
// 1.3 题目三:二维数组中的查找

//二位数组查找 题目描述
//在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。
//请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
bool FindNum(int target, vector<vector<int> > vect)
{
    int iRow = vect.size();
    int iCol = vect[0].size();
    
    //从左上角开始遍历
    int i = 0, j = iCol - 1;
    while (i <= iRow - 1 && j >= 0) //保证数组不能越界
    {
        if (vect[i][j] > target)
        {
            j--;
        }
        else if (vect[i][j] < target)
        {
            i++;
        }
        else
        {
            return true;
        }
    }

    return false;
}


//////////////////////////////////////////////////////////////////////////////
// 1.4 题目四:替换空格

// 请实现一个函数,把字符串中每个空格替换成"%20";例如输入:"We Are Happy!" --> "We%20Are%20Happy!"
//时间复杂度O(n), 空间复杂度O(1)
char* StrReplace(char* pszStr, int iLen, char ch, const char* pszReStr)
{
    assert(pszStr != NULL && pszReStr != NULL &&iLen >= 0);

    char* pTmp = pszStr;
    int iFindNum = 0;

    // 1.查找字符串中ch个数
    while (*pTmp != '\0')
    {
        if (*pTmp++ == ch)
        {
            iFindNum++;
        }
    }

    // 2.新字符串长度
    int iOldLen = strlen(pszStr);
    int iReLen = strlen(pszReStr);
    int iNewLen = iOldLen + (iReLen - 1)* iFindNum; // 这里减1 待替换字符串长度 - 原来字符长度
    if (iNewLen > iLen)
    {
        return NULL;
    }

    // 3.从后往前赋值字符串
    // 这里为什么不用 i = iOldLen - 1;  --> 复制最后的'\0';
    for (int i = iOldLen; i >= 0 && iNewLen > i; i--)
    {
        if (pszStr[i] == ch)
        {
            for (int j = iReLen - 1; j >= 0; j--)
            {
                pszStr[iNewLen--] = pszReStr[j];
            }
        }
        else
        {
            pszStr[iNewLen--] = pszStr[i];
        }
    }

#if 0
    while (iOldLen >= 0 && iNewLen > iOldLen)
    {
        if (pszStr[iOldLen] == ch)
        {
            for (int i = iReLen - 1; i >= 0; i--)
            {
                pszStr[iNewLen--] = pszReStr[i];
            }
        }
        else
        {
            pszStr[iNewLen--] = pszStr[iOldLen];
        }

        iOldLen--;
    }

#endif

    return pszStr;

}


///////////////////////////////////////////////////////////////////
// 7. 与题目四相关题目
// 有两个排序数组A1, A2, A1的末尾有足够多的的空间容纳A2,实现一个函数,把A2中所有数字插入A1中且所有的数字的有序的!

//方法一:从前往后比较,需要额外的空间
//时间复杂度O(2n), 空间复杂度O(n)
void MergeTwoArray1(int aiArrayA[], int iNumA, int aiArrayB[], int iNumB)
{
    const int MAX_ARRAY_COUNT = iNumA + iNumB;
    vector<int> vect(MAX_ARRAY_COUNT, 0);

    int i = 0, j = 0, k = 0;
    
    // 1. 比较两个数组,把较小的加入新的数组
    while (i < iNumA &&j < iNumB)
    {
        if (aiArrayA[i] < aiArrayB[j])
        {
            vect[k++] = aiArrayA[i++];
        }
        else
        {
            vect[k++] = aiArrayB[j++];
        }
    }

    // 2.把剩余的元素加到新数组
    while (i < iNumA)
    {
        vect[k++] = aiArrayA[i++];
    }

    while (j < iNumB)
    {
        vect[k++] = aiArrayB[j++];
    }

    // 3.把数据复制到数组A
    k = 0;
    for (auto it : vect)
    {
        aiArrayA[k++] = it;
    }
}

// 方法二:从后往前比较,不需要额外的空间
//时间复杂度O(n), 空间复杂度O(1)
void MergeTwoArray2(int aiArrayA[], int iNumA, int aiArrayB[], int iNumB)
{
    int iNewNum = iNumA + iNumB - 1;
    int i = iNumA - 1;
    int j = iNumB - 1;
    
    // 从数组后往前比较,就不存在重叠的情况了!!!
    while (i >= 0 && j >= 0)
    {
        if (aiArrayA[i] > aiArrayB[j])
        {
            aiArrayA[iNewNum--] = aiArrayA[i--];
        }
        else
        {
            aiArrayA[iNewNum--] = aiArrayB[j--];
        }
    }

    while (i >= 0)
    {
        aiArrayA[iNewNum--] = aiArrayA[i--];
    }

    while (j >= 0)
    {
        aiArrayA[iNewNum--] = aiArrayB[j--];
    }

}


Review : 阅读并点评一篇英文技术文章

原文链接:https://codeburst.io/redis-what-and-why-d52b6829813

什么是redis和为什么使用redis?


Tips : 学习一个技术技巧

原文链接:https://blog.csdn.net/FX677588/article/details/70157088

C++11新特性:

  • 新增基于范围的for循环;
  • 自动类型推断 auto;
  • 匿名函数 Lambda;
  • 后置返回类型(tailng-return-type);
  • 显示重写(覆盖)override和final;
  • 空指针常量 nullptr;
  • long long int类型;
  • 模板的别名;
  • 允许sizeof运算符可以再类型数据成员上使用,无需明确对象;
  • 线程支持;



Share : 分享一篇有观点和思考的技术文章

最近在学习redis相关知识,分享一个个人觉得比较好的视频教程:

视频链接:https://study.163.com/course/courseMain.htm?courseId=1003806066

猜你喜欢

转载自www.cnblogs.com/yzdai/p/11185565.html
今日推荐