保存一下单例模式这块还有一些需要的代码:
单例模式:
简单来说就是一个类只能构建一个对象的设计模式
单例设计模式就是一个类只能实例化出一个对象,不能实例化出多个对象,单例模式分为两种,一种是饿汉单例模式,是指在类创建的时候就已经实例化出了一个对象,好处是这个模式没有线程安全问题,坏处是浪费资源,不管之后有没有用到,都会先实例化一个对象,代码如下:
还有一种是懒汉模式,顾名思义,当你需要用它的时候才去实例化对象,如果多个线程同时去实例化对象,那么产生的对象可能不唯一,所以存在线程安全的问题,避免这个线程安全的解决办法是用双检查锁(double checked locking)。
解释:
(线程实例化一个对象,然后线程结束后 , 另一个线程直接使用该对象 , 不会再重新创建 , 结束后调用析构函数)
1.要想让一个类只能构建一个对象,自然不能让它随便去做new操作,因此Signleton的构造方法是私有的。
2.instance是Singleton类的静态成员,也是我们的单例对象。它的初始值可以写成Null,也可以写成new Singleton()。至于其中的区别后来会做解释。
3.getInstance是获取单例对象的方法。
如果单例初始值是null,还未构建,则构建单例对象并返回。这个写法属于单例模式当中的
懒汉模式。
如果单例对象一开始就被new Singleton()主动构建,则不再需要判空操作,这种写法属于
饿汉模式
。
4
.
为了防止new Singleton被执行多次,因此在new操作之前加上Synchronized 同步锁,锁住整个类(注意,这里不能使用对象锁)。
5.进入Synchronized 临界区以后,还要再做一次判空。因为当两个线程同时访问的时候,线程A构建完对象,线程B也已经通过了最初的判空验证,不做第二次判空的话,线程B还是会再次构建instance对象。
工厂模式:
工厂模式:定义一个用于创建对象的接口 , 让子类去决定实例化哪个类,工厂方法使一个类的实例化延迟到其子类
(在工厂模式下 , 新增一个产品 , 必须要新增一个与之相对应的工厂类)
简单工厂:
简单工厂是工厂模式最简单的一种实现,对于不同产品的创建定义一个工厂类,将产品的类型作为参数传入到工厂的创建函数,根据类型分支选择不同的产品构造函数。
抽象工厂:
抽象工厂模式对工厂方法模式进行了更加一般化的描述。工厂方法模式适用于产品种类结构单一的场合,为一类产品提供创建的接口;而抽象工厂方法适用于产品种类结构多的场合,就是当具有多个抽象产品类型时,抽象工厂便可以派上用场。一个具体的工厂可以生产多个产品
抽象工厂是工厂模式的一个扩展。具体工厂类可以创建多个产品体系的对象,但是还是需要修改抽象工厂和具体工厂的代码 , 违反开闭原则
观察者模式:
是一种基于事件和响应的设计模式
当对象间有一对多的依赖关系时,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。
单例模式指的是一个类只能构建一个实例化对象,单例模式分为饿汉模式和懒汉模式。饿汉模式是说当类创建的时候就已经实例化对象了,好处是没有线程安全问题 , 坏处是浪费资源 ,不管后面有没有用到它,该对象已经创建
懒汉模式是指,当我们用到它的时候才会去创建类的实例化对象 , 如果多个线程同时去实例化对象 , 那么对象可能不唯一 ,这时候就存在线程安全问题。可以通过双检查锁来避免。
工厂模式,定义一个用于创建对象的接口。让子类去决定实例化哪个类。
每新增一个产品都要添加一个与之相对应的工厂类
简单工厂模式:对于不同产品的创建定义一个工厂类 , 将产品的类型作为参数传递到创建函数 , 根据类型的不同选择不同的产品构造函数
抽象工厂模式是工厂模式的一个扩展,具体工厂类可以创建多个产品体系的对象 , 但是需要修改抽象工厂和具体工厂的代码 , 违反开闭原则。
观察者模式:是一种基于事件和响应的设计模式
当对象间有一对多的依赖关系时 , 一个对象的状态发生改变 , 所有依赖于它的对象都会得到通知并自动更新。
堆排
#include <stdio.h>
#include <iostream>
using namespace std;
int h[101] , n;
void swap(int x , int y)//交换堆中俩个元素的值
{
int t;
t = h[x];
h[x] = h[y];
h[y] = t;
return;
}
void siftdown(int i)//小顶堆
{
int t , flag = 0;//flag用来标记是否需要向下调整
while(i*2 <= n && flag == 0)
{
if(h[i] > h[i*2])
{
t = i*2;
}
else
{
t = i;
}
if(i*2+1 <= n)
{
if(h[t] > h[i*2+1])
{
t = i*2+1;
}
}
if(t != i)
{
swap(t,i);
i = t;
}
else
{
flag = 1;
}
}
return;
}
//建立堆的函数
void creat()
{
for(int i = n/2 ; i >= 1 ; i--)
{
siftdown(i);
}
return;
}
//删除最大的元素
int deletemax()//从小到大输出
{
int t;
t = h[1];//用一个临时变量记录堆顶点的值
h[1] = h[n];//将堆的最后一个点的值赋给堆顶
n--;//堆的元素减少1
siftdown(1);//向下调整
return t;
}
void heapsort()//堆排序 原数组 从大到小
{
while(n>1)
{
swap(1,n);
n--;
siftdown(1);
}
return;
}
int main()
{
int num;
scanf("%d" , &num);
for(int i = 1 ; i <= num ; i++)
{
scanf("%d" , &h[i]);
}
n = num;
creat();//建堆
//删除顶部元素 , 连续删除n次 , 也就是从大到小把数输出来
// heapsort();
for(int i = 1 ; i <= num ; i++)
{
printf("%d " , deletemax());
//printf("%d " , h[i]);
}
return 0;
}
快排
#include <stdio.h>
int a[101] , n;
void quicksort(int left , int right)
{
int i , j , t , temp;
if(left > right) return;
temp = a[left];
i = left ;
j = right;
while(i != j)
{
while(a[j] >= temp && i < j)
j--;
while(a[i] <= temp && i < j)
i++;
if(i < j)
{
t = a[i];
a[i] = a[j];
a[j] = t;
}
}
a[left] = a[i];
a[i] = temp;
quicksort(left , i-1);
quicksort(i+1,right);
return;
}
int main()
{
scanf("%d" , &n);
for(int i = 1 ; i <= n ; i++)
{
scanf("%d" , &a[i]);
}
quicksort(1,n);
for(int i = 1 ; i <= n ; i++)
{
printf("%d " , a[i]);
}
return 0;
}
死锁例子
#include <iostream>
#include <thread>
#include <mutex>
#include <windows.h>
using namespace std;
mutex mt1 , mt2;
static int data1 = 1, data2 = 1;
void a2()
{
mt2.lock();
data1++;
cout <<"a2 " << data1 << endl;
Sleep(1);
mt1.lock();
data2++;
mt1.unlock();
mt2.unlock();
}
void a1()
{
mt1.lock();
data2++;
cout << "a1 "<< data2 << endl;
Sleep(1);
mt2.lock();
data1++;
mt2.unlock();
mt1.unlock();
}
int main()
{
thread t2(a2);
thread t1(a1);
t1.join();
t2.join();
return 0;
}
智能指针
//shared_ptr 的循环引用:俩个对象互相使用一个shared_ptr成员变量指向对方, 导致引用计数失效
#include <iostream>
#include <memory>//包含智能指针的头文件
using namespace std;
class B;
class A{
public:
shared_ptr<B> pb;
~A(){
cout << "kill A \n";
}
};
class B{
public:
shared_ptr<A> pa;
~B(){
cout << "kill B\n";
}
};
int make()
{
shared_ptr<A> sa(new A());
shared_ptr<B> sb(new B());
if(sa && sb)
{
sa->pb = sb;
sb->pa = sa;
}
cout << " sa use count : " << sa.use_count()<<endl;
return 0;
}
kmp
class Solution{
public:
int strStr(string haystack , string needle){
if(needle == "") return 0;
int len = haystack.length();
int len2 = needle.length();
vector<int>Next(len2+6,0);
getNext(Next, needle , len2);
int i = 0 , j = 0;
while(i < len && j < len2){
if(j == -1 || haystack[i] == needle[j])
{
i++;
j++;
}
else
{
j = Next[j];
}
}
if(j == len2)
{
return i-len2;
}
else
{
return -1;
}
}
void getNext(vector<int> &Next ,string &needle ,int len2){
Next[0] = -1;
int i = 0 , j = -1;
while(i < len2)
{
if(j == -1 || needle[i] == needle[j])
{
++i;
++j;
Next[i] = j;
}
else
{
j = Next[j];
}
}
}
};
匈牙利
#include <iostream>
using namespace std;
const int maxn = 1e4+8;
int M , N ;
int Map[maxn][maxn];
int p[maxn];
bool vis[maxn];
bool match(int i)
{
for(int j = 1 ; j <= N ; j++)
{
if(Map[i][j] && !vis[j])
{
vis[j] = true;
if(p[j] == 0|| match(p[j]))//这里递归
{
p[j] = i;
return true;
}
}
}
return false;
}
int main()
{
int cnt = 0;
cin >> N >> M;
for(int i = 1 ; i <= M ; i++)
{
memset(vis,0,sizeof(vis));//重点,每次都要置为0 , 进入递归
if(match(i))cnt++;
}
cout << cnt << endl;
return 0;
}