当前位置: 首页 > news >正文

算法导论核心代码精粹

《算法导论》中的核心算法整理

以下是根据《算法导论》中的核心算法整理的C++实现示例,涵盖分治、动态规划、图算法等经典内容。示例代码均遵循C++标准,可直接用于学习或项目参考。

分治算法

1. 归并排序
void merge(vector<int>& arr, int l, int m, int r) {vector<int> temp(r - l + 1);int i = l, j = m + 1, k = 0;while (i <= m && j <= r) temp[k++] = arr[i] <= arr[j] ? arr[i++] : arr[j++];while (i <= m) temp[k++] = arr[i++];while (j <= r) temp[k++] = arr[j++];for (int p = 0; p < k; ++p) arr[l + p] = temp[p];
}
void mergeSort(vector<int>& arr, int l, int r) {if (l >= r) return;int m = l + (r - l) / 2;mergeSort(arr, l, m);mergeSort(arr, m + 1, r);merge(arr, l, m, r);
}

2. 快速排序
int partition(vector<int>& arr, int l, int r) {int pivot = arr[r], i = l;for (int j = l; j < r; ++j) {if (arr[j] <= pivot) swap(arr[i++], arr[j]);}swap(arr[i], arr[r]);return i;
}
void quickSort(vector<int>& arr, int l, int r) {if (l >= r) return;int p = partition(arr, l, r);quickSort(arr, l, p - 1);quickSort(arr, p + 1, r);
}

3. 最大子数组问题
struct Subarray { int l, r, sum; };
Subarray maxCrossingSubarray(vector<int>& arr, int l, int m, int r) {int left_sum = INT_MIN, sum = 0, max_l;for (int i = m; i >= l; --i) {sum += arr[i];if (sum > left_sum) { left_sum = sum; max_l = i; }}int right_sum = INT_MIN, max_r;sum = 0;for (int j = m + 1; j <= r; ++j) {sum += arr[j];if (sum > right_sum) { right_sum = sum; max_r = j; }}return {max_l, max_r, left_sum + right_sum};
}
Subarray maxSubarray(vector<int>& arr, int l, int r) {if (l == r) return {l, r, arr[l]};int m = l + (r - l) / 2;Subarray left = maxSubarray(arr, l, m);Subarray right = maxSubarray(arr, m + 1, r);Subarray cross = maxCrossingSubarray(arr, l, m, r);if (left.sum >= right.sum && left.sum >= cross.sum) return left;if (right.sum >= left.sum && right.sum >= cross.sum) return right;return cross;
}

动态规划

4. 钢条切割
int cutRod(vector<int>& price, int n) {vector<int> dp(n + 1, 0);for (int i = 1; i <= n; ++i) {int max_val = INT_MIN;for (int j = 0; j < i; ++j)max_val = max(max_val, price[j] + dp[i - j - 1]);dp[i] = max_val;}return dp[n];
}

5. 矩阵链乘法
int matrixChainOrder(vector<int>& p) {int n = p.size() - 1;vector<vector<int>> dp(n, vector<int>(n, 0));for (int l = 2; l <= n; ++l) {for (int i = 0; i <= n - l; ++i) {int j = i + l - 1;dp[i][j] = INT_MAX;for (int k = i; k < j; ++k) {int cost = dp[i][k] + dp[k + 1][j] + p[i] * p[k + 1] * p[j + 1];dp[i][j] = min(dp[i][j], cost);}}}return dp[0][n - 1];
}

6. 最长公共子序列
int lcs(string& X, string& Y) {int m = X.size(), n = Y.size();vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));for (int i = 1; i <= m; ++i) {for (int j = 1; j <= n; ++j) {if (X[i - 1] == Y[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);}}return dp[m][n];
}

贪心算法

7. 活动选择问题
int activitySelection(vector<pair<int, int>>& activities) {sort(activities.begin(), activities.end(), [](auto& a, auto& b) { return a.second < b.second; });int count = 1, last_end = activities[0].second;for (int i = 1; i < activities.size(); ++i) {if (activities[i].first >= last_end) {++count;last_end = activities[i].second;}}return count;
}
8. 霍夫曼编码
struct Node {char ch;int freq;Node *left, *right;Node(char c, int f) : ch(c), freq(f), left(nullptr), right(nullptr) {}
};
struct Compare {bool operator()(Node* a, Node* b) { return a->freq > b->freq; }
};
void encode(Node* root, string code, unordered_map<char, string>& huffmanCode) {if (!root) return;if (!root->left && !root->right) huffmanCode[root->ch] = code;encode(root->left, code + "0", huffmanCode);encode(root->right, code + "1", huffmanCode);
}
unordered_map<char, string> buildHuffmanTree(string text) {unordered_map<char, int> freq;for (char ch : text) freq[ch]++;priority_queue<Node*, vector<Node*>, Compare> pq;for (auto& pair : freq) pq.push(new Node(pair.first, pair.second));while (pq.size() > 1) {Node* left = pq.top(); pq.pop();Node* right = pq.top(); pq.pop();Node* newNode = new Node('\0', left->freq + right->freq);newNode->left = left;newNode->right = right;pq.push(newNode);}unordered_map<char, string> huffmanCode;encode(pq.top(), "", huffmanCode);return huffmanCode;
}

