二叉树层序遍历结果
#include <iostream>
#include <queue>
#include <vector>
// 定义二叉树节点结构
struct TreeNode
{
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
void levelOrderTraverse(TreeNode* root)
{
if (root == nullptr)
{
return;
}
queue<TreeNode*> q;
q.push(root);
// 记录当前遍历到的层数(根节点视为第 1 层)
int depth = 1;
while (!q.empty())
{
int sz = q.size();
for (int i = 0; i < sz; i++)
{
TreeNode* cur = q.front();
q.pop();
// 访问 cur 节点,同时知道它所在的层数
cout << "depth = " << depth << ", val = " << cur->val << endl;
// 把 cur 的左右子节点加入队列
if (cur->left != nullptr)
{
q.push(cur->left);
}
if (cur->right != nullptr)
{
q.push(cur->right);
}
}
depth++;
}
}
int main() {
// 构建一棵测试用的二叉树
// 1
// / \
// 2 3
// / \ \
// 4 5 6
TreeNode* root = new TreeNode(1);
root->left = new TreeNode(2);
root->right = new TreeNode(3);
root->left->left = new TreeNode(4);
root->left->right = new TreeNode(5);
root->right->right = new TreeNode(6);
// 执行层序遍历,并获取结果
std::vector<int> result = levelOrderTraversal(root);
// 输出结果
for (int val : result)
{
std::cout << val << " ";
}
std::cout << std::endl;
// 注意:这里省略了释放分配的内存的代码
// 实际使用中,应当在适当的位置释放这些内存以避免内存泄漏
return 0;
}
二叉树非递归遍历
前序遍历
void preorderTraversal(TreeNode* root) {
if (root == nullptr) return;
std::stack<TreeNode*> stk;
stk.push(root);
while (!stk.empty()) {
TreeNode* node = stk.top();
stk.pop();
// 访问节点
std::cout << node->val << " ";
// 注意:这里要先压入右子节点,再压入左子节点,
// 因为栈是后进先出,而我们希望先遍历左子树
if (node->right) stk.push(node->right);
if (node->left) stk.push(node->left);
}
}
中序遍历
void inorderTraversal(TreeNode* root)
{
std::stack<TreeNode*> stk;
TreeNode* curr = root;
while (curr != nullptr || !stk.empty())
{
// 遍历左子树,将左子节点依次入栈
while (curr != nullptr)
{
stk.push(curr);
curr = curr->left;
}
// 栈顶元素即为当前子树的最左节点,处理它
curr = stk.top();
stk.pop();
std::cout << curr->val << " "; // 访问节点
// 转向右子树
curr = curr->right;
}
}
后序遍历
void postorderTraversal(TreeNode* root) {
if (root == nullptr) return;
std::stack<TreeNode*> stk1, stk2; // 使用两个栈
stk1.push(root);
while (!stk1.empty()) {
TreeNode* node = stk1.top();
stk1.pop();
stk2.push(node); // 将节点压入第二个栈
// 先压入右子节点,再压入左子节点(因为栈是后进先出)
if (node->left) stk1.push(node->left);
if (node->right) stk1.push(node->right);
}
// 第二个栈中的节点顺序就是后序遍历的顺序
while (!stk2.empty()) {
TreeNode* node = stk2.top();
stk2.pop();
std::cout << node->val << " ";
}
}
链表是否包含环
class Solution
{
public:
ListNode* detectCycle(ListNode* head)
{
ListNode* fast = head;
ListNode* slow = head;
while (fast != nullptr && fast->next != nullptr)
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
break;
}
// 上面的代码类似 hasCycle 函数
if (fast == nullptr || fast->next == nullptr)
{
// fast 遇到空指针说明没有环
return nullptr;
}
// 重新指向头结点
slow = head;
// 快慢指针同步前进,相交点就是环起点
while (slow != fast)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}
};
反转链表
// 定义链表节点结构体
struct ListNode
{
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
// 反转单链表的函数
ListNode* reverseList(ListNode* head)
{
ListNode* prev = nullptr; // 前一个节点,初始化为nullptr
ListNode* curr = head; // 当前节点,初始化为头节点
ListNode* next = nullptr; // 下一个节点,用于临时存储当前节点的下一个节点
while (curr != nullptr)
{
// 临时存储当前节点的下一个节点
next = curr->next;
// 将当前节点的next指针指向前一个节点
curr->next = prev;
// 移动前一个节点和当前节点到下一个位置
prev = curr;
curr = next;
}
// 当循环结束时,prev将指向新的头节点(原链表的尾节点)
return prev;
}
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) : val(x), next(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @param m int整型
* @param n int整型
* @return ListNode类
*/
ListNode* reverseBetween(ListNode* head, int m, int n) {
// write code here
auto dummy = new ListNode(0);
dummy->next = head;
ListNode* preNode = dummy;
ListNode* curNode = head;
for (int i = 1; i < m; i++)
{
preNode = curNode;
curNode = curNode->next;
}
ListNode* next = nullptr;
for (int j = 0; j < n - m; j++)
{
next = curNode->next;
curNode->next = next->next;
next->next = preNode->next;
preNode->next = next;
}
return dummy->next;
}
};
209. 长度最小的子数组 - 力扣(LeetCode)
class Solution
{
public:
int minSubArrayLen(int target, vector<int>& nums)
{
int result = INT32_MAX, left = 0, right = 0, curentSum = 0;
while(right < nums.size())
{
curentSum += nums[right];
while (curentSum >= target)
{
result = min(result, right - left +1);
curentSum -= nums[left++];
}
right++;
}
return result == INT32_MAX ? 0 : result;
}
};
字符串是否有效
给定一个只包括'(',')','{','}','[',']' 的字符串s,判断字符串是否有效。
#include <stack>
#include <string>
bool isValid(const std::string& s)
{
std::stack<char> stk;
for (char c : s)
{
if (c == '(' || c == '[' || c == '{')
{
stk.push(c);
}
else if (c == ')' || c == ']' || c == '}')
{
if (stk.empty())
{
return false; // 没有对应的左括号
}
char top = stk.top();
stk.pop();
if ((c == ')' && top != '(') ||
(c == ']' && top != '[') ||
(c == '}' && top != '{'))
{
return false; // 左右括号不匹配
}
}
}
return stk.empty(); // 如果栈为空,则所有括号都匹配
}
删除元素
// 函数模板,用于从vector中删除所有等于value的元素
template <typename T>
void remove_value_without_remove(std::vector<T>& vec, const T& value)
{
auto it = vec.begin();
while (it != vec.end())
{
if (*it == value)
{
it = vec.erase(it); // 如果找到值,则erase并更新迭代器
}
else
{
++it; // 否则,继续遍历
}
}
}
智能指针
#include <iostream>
#include <atomic>
// 控制块类,用于管理引用计数和对象
template <typename T>
class ControlBlock
{
public:
std::atomic<int> ref_count; // 引用计数
T* object_ptr; // 指向被管理的对象
explicit ControlBlock(T* obj) : ref_count(1), object_ptr(obj) {}
void add_ref()
{
++ref_count;
}
void release()
{
if (--ref_count == 0)
{
// 引用计数为零,释放对象和控制块
delete object_ptr;
delete this;
}
}
};
// 智能指针类
template <typename T>
class MySharedPtr
{
private:
T* ptr;
ControlBlock<T>* control_block;
public:
// 构造函数
explicit MySharedPtr(T* p = nullptr)
: ptr(p), control_block(p ? new ControlBlock<T>(p) : nullptr) {}
// 拷贝构造函数
MySharedPtr(const MySharedPtr& other)
: ptr(other.ptr), control_block(other.control_block)
{
if (control_block)
{
control_block->add_ref();
}
}
// 移动构造函数
MySharedPtr(MySharedPtr&& other) noexcept
: ptr(other.ptr), control_block(other.control_block)
{
other.ptr = nullptr;
other.control_block = nullptr;
}
// 拷贝赋值运算符
MySharedPtr& operator=(const MySharedPtr& other)
{
if (this != &other)
{
release(); // 释放当前对象
ptr = other.ptr;
control_block = other.control_block;
if (control_block)
{
control_block->add_ref();
}
}
return *this;
}
// 移动赋值运算符
MySharedPtr& operator=(MySharedPtr&& other) noexcept
{
if (this != &other)
{
release(); // 释放当前对象
ptr = other.ptr;
control_block = other.control_block;
other.ptr = nullptr;
other.control_block = nullptr;
}
return *this;
}
// 析构函数
~MySharedPtr()
{
release();
}
// 获取原始指针
T* get() const
{
return ptr;
}
// 重载解引用运算符
T& operator*() const
{
return *ptr;
}
// 重载箭头运算符
T* operator->() const
{
return ptr;
}
// 获取引用计数(可选,用于调试)
int use_count() const
{
return control_block ? control_block->ref_count : 0;
}
private:
void release()
{
if (control_block)
{
control_block->release();
ptr = nullptr;
control_block = nullptr;
}
}
};
// 示例使用
int main()
{
MySharedPtr<int> sp1(new int(10));
{
MySharedPtr<int> sp2 = sp1; // 共享所有权
std::cout << "sp2 value: " << *sp2 << ", use_count: " << sp2.use_count() << std::endl;
} // sp2 离开作用域,但引用计数不为0,因此不会释放资源(由sp1维持)
std::cout << "sp1 value after sp2 out of scope: " << *sp1 << ", use_count: " << sp1.use_count() << std::endl;
return 0;
}
strstr
strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回 str1字符串从 str2第一次出现的位置开始到 str1结尾的字符串;否则,返回NULL
int strStr(string haystack, string needle) {
int result = -1;
for (int i = 0; i < haystack.size(); i++) {
int curIndex = i;
int targetIndex = 0;
while (haystack[curIndex] == needle[targetIndex] &&
curIndex < haystack.size() && targetIndex < needle.size()) {
curIndex++;
targetIndex++;
}
if (targetIndex == needle.size()) {
result = i;
break;
}
}
return result;
}
#include <iostream>
char* myStrstr(const char* haystack, const char* needle)
{
// If either string is nullptr, return nullptr
if (!haystack || !needle)
{
return nullptr;
}
// If needle is an empty string, return haystack
if (*needle == '\0')
{
return const_cast<char*>(haystack);
}
// Iterate over haystack
for (const char* h = haystack; *h != '\0'; ++h)
{
// Pointers for haystack and needle
const char* h_temp = h;
const char* n = needle;
// Compare haystack substring with needle
while (*h_temp != '\0' && *n != '\0' && *h_temp == *n)
{
++h_temp;
++n;
}
// If we have reached the end of needle, we have found a match
if (*n == '\0')
{
return const_cast<char*>(h);
}
}
// If no match is found, return nullptr
return nullptr;
}
int main() {
const char* haystack = "Hello, world!";
const char* needle = "world";
char* result = myStrstr(haystack, needle);
if (result)
{
std::cout << "Found substring: " << result << std::endl;
}
else
{
std::cout << "Substring not found." << std::endl;
}
return 0;
}
在最坏情况下,
myStrstr函数的时间复杂度为 O((n-m+1)*m),其中 n 是haystack的长度,m 是needle的长度
生产者消费者
#include <queue>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <iostream>
using namespace std;
class MessageQueue
{
public:
MessageQueue(int maxSize) : m_maxsize(maxSize){};
~MessageQueue(){
};
void put(int value)
{
std::unique_lock<std::mutex> lck(m_tex);
fullCond.wait(lck, [this]{ return m_quque.size() < m_maxsize;});
m_quque.push(value);
std::cout << "put: " << value << std::endl;
lck.unlock();
emptyCond.notify_one();
}
int get()
{
std::unique_lock<std::mutex> lck(m_tex);
emptyCond.wait(lck, [this]{ return !m_quque.empty();});
int value = m_quque.front();
m_quque.pop();
std::cout << "get: " << value << std::endl;
lck.unlock();
fullCond.notify_one();
return value;
}
private:
int m_maxsize = 0;
std::condition_variable fullCond, emptyCond;
std::mutex m_tex;
std::queue<int> m_quque;
};
void producer(MessageQueue& MessageQu, int id, int count)
{
std::thread::id this_thread_id = std::this_thread::get_id(); // 获取当前线程的ID
std::cout << "producer: "<< " " << this_thread_id << std::endl;
for (int i = 0; i < count; ++i)
{
MessageQu.put(id);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
void customer(MessageQueue& MessageQu, int id, int count)
{
std::thread::id this_thread_id = std::this_thread::get_id(); // 获取当前线程的ID
std::cout << "customer: "<< this_thread_id << std::endl;
for (int i = 0; i < count; ++i)
{
MessageQu.get();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
int main(int argc, char const *argv[])
{
const int ququeSize = 10;
const int producerCount = 3;
const int customerCount = 2;
const int valueCont = 10;
MessageQueue MessageQu(ququeSize);
std::vector<std::thread> producers;
std::vector<std::thread> customers;
for (int i = 0; i < producerCount; ++i)
{
producers.emplace_back(producer, std::ref(MessageQu), i, valueCont);
}
for (int i = 0; i < customerCount; ++i)
{
customers.emplace_back(customer, std::ref(MessageQu), i, valueCont);
}
for (auto& produ : producers)
{
produ.join();
}
for(auto& cust : customers)
{
cust.join();
}
return 0;
}
两个线程交替打印 0 1
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
class Printer
{
public:
Printer() : turn(0) {}
void printZero()
{
for (int i = 0; i < 10; ++i)
{ // 打印10次,可以根据需要调整
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [this]() { return turn == 0; });
std::cout << "0";
turn = 1;
cv.notify_all();
}
}
void printOne()
{
for (int i = 0; i < 10; ++i)
{ // 打印10次,可以根据需要调整
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [this]() { return turn == 1; });
std::cout << "1";
turn = 0;
cv.notify_all();
}
}
private:
std::mutex mtx;
std::condition_variable cv;
int turn; // 用于指示当前该哪个线程打印
};
int main()
{
Printer printer;
std::thread t1(&Printer::printZero, &printer);
std::thread t2(&Printer::printOne, &printer);
t1.join();
t2.join();
return 0;
}