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