图算法

9. BFS遍历
void bfs(vector<vector<int>>& graph, int start) {queue<int> q;vector<bool> visited(graph.size(), false);q.push(start);visited[start] = true;while (!q.empty()) {int u = q.front(); q.pop();cout << u << " ";for (int v : graph[u]) {if (!visited[v]) {visited[v] = true;q.push(v);}}}
}
10. DFS遍历
void dfsUtil(vector<vector<int>>& graph, int u, vector<bool>& visited) {visited[u] = true;cout << u << " ";for (int v : graph[u]) {if (!visited[v]) dfsUtil(graph, v, visited);}
}
void dfs(vector<vector<int>>& graph, int start) {vector<bool> visited(graph.size(), false);dfsUtil(graph, start, visited);
}

11. Dijkstra最短路径
void dijkstra(vector<vector<pair<int, int>>>& graph, int src) {priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;vector<int> dist(graph.size(), INT_MAX);pq.push({0, src});dist[src] = 0;while (!pq.empty()) {int u = pq.top().second; pq.pop();for (auto& edge : graph[u]) {int v = edge.first, weight = edge.second;if (dist[v] > dist[u] + weight) {dist[v] = dist[u] + weight;pq.push({dist[v], v});}}}
}


其他重要算法

12. 红黑树插入
enum Color { RED, BLACK };
struct Node {int data;Color color;Node *left, *right, *parent;Node(int d) : data(d), color(RED), left(nullptr), right(nullptr), parent(nullptr) {}
};
void insertFixup(Node*& root, Node* pt) {while (pt != root && pt->parent->color == RED) {Node* uncle = (pt->parent == pt->parent->parent->left) ? pt->parent->parent->right : pt->parent->parent->left;if (uncle && uncle->color == RED) {pt->parent->color = BLACK;uncle->color = BLACK;pt->parent->parent->color = RED;pt = pt->parent->parent;} else {if (pt->parent == pt->parent->parent->left && pt == pt->parent->right) {pt = pt->parent;leftRotate(root, pt);}pt->parent->color = BLACK;pt->parent->parent->color = RED;rightRotate(root, pt->parent->parent);}}root->color = BLACK;
}

(因篇幅限制,剩余示例可扩展实现:KMP字符串匹配、FFT快速傅里叶变换、NP完全问题验证算法等。)

KMP(Knuth-Morris-Pratt)算法

KMP算法简介

KMP(Knuth-Morris-Pratt)算法是一种高效的字符串匹配算法,通过预处理模式串构建部分匹配表(Partial Match Table),避免主串指针回溯,时间复杂度为O(n+m)。

C++实现代码模板

#include <vector>
#include <string>
using namespace std;vector<int> computeLPS(const string& pattern) {vector<int> lps(pattern.size(), 0);int len = 0;for (int i = 1; i < pattern.size(); ) {if (pattern[i] == pattern[len]) {lps[i++] = ++len;} else {if (len != 0) len = lps[len-1];else lps[i++] = 0;}}return lps;
}vector<int> KMPSearch(const string& text, const string& pattern) {vector<int> lps = computeLPS(pattern);vector<int> matches;int i = 0, j = 0;while (i < text.size()) {if (text[i] == pattern[j]) {i++; j++;if (j == pattern.size()) {matches.push_back(i - j);j = lps[j-1];}} else {if (j != 0) j = lps[j-1];else i++;}}return matches;
}

实例集合

每个示例包含测试字符串和模式串:

示例1
文本: "ABABDABACDABABCABAB"
模式: "ABABCABAB"
输出: [10]

示例2
文本: "AABAACAADAABAABA"
模式: "AABA"
输出: [0, 9, 12]

示例3
文本: "THIS IS A TEST TEXT"
模式: "TEST"
输出: [10]

示例4
文本: "AAAAABAAABA"
模式: "AAAA"
输出: [0, 1]

示例5
文本: "ABCDABCDABDE"
模式: "BCD"
输出: [1, 5]

示例6
文本: "ABCABCABCABC"
模式: "ABCABC"
输出: [0, 3, 6]

示例7
文本: "GEEKS FOR GEEKS"
模式: "GEEK"
输出: [0, 10]

示例8
文本: "ABABABABABABAB"
模式: "ABABA"
输出: [0, 2, 4, 6, 8]

示例9
文本: "1111111111"
模式: "111"
输出: [0,1,2,3,4,5,6,7]

示例10
文本: "ABC#DEF#GHI#"
模式: "#"
输出: [3,7,11]

边界测试用例

示例11
文本: ""
模式: "ABC"
输出: []

示例12
文本: "ABCD"
模式: ""
输出: []

示例13
文本: "A"
模式: "A"
输出: [0]

示例14
文本: "ABCDEF"
模式: "XYZ"
输出: []

示例15
文本: "重复重复重复"
模式: "重复"
输出: [0, 2, 4]

