23.常用代码
0.C++万能库
#include<bits/stdc++.h>
using namespace std;
int main() {
int a, b;
std::getline(std::cin, input); //可以输入带空格的字符串
while (cin >> a >> b) {
if (a == 0 && b == 0) break;
cout << a + b << endl;
}
}
1.排序类
快排
void QuichSort(vector<int> &arr,int start,int end) //快排需要传入 开始 结束
{
if(end <= start) return; //结束条件为开始大于等于结束
int left = start,right = end,cur = arr[start]; //定义left,right以及cur(左边第一个值)
while(left < right) //循环遍历
{
while(left < right && arr[right] >= cur) right--; //找到右边比cur小的数
arr[left] = arr[right]; //将其交换到左边
while(left < right && arr[left] <= cur) left++;//找到左边比cur大的数
arr[right] = arr[left];//将其交换到右边
}
arr[left] = cur;//将cur 放到中间,保证cur左边小于,右边大于
QuichSort(arr,0,left - 1); //递归遍历左边
QuichSort(arr,left + 1,end); //递归遍历右边
}
归并
这里注意,对比的是temp:if(temp[start] > temp[end]) arr[cnt++] = temp[end++];
void Sort(vector<int> &arr) //快排需要传入 开始 结束
{
vector<int> temp = arr;
function<void(int,int)> MySort = [&](int left, int right){
if(left >= right) return;
//先拆分
int mid = (left + right) / 2;
MySort(left,mid);
MySort(mid + 1,right);
//后排序,此时arr在(left,mid),(mid,right)是有序的,需要合并至temp
int start = left, end = mid + 1,cnt = start; //注意这里,开始的合并的初始化
for(int i = left; i <= right;i++) temp[i] = arr[i]; //先进行拷贝
//进行合并
while(start <= mid && end <= right)
{
if(temp[start] > temp[end]) arr[cnt++] = temp[end++]; //这里注意,对比的是temp
else arr[cnt++] = temp[start++];
}
while(start <= mid) arr[cnt++] = temp[start++];
while(end <= right) arr[cnt++] = temp[end++];
};
MySort(0,arr.size() - 1);
}
快速幂运算求-Pow
double myPow2(double x, long long n) {
if(n == 0) return 1;
if(n == 1) return x;
if(n < 0) return 1 / myPow2(x, abs(n));
//现在是正数了
double temp = myPow2(x, n / 2);
return n % 2 == 0 ? temp * temp : temp * temp * x;
}
2.其余类
二叉数的迭代遍历
//前序遍历 -> 中 左 右
vector<int> preorderTraversal(TreeNode* root) {
if(!root) return {};
vector<int> res;
stack<TreeNode* > st; //使用栈
st.push(root);
while(!st.empty())
{
TreeNode* top = st.top();
st.pop();
res.push_back(top->val); //中
if(top->right) st.push(top->right); //右 -> 右边节点先入栈,后出
if(top->left) st.push(top->left); //左-> 右边节点后入栈,先出
}
return res;
}
//中序遍历
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> st;
while(!st.empty() || root)
{
if(root)
{
st.push(root);
root = root->left;
}
else
{
TreeNode* top = st.top();
st.pop();
res.push_back(top->val);
root = top->right;
}
}
return res;
}
//后序遍历 -> 左 右 中(可以由前序遍历改 中右左)反序得到
vector<int> postorderTraversal(TreeNode* root) {
if(!root) return {};
vector<int> res;
stack<TreeNode* > st; //使用栈
st.push(root);
while(!st.empty())
{
TreeNode* top = st.top();
st.pop();
res.push_back(top->val); //中
if(top->left) st.push(top->left); //左-> 右边节点后入栈,先出
if(top->right) st.push(top->right); //右 -> 右边节点先入栈,后出
}
reverse(res.begin(),res.end());
return res;
}
智能指针sheard_ptr
#include <iostream>
#include <mutex>
template <typename T>
class SharedPtr {
private:
T* data;
size_t* count;
std::mutex mtx; // 添加互斥锁
public:
// 构造函数
SharedPtr(T* ptr = nullptr) : data(ptr), count(new size_t(1)) {}
// 拷贝构造函数
SharedPtr(const SharedPtr& other) : data(other.data), count(other.count) {
std::lock_guard<std::mutex> lock(mtx); // 加锁
(*count)++;
}
// 赋值运算符重载
SharedPtr& operator=(const SharedPtr& other) {
if (this != &other) {
// 减少旧对象的引用计数
release();
// 复制新对象的数据
std::lock_guard<std::mutex> lock(mtx); // 加锁
data = other.data;
count = other.count;
// 增加新对象的引用计数
(*count)++;
}
return *this;
}
// 析构函数
~SharedPtr() {
release();
}
// 解引用运算符重载
T& operator*() const {
return *data;
}
// 成员访问运算符重载
T* operator->() const {
return data;
}
private:
// 释放资源的辅助函数
void release() {
if (count != nullptr) {
std::lock_guard<std::mutex> lock(mtx); // 加锁
(*count)--;
if (*count == 0) {
delete data;
delete count;
}
}
}
};
int main() {
SharedPtr<int> ptr1(new int(42));
SharedPtr<int> ptr2 = ptr1;
std::cout << "ptr1: " << *ptr1 << std::endl;
std::cout << "ptr2: " << *ptr2 << std::endl;
return 0;
}
线程池
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <functional>
class ThreadPool {
public:
// 构造函数,初始化线程池
ThreadPool(size_t numThreads) : stop(false) {
// 创建指定数量的工作线程,并将它们添加到线程池中
for (size_t i = 0; i < numThreads; ++i) {
workers.emplace_back([this] {
// 线程主循环
while (true) {
std::function<void()> task;
{
// 使用互斥锁保护任务队列
std::unique_lock<std::mutex> lock(queueMutex);
// 使用条件变量等待任务队列不为空或停止信号
condition.wait(lock, [this] { return stop || !tasks.empty(); });
// 如果收到停止信号且任务队列为空,线程退出
if (stop && tasks.empty()) {
return;
}
// 取出队列头部的任务
task = std::move(tasks.front());
tasks.pop();
}
// 执行取出的任务
task();
}
});
}
}
// 将任务加入到任务队列
template<class F>
void enqueue(F&& func) {
{
// 使用互斥锁保护任务队列
std::unique_lock<std::mutex> lock(queueMutex);
// 将任务移动到队列中
tasks.emplace(std::forward<F>(func));
}
// 通知一个等待中的线程有新任务可以执行
condition.notify_one();
}
// 析构函数,停止线程池,并等待所有线程结束
~ThreadPool() {
{
// 使用互斥锁保护停止信号
std::unique_lock<std::mutex> lock(queueMutex);
stop = true;
}
// 唤醒所有等待中的线程
condition.notify_all();
// 等待所有线程结束
for (std::thread &worker : workers) {
worker.join();
}
}
private:
// 工作线程
std::vector<std::thread> workers;
// 任务队列
std::queue<std::function<void()>> tasks;
// 互斥锁用于保护对任务队列的访问
std::mutex queueMutex;
// 条件变量用于通知工作线程有新任务
std::condition_variable condition;
// 停止信号,用于通知工作线程停止
bool stop;
};
int main() {
// 创建包含4个工作线程的线程池
ThreadPool threadPool(4);
// 向线程池中提交8个任务
for (int i = 0; i < 8; ++i) {
threadPool.enqueue([i] {
// 打印任务信息和执行线程的ID
std::cout << "Task " << i << " processed by thread " << std::this_thread::get_id() << std::endl;
});
}
// 给予一些时间让任务被处理
std::this_thread::sleep_for(std::chrono::seconds(2));
return 0;
}
哈希表
#include <iostream>
#include <vector>
#include <list>
#include <iterator>
#include <algorithm>
// HashNode表示哈希表中的一个节点
template <typename K, typename V>
struct HashNode {
K key;
V value;
};
// HashMap表示哈希表
template <typename K, typename V, typename Hash = std::hash<K>>
class HashMap {
private:
std::vector<std::list<HashNode<K, V>>> buckets;
Hash hashFunction;
public:
HashMap(size_t size = 10) : buckets(size) {}
// 插入键值对
void insert(const K& key, const V& value) {
size_t index = hashFunction(key) % buckets.size();
auto& bucket = buckets[index];
// 检查是否已经存在相同的键,如果是,更新值
auto it = std::find_if(bucket.begin(), bucket.end(), [&key](const HashNode<K, V>& node) {
return node.key == key;
});
if (it != bucket.end()) {
it->value = value;
} else {
// 否则,在链表头部插入新节点
bucket.push_front({key, value});
}
}
// 查找键对应的值
bool find(const K& key, V& value) const {
size_t index = hashFunction(key) % buckets.size();
const auto& bucket = buckets[index];
// 在链表中查找键
auto it = std::find_if(bucket.begin(), bucket.end(), [&key](const HashNode<K, V>& node) {
return node.key == key;
});
// 如果找到了,返回对应的值
if (it != bucket.end()) {
value = it->value;
return true;
}
return false; // 没找到
}
// 移除键值对
void remove(const K& key) {
size_t index = hashFunction(key) % buckets.size();
auto& bucket = buckets[index];
// 移除链表中的节点
bucket.remove_if([&key](const HashNode<K, V>& node) {
return node.key == key;
});
}
};
int main() {
HashMap<std::string, int> myMap;
myMap.insert("one", 1);
myMap.insert("two", 2);
myMap.insert("three", 3);
int value;
if (myMap.find("two", value)) {
std::cout << "Value for key 'two': " << value << std::endl;
} else {
std::cout << "Key 'two' not found." << std::endl;
}
myMap.remove("two");
if (myMap.find("two", value)) {
std::cout << "Value for key 'two': " << value << std::endl;
} else {
std::cout << "Key 'two' not found." << std::endl;
}
return 0;
}
线程同步问题-3线程交替打印 1 - 100
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
const int target = 100;
std::mutex mtx,numMutx;
std::condition_variable cv;
std::atomic<int> atomicInt(1);
void printNumber(int threadId, int mod) {
while (atomicInt <= target) {
std::unique_lock<std::mutex> lock(mtx);
// 等待轮到当前线程打印
cv.wait(lock, [threadId] { return (atomicInt % 3) == threadId; });
if(atomicInt <= target) std::cout << "Thread " << threadId + 1 << ": " << atomicInt << std::endl;
atomicInt++;
cv.notify_all();
}
}
int main() {
std::thread t1(printNumber, 0, 3);
std::thread t2(printNumber, 1, 3);
std::thread t3(printNumber, 2, 3);
t1.join();
t2.join();
t3.join();
return 0;
}
实现可能含交集的memcpy(memmove)
#include <iostream>
//考虑内存᯿叠的memcpy函数 优化的点
void* memmove(void* dest, void* src, size_t num) {
char* p1 = (char*)dest;
char* p2 = (char*)src;
if(p1<p2) {//p1低地址p2⾼地址
for(size_t i = 0; i != num; ++i)
*(p1++) = *(p2++);
}
else {
//从后往前赋值
p1 += num - 1;
p2 += num - 1;
for(size_t i = 0; i != num; ++i)
*(p1--) = *(p2--);
}
return dest;
}
int main() {
char buffer[20] = "Hello, World!ABCD";
// 将 "World!" 移动到 buffer 的开头
memmove(buffer, buffer + 7, 10);
std::cout << "Buffer: " << buffer << std::endl;
return 0;
}
单例模式
饿汉
class Chairman
{
public:
void print()
{
cout << "对象调用" << endl;
}
private:
Chairman() //私有构造函数
{
cout << "创建chairman类" << endl;
}
public:
static Chairman* singleman; //类内声明chairman对象指针
};
Chairman* Chairman::singleman = new Chairman; //类外进行初始化
int main()
{
cout << "main函数开始执行" << endl;
Chairman::singleman->print();
system("pause");
return 0;
}
懒汉
#include <iostream>
#include <memory> // shared_ptr
#include <mutex> // mutex
// version 2:
// with problems below fixed:
// 1. thread is safe now
// 2. memory doesn't leak
class Singleton {
public:
typedef std::shared_ptr<Singleton> Ptr;
~Singleton() {
std::cout << "destructor called!" << std::endl;
}
Singleton(Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
static Ptr get_instance() {
// "double checked lock"
if (m_instance_ptr == nullptr) {
std::lock_guard<std::mutex> lk(m_mutex);
if (m_instance_ptr == nullptr) {
m_instance_ptr = std::shared_ptr<Singleton>(new Singleton);
}
}
return m_instance_ptr;
}
private:
Singleton() {
std::cout << "constructor called!" << std::endl;
}
static Ptr m_instance_ptr;
static std::mutex m_mutex;
};
// initialization static variables out of class
Singleton::Ptr Singleton::m_instance_ptr = nullptr;
std::mutex Singleton::m_mutex;
/// 内部静态变量的懒汉实现 //
class Singleton
{
public:
~Singleton(){
std::cout<<"destructor called!"<<std::endl;
}
//或者放到private中
Singleton(const Singleton&)=delete;
Singleton& operator=(const Singleton&)=delete;
static Singleton& get_instance(){
//关键点!
static Singleton instance;
return instance;
}
//不推荐,返回指针的方式
/*static Singleton* get_instance(){
static Singleton instance;
return &instance;
}*/
private:
Singleton(){
std::cout<<"constructor called!"<<std::endl;
}
};
无锁队列
#include <atomic>
template <typename T>
class LockFreeQueue {
private:
struct Node {
T data;
Node* next;
Node(const T& data) : data(data), next(nullptr) {} // 节点构造函数
};
std::atomic<Node*> head; // 原子指针,指向队列头节点
std::atomic<Node*> tail; // 原子指针,指向队列尾节点
public:
LockFreeQueue() : head(nullptr), tail(nullptr) {} // 构造函数
void enqueue(const T& value) {
Node* newNode = new Node(value); // 创建新节点
Node* oldTail = tail.exchange(newNode); // 原子替换尾指针,并返回之前的尾指针
if (oldTail != nullptr) {
oldTail->next = newNode; // 如果之前的尾指针不为空,更新之前尾节点的下一个节点为新节点
} else {
head.store(newNode); // 如果之前的尾指针为空,则表示队列为空,更新头指针为新节点
}
}
bool dequeue(T& value) {
Node* oldHead = head.load(); // 加载头指针的值
if (oldHead == nullptr) {
return false; // 如果头指针为空,表示队列为空,返回失败
}
if (oldHead->next == nullptr) { // 如果头节点的下一个节点为空,表示队列只有一个节点
tail.compare_exchange_strong(oldHead, nullptr); // 原子比较并交换,将尾指针置为空
}
value = oldHead->data; // 获取头节点的数据
head.store(oldHead->next); // 更新头指针为头节点的下一个节点
delete oldHead; // 释放头节点的内存
return true; // 返回成功
}
~LockFreeQueue() { // 析构函数,释放队列中的所有节点
T temp;
while (dequeue(temp)); // 循环调用 dequeue 方法,直到队列为空
}
};