单例模式
#include<iostream>
#include<atomic>
#include<mutex>
using namespace std;
/*一个类只有一个实例,提供这个实例的全局访问点,
应用程序的日志应用,一般对都是单例模式实现,只能有一个实例去操作文件*/
/*线程不安全版本*/
class Singleton {
public:
static Singleton* getinstance() {
if (m_instance == NULL) {
m_instance = new Singleton();
}
return m_instance;
}
private:
Singleton();//私有构造函数,不允许使用者自己生成对象
Singleton(const Singleton& other);
static Singleton* m_instance;//静态成员变量
};
Singleton* Singleton::m_instance = NULL;//静态成员初始化
/*上述,将构造函数和拷贝构造函数都设为私有,而且采用了延迟初始化的方式,
在第一调用getinstance后才会生成对象,会产生两个对象。*/
/*线程安全,锁的代价高*/
Singleton* Singleton::getinstance(){
Lock lock;//伪代码,加锁
if (m_instance == NULL) {
m_instance = new Singleton();
}
return m_instance;
}
/*上述,性能不高,因为每次调用getinstance都会加锁,而这个步骤只有在第一次new对象时才需要*/
/*双检查锁,由于内存读写失序,会导致不安全*/
//双检查锁,但由于内存读写reorder不安全
Singleton* Singleton::getinstance() {
//先判断是不是初始化了,如果初始化过,就再也不会使用锁了
if (m_instance == nullptr) {
Lock lock; //伪代码
if (m_instance == nullptr) {
m_instance = new Singleton();
}
}
return m_instance;
}
/*上述,m_instance = new Singleton();有三步:(1)分配一个Singleton类型的对象需要的缓存
(2)在分配的内存处构造Singleton类型的对象(3)把分配的内存地址赋值给指针m_instance
但是后两步的执行不一定是按照顺序的。*/
/*c++11引入了原子操作atomic,表示不能失序*/
/*c++11最新:*/
class Singleton {
public:
// 注意返回的是引用。
static Singleton& getInstance() {
static Singleton m_instance; //局部静态变量
return m_instance;
}
private:
Singleton(); //私有构造函数,不允许使用者自己生成对象
Singleton(const Singleton& other);
};
/*饿汉模式:在单例类定义的时候就进行实例化,
由于要线程同步,所以在访问量较大时,或者可能访问的线程较多时,采用饿汉实现*/
class Singleton {
public:
static Singleton * getinstance();
private:
Singleton(const Singleton&) {};
Singleton & operator=(const Singleton&) {};
Singleton() {};
static Singleton* instance;
};
Singleton* Singleton::instance = new Singleton();
Singleton* Singleton::getinstance() {
return instance;
}
实现strcpy、strlen
#include"pch.h"
#include<iostream>
#include<vector>
using namespace std;
char * strcpy0(char *dst, const char * src) {
if (dst == NULL || src == NULL) return NULL;
char *res = dst;//保存原始dst的地址
while ((*dst++ = *src++) != '\0');
return res;
}
int getstrlen(const char * src) {
int len = 0;
if (src == NULL) return 0;
while ((*src++) != '\0') len++;
return len;
}
int main() {
char src[] = "hello world";
char dst[20] = { 0 };
char* res = strcpy0(dst, src);
cout << res << endl;
cout << getstrlen(res) << endl;
return 0;
}
单链表反转(递归与非递归)
#include"pch.h"
#include<iostream>
#include<vector>
using namespace std;
typedef struct Node {
int value;
Node *next;
Node(int x) :value(x), next(NULL) {}
}Node;
Node *reverse(Node *head) {
Node *tmp = head, *res = head;
head = head->next; tmp->next = NULL;
while (head->next) {
Node *tmpp = head->next;
head->next = tmp;
tmp = head;
head = tmpp;
}
head->next = tmp;
return head;
}
Node *reverse0(Node *head) {
if (head == NULL || head->next == NULL) return head;
Node *newhead = reverse0(head->next);
head->next->next = head;
head->next = NULL;
return newhead;
}
int main() {
vector<int> nums = { 1,2,3,4,5 };
Node *node1 = new Node(nums[0]);
Node *node2 = new Node(nums[1]);
Node *node3 = new Node(nums[2]);
Node *node4 = new Node(nums[3]);
Node *node5 = new Node(nums[4]);
node1->next = node2; node2->next = node3;
node3->next = node4; node4->next = node5;
node5->next = NULL;
node1 = reverse0(node1);
while (node1) {
cout << node1->value << " ";
node1 = node1->next;
}
return 0;
}
n!后面0的个数
#include"pch.h"
#include<iostream>
#include<vector>
using namespace std;
/*n!后面0的个数
找规律的数学问题,两个大数字相乘,可以拆分成多个质数相乘,
质数相乘结尾是0的,只有2*5,
所以两个数相乘,尾数0的个数其实就是依赖于2和5因子的个数,
因为每两个连续的数字就有一个2,所以只需要关心5因子的个数。
如何计算一个n!中5的个数?
把5的倍数都挑出来: 令n! = (5*K) * (5*(K-1)) * (5*(K-2)) * ... * 5 * A,
其中A就是不含5因子的数相乘结果,n = 5*K + r(0<= r <= 4)。
假设f(n!)是计算阶乘n!尾数0的个数,而g(n!)是计算n!中5因子的个数,
那么就会有如下公式:
f(n!) = g(n!) = g(5^K * K! * A) = K + g(K!) = K + f(K!),其中K=n / 5(取整数)。
很显然,当0 <= n <= 4时,f(n!)=0。*/
int getN_1(int n) {
if (n < 5) return 0;
return (n / 5) + getN_1(n / 5);
}
int main() {
cout << getN_1(1000) << endl;
return 0;
}
判断平衡二叉树
#include<iostream>
using namespace std;
//判断平衡二叉树
typedef struct TreeNode{
int value;
TreeNode *left,*right;
TreeNode(int x):value(x),left(NULL),right(NULL){}
}
int height(TreeNode *root,bool &res){
if(root==NULL) return 0;
int left=height(root->left,res)+1;
int right=height(root->right,res)+1;
if(left-right>=2 || right-left>=2) res=0;
return max(left,right);//这棵树的高度,左节点、右节点的更高的
}
bool isBalance(TreeNode *root){
bool res=1;
height(root,res);
return res;
}
int main(){
...
}
最近公共祖先节点
#include<iostream>
#include<stack>
#include<vector>
#include<algorithm>
using namespace std;
//最近公共祖先节点
typedef struct TreeNode{
int value;
TreeNode *left,*right;
TreeNode(int x):value(x),left(NULL),right(NULL){}
};
//如果是二叉搜索树
TreeNode* LCA1(TreeNode *root,TreeNode *a,TreeNode *b){
if(root==NULL||a==NULL||b==NULL) return NULL;
if(a->value==root->value || b->value==root->value) return root;
//上条语句,相当于说a是b的祖先,或者b是a的祖先
TreeNode *l=LCA1(root->left,a,b);//到左子树中找
TreeNode *r=LCA1(root->right,a,b);//到右子树中找
if(l&&r) return root;//如果左子树有其中一个节点,右子树有另一个节点,root就是所求
return l==NULL?r:l;//如果返回的左子树为空,那么LCA在右子树上
}//a和b分别是两个需要查找的树节点,
//后序遍历非递归方法找LCA,后序遍历非递归,栈中元素就是从根到达该节点的路径
TreeNode *LCA2(TreeNode *root, TreeNode *a, TreeNode *b) {
if (root == NULL) return root;
stack<TreeNode*> st;
vector<TreeNode *> vec1, vec2;
bool tag1 = false;
bool tag2 = false;
TreeNode *pre = NULL;
while (root || !st.empty()) {
if (tag1 && tag2) break;
while (root) {
if (tag1 && tag2) break;
if (root == a) {
tag1 = true;
stack<TreeNode*> tmp = st;
vec1.push_back(root);
while (!tmp.empty()) {
vec1.push_back(tmp.top());
tmp.pop();
}
}
if (root == b) {
tag2 = true;
stack<TreeNode*> tmp = st;
vec2.push_back(root);
while (!tmp.empty()) {
vec2.push_back(tmp.top());
tmp.pop();
}
}
st.push(root);
root = root->left;
}
root = st.top();
if (root->right == NULL || root->right == pre) {
st.pop();
pre = root;
root = NULL;
}
else {
root = root->right;
}
}
reverse(vec1.begin(), vec1.end());
reverse(vec2.begin(), vec2.end());
TreeNode *res = NULL;
for (int i = 0, j = 0; i < vec1.size() && j < vec2.size();i++,j++) {
if (vec1[i]->value == vec2[i]->value) {
res = vec1[i];
continue;
}
else if (vec1[i]->value != vec2[i]->value) {
return vec1[i - 1];
}
}
return res;
}
//后序遍历非递归:
void BacOrder(TreeNode* root){
stack<TreeNode*> st;
TreeNode *pre=NULL;
while(root|| !st.empty()){
while(root){
st.push(root);
root=root->left;
}
root=st.top();
if(root->right==NULL || root->right==pre){
st.pop();
cout<<root->value<<endl;
pre=root;
root=NULL;
}else{
root=root->right;
}
}
return ;
}
int main(){
TreeNode *root=new TreeNode (10);
TreeNode *node1=new TreeNode (1);
TreeNode *node2=new TreeNode (2);
TreeNode *node3=new TreeNode (3);
TreeNode *node4=new TreeNode (4);
TreeNode *node5=new TreeNode (5);
root->left=node1;root->right=node2;
node1->left=node3;node2->left=node4;node2->right=node5;
//BacOrder(root);
TreeNode *res=LCA2(root,node2,node5);
cout<<res->value<<endl;
return 0;
}
多线程
三个线程A、B、C,循环输出ABCABC。。。。。。
#include"pch.h"
#include<iostream>
#include<stack>
#include<vector>
#include<mutex>
#include<thread>
using namespace std;
//三个线程A、B、C,循环输出ABCABC。。。。。。
int main() {
mutex mtex;
int cnt = 0;
auto work = [&](char ch, int num) {
while (num--) {
while (ch != cnt + 'A') this_thread::yield();
//this_thread::yield();可以将本线程时间片放弃,允许其他线程运行
unique_lock<mutex> lk(mtex);
cout << ch;
cnt = (cnt + 1) % 3;
lk.unlock();
}
};//lambda,[&]表示引用的外部变量可以被改变
thread t1(work, 'A', 10);
thread t2(work, 'B', 10);
work('C', 10);
t1.join();
t2.join();
return 0;
}
输入一个正数n,输出所有和为n连续正数序列。
#include "pch.h"
#include <iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
/*题目:
输入一个正数n,输出所有和为n连续正数序列。
例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以输出3个连续序列1-5、4-6和7-8。
解决:
结果一定是2个相连的数、3个相连的数、4个、5个等等。
那么可以把这个数n除以i(i为2,3,4...代表相连的数的个数),
得到的这些相邻的数的大概平均值,如当 n = 15、i = 2 时,n / i = 7,
这代表如果有两个相邻的数的和是15,那么它们的大概平均值是7;
i = 3 时,n / i = 5,代表三个连续的数的大概平均值是5,那么这三个数是4,5,6。
大概平均值是因为整数除引起的。
所以可以由相连数的个数得到这些数的大概平均值,从而可以得到这么多个相连的数,
判断它们的和是否满足,不满足再看下一个相邻数的个数,直到相连数的第一个到了1。
或者使用公式:
Suppose n = i+(i+1)+...+(j-1)+j, then n = (i+j)(j-i+1)/2 = (j*j-i*i+i+j)/2
=> j^2+j+(i-i^2-2n) = 0 => j = (sqrt(1-4(i-i^2-2n))-1)/2
=> j = (sqrt(4i^2+8n-4i+1)-1)/2.
*/
int main() {
int n;
cin >> n;
vector<vector<int> > res;
for (int i = 2;i<=sqrt(2*n); i++) {
int tmp = n / i;
if (i % 2 == 0) {
int sum = (tmp * 2 + 1)*(i / 2);
if (sum != n) continue;
}
else {
int sum = 2 * tmp*(i / 2) + tmp;
if (sum != n) continue;
}
vector<int> ans;
int sum = 0;
for (int j = tmp - (i - 1) / 2;; j++) {
sum += j;
ans.push_back(j);
if (sum == n) {
res.push_back(ans);
break;
}
else if (sum > n) break;
}
}
for (int i = 0; i < res.size(); i++) {
for (int j = 0; j < res[i].size(); j++) cout << res[i][j] << " ";
cout << endl;
}
return 0;
}