特殊字符测试

示例16
文本: "abc$123*^xx"
模式: "$123*"
输出: [3]

示例17
文本: "你好世界你好"
模式: "你好"
输出: [0, 4]

示例18
文本: "a\nb\tc\0d"
模式: "b\tc"
输出: [2]

性能测试用例

示例19
文本: string(1000000, 'A') + "B"
模式: string(1000, 'A') + "B"
输出: [999000]

示例20
文本: "ABCD"*10000
模式: "CDAB"
输出: [2,6,10,...,39998]

综合应用场景

示例21 - DNA序列匹配
文本: "AGCTAGCTAGCT"
模式: "AGCT"
输出: [0,4,8]

示例22 - 日志分析
文本: "ERROR:404;ERROR:500;WARN:301"
模式: "ERROR:"
输出: [0, 12]

示例23 - 二进制模式
文本: "\x01\x00\x01\x01\x00"
模式: "\x01\x00"
输出: [0, 3]

示例24 - URL路由匹配
文本: "/user/profile/account/settings"
模式: "/account/"
输出: [13]

示例25 - 版本号检测
文本: "v1.2.3 v1.2.4 v2.0.1"
模式: "v1.2."
输出: [0, 6]

复杂模式示例

示例26 - 重叠匹配
文本: "ababababa"
模式: "aba"
输出: [0,2,4,6]

示例27 - 前后缀测试
文本: "mississippi"
模式: "issi"
输出: [1,4]

示例28 - 全匹配
文本: "aaaaa"
模式: "aa"
输出: [0,1,2,3]

示例29 - Unicode字符
文本: "😊🐱🐶🍎😊"
模式: "😊"
输出: [0,4]

示例30 - 混合编码
文本: "中文ABC123!@#"
模式: "ABC"
输出: [2]

使用说明

  1. 将computeLPS和KMPSearch函数复制到C++项目中
  2. 使用g++编译时需要添加-std=c++11标准
  3. 结果返回所有匹配的起始位置索引(从0开始)
  4. 空模式或空文本时返回空向量

复杂度分析

  • 预处理阶段:O(m) 其中m为模式串长度
  • 匹配阶段:O(n) 其中n为文本长度
  • 总时间复杂度:O(n+m)
  • 空间复杂度:O(m) 用于存储LPS数组

场景下的C++插入排序

以下是不同场景下的C++插入排序实例,涵盖基础实现、变体及优化版本。每个示例独立且可直接运行,通过注释说明核心逻辑。

基础插入排序(升序)

void insertionSort(int arr[], int n) {for (int i = 1; i < n; i++) {int key = arr[i];int j = i - 1;while (j >= 0 && arr[j] > key) {arr[j + 1] = arr[j];j--;}arr[j + 1] = key;}
}

降序排列

void insertionSortDesc(int arr[], int n) {for (int i = 1; i < n; i++) {int key = arr[i];int j = i - 1;while (j >= 0 && arr[j] < key) { // 比较符号反向arr[j + 1] = arr[j];j--;}arr[j + 1] = key;}
}

字符串数组排序

void insertionSortStrings(string arr[], int n) {for (int i = 1; i < n; i++) {string key = arr[i];int j = i - 1;while (j >= 0 && arr[j] > key) {arr[j + 1] = arr[j];j--;}arr[j + 1] = key;}
}

结构体排序(按年龄)

struct Person {string name;int age;
};void sortByAge(Person people[], int n) {for (int i = 1; i < n; i++) {Person key = people[i];int j = i - 1;while (j >= 0 && people[j].age > key.age) {people[j + 1] = people[j];j--;}people[j + 1] = key;}
}

双向插入排序

void bidirectionalInsertionSort(int arr[], int n) {int left = 0, right = n - 1;while (left < right) {for (int i = left + 1; i <= right; i++) {int key = arr[i];int j = i - 1;while (j >= left && arr[j] > key) {arr[j + 1] = arr[j];j--;}arr[j + 1] = key;}right--;}
}

递归实现

void recursiveInsertionSort(int arr[], int n) {if (n <= 1) return;recursiveInsertionSort(arr, n - 1);int key = arr[n - 1];int j = n - 2;while (j >= 0 && arr[j] > key) {arr[j + 1] = arr[j];j--;}arr[j + 1] = key;
}

使用STL的插入排序

void stlInsertionSort(vector<int>& v) {for (auto it = v.begin(); it != v.end(); ++it) {auto const insertion_point = upper_bound(v.begin(), it, *it);rotate(insertion_point, it, it + 1);}
}

链表排序

struct Node {int data;Node* next;
};void insertionSortLinkedList(Node** head) {Node* sorted = nullptr;Node* current = *head;while (current != nullptr) {Node* next = current->next;if (sorted == nullptr || sorted->data >= current->data) {current->next = sorted;sorted = current;} else {Node* temp = sorted;while (temp->next != nullptr && temp->next->data < current->data) {temp = temp->next;}current->next = temp->next;temp->next = current;}current = next;}*head = sorted;
}

浮点数排序

void insertionSortFloat(float arr[], int n) {for (int i = 1; i < n; i++) {float key = arr[i];int j = i - 1;while (j >= 0 && arr[j] > key) {arr[j + 1] = arr[j];j--;}arr[j + 1] = key;}
}

带比较函数的泛型版本

template <typename T>
void insertionSortGeneric(T arr[], int n, bool (*compare)(T, T)) {for (int i = 1; i < n; i++) {T key = arr[i];int j = i - 1;while (j >= 0 && compare(arr[j], key)) {arr[j + 1] = arr[j];j--;}arr[j + 1] = key;}
}

优化版(二分查找插入位置)

void binaryInsertionSort(int arr[], int n) {for (int i = 1; i < n; i++) {int key = arr[i];int left = 0, right = i;while (left < right) {int mid = left + (right - left) / 2;if (arr[mid] <= key) left = mid + 1;else right = mid;}for (int j = i; j > left; j--) {arr[j] = arr[j - 1];}arr[left] = key;}
}

完整代码示例可通过C++编译器直接测试,根据实际需求调整数据类型和比较逻辑。

    C++模拟动态表

    以下是C++模拟动态表(如std::vector)插入操作的示例,涵盖不同场景和技巧。所有示例均基于动态数组的实现逻辑,可直接运行测试。

    示例1:基础动态表尾部插入

    #include <iostream>
    using namespace std;class DynamicArray {int* arr;int capacity;int size;
    public:DynamicArray() : capacity(1), size(0) {arr = new int[capacity];}void push_back(int val) {if (size == capacity) {capacity *= 2;int* temp = new int[capacity];for (int i = 0; i < size; i++) temp[i] = arr[i];delete[] arr;arr = temp;}arr[size++] = val;}void print() {for (int i = 0; i < size; i++) cout << arr[i] << " ";}
    };int main() {DynamicArray da;da.push_back(10); // 插入10da.print(); // 输出: 10
    }
    

    示例2:指定位置插入元素

    void insert(int index, int val) {if (index < 0 || index > size) throw "Index out of bounds";if (size == capacity) {capacity *= 2;int* temp = new int[capacity];for (int i = 0; i < index; i++) temp[i] = arr[i];temp[index] = val;for (int i = index; i < size; i++) temp[i+1] = arr[i];delete[] arr;arr = temp;} else {for (int i = size; i > index; i--) arr[i] = arr[i-1];arr[index] = val;}size++;
    }
    

    示例3:插入时缩小容量检查

    void push_back(int val) {if (size == capacity) {capacity = (capacity == 0) ? 1 : capacity * 2;int* temp = new int[capacity];for (int i = 0; i < size; i++) temp[i] = arr[i];delete[] arr;arr = temp;}arr[size++] = val;
    }
    

    示例4:批量插入元素

    void insertRange(int index, int* vals, int count) {while (size + count > capacity) capacity *= 2;int* temp = new int[capacity];for (int i = 0; i < index; i++) temp[i] = arr[i];for (int i = 0; i < count; i++) temp[index + i] = vals[i];for (int i = index; i < size; i++) temp[i + count] = arr[i];delete[] arr;arr = temp;size += count;
    }
    

    示例5:插入排序式插入

    void sortedInsert(int val) {push_back(val); // 先插入尾部for (int i = size - 1; i > 0 && arr[i] < arr[i-1]; i--) {swap(arr[i], arr[i-1]);}
    }
    

    可根据实际需求组合这些示例中的技术点,构建更复杂的动态表结构。

    C++中实现链表

    在C++中实现链表反转是一个常见的数据结构和算法问题。以下是多种实现方法和示例,涵盖递归、迭代以及不同场景的优化方案。

    基础迭代法

    struct ListNode {int val;ListNode* next;ListNode(int x) : val(x), next(nullptr) {}
    };ListNode* reverseList(ListNode* head) {ListNode* prev = nullptr;ListNode* curr = head;while (curr) {ListNode* next = curr->next;curr->next = prev;prev = curr;curr = next;}return prev;
    }
    

    递归实现

    ListNode* reverseListRecursive(ListNode* head) {if (!head || !head->next) return head;ListNode* newHead = reverseListRecursive(head->next);head->next->next = head;head->next = nullptr;return newHead;
    }
    

    头插法反转

    ListNode* reverseListHeadInsert(ListNode* head) {ListNode dummy(0);while (head) {ListNode* next = head->next;head->next = dummy.next;dummy.next = head;head = next;}return dummy.next;
    }
    

    反转部分链表(指定区间)

    ListNode* reverseBetween(ListNode* head, int m, int n) {ListNode dummy(0);dummy.next = head;ListNode* pre = &dummy;for (int i = 0; i < m - 1; ++i) pre = pre->next;ListNode* curr = pre->next;for (int i = 0; i < n - m; ++i) {ListNode* next = curr->next;curr->next = next->next;next->next = pre->next;pre->next = next;}return dummy.next;
    }
    

    每K个节点一组反转

    ListNode* reverseKGroup(ListNode* head, int k) {ListNode* curr = head;int count = 0;while (curr && count < k) {curr = curr->next;count++;}if (count == k) {curr = reverseKGroup(curr, k);while (count-- > 0) {ListNode* tmp = head->next;head->next = curr;curr = head;head = tmp;}head = curr;}return head;
    }
    

    双指针优化

    ListNode* reverseListTwoPointer(ListNode* head) {ListNode* slow = nullptr;ListNode* fast = head;while (fast) {ListNode* next = fast->next;fast->next = slow;slow = fast;fast = next;}return slow;
    }
    

    反转链表并返回新头尾

    pair<ListNode*, ListNode*> reverseListReturnHeadTail(ListNode* head) {if (!head || !head->next) return {head, head};auto [newHead, newTail] = reverseListReturnHeadTail(head->next);newTail->next = head;head->next = nullptr;return {newHead, head};
    }
    

    使用栈反转

    ListNode* reverseListUsingStack(ListNode* head) {stack<ListNode*> s;while (head) {s.push(head);head = head->next;}ListNode dummy(0);ListNode* curr = &dummy;while (!s.empty()) {curr->next = s.top();s.pop();curr = curr->next;}curr->next = nullptr;return dummy.next;
    }
    

    反转交替K个节点

    ListNode* reverseAlternateK(ListNode* head, int k) {ListNode* curr = head;ListNode* prev = nullptr;ListNode* next = nullptr;int count = 0;while (curr && count < k) {next = curr->next;curr->next = prev;prev = curr;curr = next;count++;}if (head) head->next = curr;count = 0;while (curr && count < k - 1) {curr = curr->next;count++;}if (curr) curr->next = reverseAlternateK(curr->next, k);return prev;
    }
    

    上示例盖了链表反转的多种场景,包括基础反转、部分反转、分组反转等。实际应用中可根据需求选择合适方法,注意处理边界条件(如空链表或单节点链表)。

    C++的二叉搜索树

    以下是一些基于C++的二叉搜索树(BST)实例,涵盖基础操作、常见算法和实际应用场景。每个例子均附简要说明,可直接运行或扩展。


    基础操作

    插入节点

    struct Node {int data;Node* left;Node* right;Node(int val) : data(val), left(nullptr), right(nullptr) {}
    };void insert(Node* &root, int val) {if (!root) root = new Node(val);else if (val < root->data) insert(root->left, val);else insert(root->right, val);
    }
    

    查找节点

    bool search(Node* root, int val) {if (!root) return false;if (root->data == val) return true;return val < root->data ? search(root->left, val) : search(root->right, val);
    }
    

    删除节点

    Node* deleteNode(Node* root, int val) {if (!root) return root;if (val < root->data) root->left = deleteNode(root->left, val);else if (val > root->data) root->right = deleteNode(root->right, val);else {if (!root->left) return root->right;if (!root->right) return root->left;Node* temp = root->right;while (temp->left) temp = temp->left;root->data = temp->data;root->right = deleteNode(root->right, temp->data);}return root;
    }
    


    遍历与输出

    中序遍历(升序输出)

    void inorder(Node* root) {if (!root) return;inorder(root->left);std::cout << root->data << " ";inorder(root->right);
    }
    

    层序遍历(广度优先)

    #include <queue>
    void levelOrder(Node* root) {if (!root) return;std::queue<Node*> q;q.push(root);while (!q.empty()) {Node* curr = q.front();q.pop();std::cout << curr->data << " ";if (curr->left) q.push(curr->left);if (curr->right) q.push(curr->right);}
    }
    


    实用功能

    计算树的高度

    int height(Node* root) {if (!root) return 0;return 1 + std::max(height(root->left), height(root->right));
    }
    

    检查是否为BST

    bool isBST(Node* root, Node* min = nullptr, Node* max = nullptr) {if (!root) return true;if (min && root->data <= min->data) return false;if (max && root->data >= max->data) return false;return isBST(root->left, min, root) && isBST(root->right, root, max);
    }
    

    寻找第k小的元素

    int kthSmallest(Node* root, int& k) {if (!root) return -1;int left = kthSmallest(root->left, k);if (left != -1) return left;if (--k == 0) return root->data;return kthSmallest(root->right, k);
    }
    


    高级应用

    BST转双向链表

    void treeToDoublyList(Node* root, Node* &prev, Node* &head) {if (!root) return;treeToDoublyList(root->left, prev, head);if (!prev) head = root;else {prev->right = root;root->left = prev;}prev = root;treeToDoublyList(root->right, prev, head);
    }
    

    从有序数组构造BST

    Node* sortedArrayToBST(std::vector<int>& nums, int start, int end) {if (start > end) return nullptr;int mid = start + (end - start) / 2;Node* root = new Node(nums[mid]);root->left = sortedArrayToBST(nums, start, mid - 1);root->right = sortedArrayToBST(nums, mid + 1, end);return root;
    }
    

    范围查询

    void rangeQuery(Node* root, int L, int R, std::vector<int>& res) {if (!root) return;if (root->data > L) rangeQuery(root->left, L, R, res);if (root->data >= L && root->data <= R) res.push_back(root->data);if (root->data < R) rangeQuery(root->right, L, R, res);
    }
    

    以上代码片段可直接组合使用或独立扩展。

    基于C++的BFS

    以下是一些基于C++的BFS(广度优先搜索)遍历实例,涵盖不同应用场景和数据结构。每个例子包含关键代码片段和简要说明,可直接用于实际项目或学习。

    基础BFS遍历(无向图)

    #include <queue>
    #include <vector>
    using namespace std;void bfs(vector<vector<int>>& graph, int start) {queue<int> q;vector<bool> visited(graph.size(), false);q.push(start);visited[start] = true;while (!q.empty()) {int node = q.front();q.pop();cout << node << " ";for (int neighbor : graph[node]) {if (!visited[neighbor]) {visited[neighbor] = true;q.push(neighbor);}}}
    }
    

    迷宫最短路径(网格BFS)

    struct Point { int x, y; };int dirs[4][2] = {{-1,0}, {1,0}, {0,-1}, {0,1}};int bfsMaze(vector<vector<int>>& maze, Point start, Point end) {queue<Point> q;vector<vector<int>> dist(maze.size(), vector<int>(maze[0].size(), -1));q.push(start);dist[start.x][start.y] = 0;while (!q.empty()) {Point p = q.front();q.pop();if (p.x == end.x && p.y == end.y) return dist[p.x][p.y];for (auto& dir : dirs) {int nx = p.x + dir[0], ny = p.y + dir[1];if (nx >= 0 && nx < maze.size() && ny >= 0 && ny < maze[0].size() && maze[nx][ny] == 0 && dist[nx][ny] == -1) {dist[nx][ny] = dist[p.x][p.y] + 1;q.push({nx, ny});}}}return -1;
    }
    

    层级遍历二叉树

    struct TreeNode {int val;TreeNode *left, *right;
    };void bfsTree(TreeNode* root) {if (!root) return;queue<TreeNode*> q;q.push(root);while (!q.empty()) {int levelSize = q.size();for (int i = 0; i < levelSize; ++i) {TreeNode* node = q.front();q.pop();cout << node->val << " ";if (node->left) q.push(node->left);if (node->right) q.push(node->right);}cout << endl; // 换行表示不同层级}
    }
    

    拓扑排序(有向无环图)

    vector<int> topologicalSort(vector<vector<int>>& graph, vector<int>& inDegree) {queue<int> q;vector<int> result;for (int i = 0; i < inDegree.size(); ++i) {if (inDegree[i] == 0) q.push(i);}while (!q.empty()) {int u = q.front();q.pop();result.push_back(u);for (int v : graph[u]) {if (--inDegree[v] == 0) {q.push(v);}}}return result.size() == graph.size() ? result : vector<int>();
    }
    

    多源BFS(多个起点)

    vector<vector<int>> multiSourceBfs(vector<vector<int>>& grid, vector<Point>& sources) {queue<Point> q;vector<vector<int>> dist(grid.size(), vector<int>(grid[0].size(), INT_MAX));for (auto& p : sources) {dist[p.x][p.y] = 0;q.push(p);}while (!q.empty()) {Point p = q.front();q.pop();for (auto& dir : dirs) {int nx = p.x + dir[0], ny = p.y + dir[1];if (nx >= 0 && nx < grid.size() && ny >= 0 && ny < grid[0].size() && grid[nx][ny] == 1 && dist[nx][ny] > dist[p.x][p.y] + 1) {dist[nx][ny] = dist[p.x][p.y] + 1;q.push({nx, ny});}}}return dist;
    }
    

    双向BFS(单词接龙问题)

    int ladderLength(string beginWord, string endWord, vector<string>& wordList) {unordered_set<string> dict(wordList.begin(), wordList.end());if (!dict.count(endWord)) return 0;unordered_set<string> beginSet{beginWord}, endSet{endWord};int steps = 1;while (!beginSet.empty() && !endSet.empty()) {if (beginSet.size() > endSet.size()) swap(beginSet, endSet);unordered_set<string> tempSet;for (string word : beginSet) {for (int i = 0; i < word.size(); ++i) {char original = word[i];for (char c = 'a'; c <= 'z'; ++c) {word[i] = c;if (endSet.count(word)) return steps + 1;if (dict.count(word)) {tempSet.insert(word);dict.erase(word);}}word[i] = original;}}beginSet = tempSet;steps++;}return 0;
    }
    

    0-1权图BFS(双端队列)

    int bfs01(vector<vector<pair<int, int>>>& graph, int start, int end) {deque<int> dq;vector<int> dist(graph.size(), INT_MAX);dist[start] = 0;dq.push_front(start);while (!dq.empty()) {int u = dq.front();dq.pop_front();for (auto& [v, w] : graph[u]) {if (dist[v] > dist[u] + w) {dist[v] = dist[u] + w;w == 0 ? dq.push_front(v) : dq.push_back(v);}}}return dist[end];
    }
    

    状态压缩BFS(八数码问题)

    int slidingPuzzle(vector<vector<int>>& board) {string target = "123450";string start;for (auto& row : board) {for (int num : row) {start += to_string(num);}}vector<vector<int>> dirs = {{1,3}, {0,2,4}, {1,5}, {0,4}, {1,3,5}, {2,4}};queue<string> q{{start}};unordered_set<string> visited{start};int steps = 0;while (!q.empty()) {int size = q.size();while (size--) {string curr = q.front();q.pop();if (curr == target) return steps;int zero = curr.find('0');for (int next : dirs[zero]) {string neighbor = curr;swap(neighbor[zero], neighbor[next]);if (!visited.count(neighbor)) {visited.insert(neighbor);q.push(neighbor);}}}steps++;}return -1;
    }
    

    1. 网页爬虫:基于URL的层级抓取
    2. 连通区域检测:图像处理中的像素连通性分析
    3. 游戏AI:寻路算法(A*的基础)
    4. 电路布线:VLSI设计中的网格布线

    每个场景均可通过调整上述基础模板实现。BFS的核心在于队列管理和状态记录,实际应用中需根据问题特点设计节点表达方式和转移规则。

    基于C++的社交网络好友推荐

    以下是一些基于C++的社交网络好友推荐实现思路和示例代码片段,涵盖不同算法和场景的应用:


    基于共同好友的推荐

    void recommendByCommonFriends(const User& targetUser, const SocialGraph& graph) {unordered_map<UserId, int> commonCounts;for (const auto& friendId : targetUser.friends) {for (const auto& potentialFriend : graph.getUser(friendId).friends) {if (!targetUser.isFriend(potentialFriend)) {commonCounts[potentialFriend]++;}}}// 按共同好友数排序输出推荐
    }
    

    Jaccard相似度推荐

    vector<UserId> recommendByJaccard(const User& u1, const User& u2) {unordered_set<UserId> unionSet(u1.friends.begin(), u1.friends.end());unionSet.insert(u2.friends.begin(), u2.friends.end());unordered_set<UserId> intersection;for (auto& f : u1.friends) {if (u2.friends.count(f)) intersection.insert(f);}double similarity = intersection.size() / (double)unionSet.size();return similarity > 0.2 ? getTopRecommendations() : vector<UserId>();
    }
    

    基于图的BFS推荐

    void bfsRecommendation(UserId start, const SocialGraph& graph, int depth) {queue<pair<UserId, int>> q;unordered_set<UserId> visited;q.push({start, 0});while (!q.empty()) {auto [current, dist] = q.front();q.pop();if (dist == depth) {recommendUser(current);continue;}for (UserId neighbor : graph.getFriends(current)) {if (!visited.count(neighbor)) {visited.insert(neighbor);q.push({neighbor, dist+1});}}}
    }
    

    矩阵分解推荐

    void matrixFactorization(const MatrixXd& R, int k, double alpha, double lambda) {MatrixXd P = MatrixXd::Random(R.rows(), k);MatrixXd Q = MatrixXd::Random(k, R.cols());for (int iter = 0; iter < 50; ++iter) {for (int i = 0; i < R.rows(); ++i) {for (int j = 0; j < R.cols(); ++j) {if (R(i,j) > 0) {double error = R(i,j) - P.row(i)*Q.col(j);P.row(i) += alpha * (2 * error * Q.col(j).transpose() - lambda * P.row(i));Q.col(j) += alpha * (2 * error * P.row(i).transpose() - lambda * Q.col(j));}}}}
    }
    

    基于兴趣标签的推荐

    vector<UserId> recommendByTags(const User& target, const vector<User>& users) {vector<pair<UserId, double>> scores;for (const auto& user : users) {if (user.id == target.id) continue;double score = cosineSimilarity(target.tags, user.tags);scores.emplace_back(user.id, score);}sort(scores.begin(), scores.end(), [](auto& a, auto& b) {return a.second > b.second;});vector<UserId> recommendations;for (int i = 0; i < min(5, (int)scores.size()); ++i) {recommendations.push_back(scores[i].first);}return recommendations;
    }
    


    其他实现方向(需完整代码可扩展)

    1. 基于PageRank的推荐
    void calculatePageRank(const SocialGraph& graph) {// 实现PageRank算法计算用户影响力
    }
    

    2. 社团发现推荐
    vector<Community> detectCommunities(Graph& g) {// 使用Louvain等方法发现社团
    }
    

    3. 基于深度学习的嵌入
    class GraphSAGE : public torch::nn::Module {// 实现图神经网络嵌入
    };
    

    4. 实时推荐系统
    class RealTimeRecommender {// 使用消息队列处理实时交互
    };
    

    5. 地理位置推荐
    vector<UserId> recommendByLocation(UserId userId, double radiusKm) {// 基于地理位置的推荐逻辑
    }
    

    6. 混合推荐系统
    void hybridRecommendation(const User& user) {// 组合多种推荐策略
    }
    

    7. 基于活动的推荐
    void eventBasedRecommendation(UserId userId) {// 根据用户参与的活动推荐
    }
    
    8. 社交影响力推荐
    void influenceBasedRecommendation() {// 基于用户影响力评分
    }
    
    9. 时间衰减推荐
    double timeDecayScore(Interaction interaction) {// 实现时间衰减因子
    }
    
    10. 社交图谱嵌入
    void graphEmbedding() {// 使用node2vec等算法
    }
    

    完整系统架构示例

    class FriendRecommender {
    private:SocialGraph graph;RecommenderAlgorithm* algorithm;public:void setAlgorithm(RecommenderAlgorithm* algo) {algorithm = algo;}vector<Recommendation> generateRecommendations(UserId userId) {return algorithm->recommend(userId, graph);}
    };// 策略模式实现不同算法
    class RecommenderAlgorithm {
    public:virtual vector<Recommendation> recommend(UserId, SocialGraph&) = 0;
    };// 具体算法实现
    class CommonFriendsAlgorithm : public RecommenderAlgorithm {// 实现具体逻辑
    };
    

    性能优化技巧

    // 使用位集加速共同好友计算
    bitset<MAX_USERS> getFriendBitset(const User& user) {bitset<MAX_USERS> bs;for (auto fid : user.friends) bs.set(fid);return bs;
    }// 并行计算推荐
    void parallelRecommend() {#pragma omp parallel forfor (int i = 0; i < users.size(); ++i) {// 并行处理每个用户的推荐}
    }
    

    以上示例涵盖了从基础到进阶的各种好友推荐实现方法。完整实现需要结合具体社交网络的数据结构和业务需求进行扩展。每个示例都可以作为独立模块或组合成混合推荐系统。

    DFS(深度优先搜索)

    DFS拓扑排序简介

    DFS(深度优先搜索)拓扑排序是一种用于有向无环图(DAG)的排序算法,通过递归或栈实现节点的线性排序,确保每个节点在其前驱节点之后出现。

    基本实现代码

    以下是C++中DFS拓扑排序的基础代码框架:

    #include <iostream>
    #include <vector>
    #include <stack>
    using namespace std;void topologicalSortUtil(int v, vector<bool>& visited, stack<int>& Stack, const vector<vector<int>>& adj) {visited[v] = true;for (int i : adj[v]) {if (!visited[i]) {topologicalSortUtil(i, visited, Stack, adj);}}Stack.push(v);
    }void topologicalSort(int V, const vector<vector<int>>& adj) {stack<int> Stack;vector<bool> visited(V, false);for (int i = 0; i < V; ++i) {if (!visited[i]) {topologicalSortUtil(i, visited, Stack, adj);}}while (!Stack.empty()) {cout << Stack.top() << " ";Stack.pop();}
    }
    

    应用实例分类

    以下是DFS拓扑排序的应用实例,涵盖不同场景:

    课程安排问题

    给定课程间的先修关系,输出可行的学习顺序。

    vector<vector<int>> adj = {{1, 2}, {3}, {3}, {}};
    topologicalSort(4, adj); // 输出: 0 2 1 3
    
    任务调度

    根据任务依赖关系生成执行顺序。

    vecto
    http://www.dtcms.com/a/304411.html

    相关文章:

  1. USRP X440 和USRP X410 直接RF采样架构的优势
  2. 【51单片机静态1位数码管显示按键倒计时控制蜂鸣器】2022-9-28
  3. Wndows Docker Desktop-Unexpected WSL error
  4. AUTOSAR Mcal Dio - 模块介绍 + EB配置工具介绍
  5. 【开源项目】轻量加速利器 HubProxy 自建 Docker、GitHub 下载加速服务
  6. Doris中文检索效果调优
  7. 自组织遗传算法(Self-Organizing Genetic Algorithm, SOGA)求解Rastrigin函数优化问题
  8. 【Rust并发集合】如何在多线程中并发安全地使用集合
  9. 【AI News | 20250728】每日AI进展
  10. 接口自动化测试pytest框架
  11. 网络原理--HTTPHTTPS
  12. JAVA_TWENTY—ONE_单元测试+注解+反射
  13. MySQL——MVCC
  14. ftp加ssl,升级ftps
  15. 解决Spring MVC中@PathVariable参数为null导致的404问题:全面解析与最佳实践
  16. Spring MVC数据传递全攻略
  17. 架构实战——互联网架构模板(“网络层”技术)
  18. WINCC选项组配置
  19. Spring Boot 请求限流实战:基于 IP 的高效防刷策略
  20. Postgresql 查询使用正则
  21. SQL158 每类视频近一个月的转发量/率
  22. Java 大视界 -- Java 大数据在智能教育学习社区知识图谱构建与知识传播分析中的应用(370)
  23. DeepCompare文件深度对比软件的差异内容提取与保存功能深度解析
  24. Go语言新手村:轻松理解变量、常量和枚举用法
  25. 论文阅读--射频电源在半导体领域的应用
  26. 《从HTTP到IP证书:网络身份验证的下一站革命》
  27. 如何使用 Git 钩子 hooks 自动化任务?
  28. 【MySQL】数据库的简单介绍
  29. [2025CVPR-图象分类]ProAPO:视觉分类的渐进式自动提示优化
  30. java基础面试题(6)--Object