搜索的钇铥铥小知识——c++中的各列排序算法

一、基础算法

1. 递归与迭代
  • 递归:函数直接或间接调用自身(需注意终止条件,避免栈溢出)。
    示例:计算阶乘

    cpp

    int factorial(int n) {
        return (n == 0) ? 1 : n * factorial(n - 1); // 递归版本
    }
    
  • 迭代:通过循环实现重复计算(效率更高,适合大数运算)。
    示例:计算阶乘

    cpp

    int factorial(int n) {
        int result = 1;
        for (int i = 1; i <= n; ++i) result *= i; // 迭代版本
        return result;
    }
    
2. 数学算法
  • 最大公约数(GCD):欧几里得算法(辗转相除法)。

    cpp

    int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }
    
  • 素数判断:试除法(优化:只需试除到 √n)。

    cpp

    bool isPrime(int n) {
        if (n <= 1) return false;
        for (int i = 2; i * i <= n; ++i) {
            if (n % i == 0) return false;
        }
        return true;
    }
    

二、排序算法

算法名称时间复杂度空间复杂度稳定性特点及适用场景
冒泡排序O(n²)O(1)稳定简单,适合小规模数据
选择排序O(n²)O(1)不稳定每次选最小值,交换次数少
插入排序O(n²)O(1)稳定局部有序时效率高,适合近乎有序数据
快速排序平均 O (n log n)O(log n)不稳定常用排序,适合大规模数据
归并排序O(n log n)O(n)稳定分治思想,适合外排序
堆排序O(n log n)O(1)不稳定原地排序,适合取前 k 大元素
计数排序O(n + k)O(k)稳定k 为值域范围,适合整数排序
基数排序O(d(n + k))O(n + k)稳定d 为位数,适合多关键字排序
快速排序代码示例:

cpp

void quickSort(int arr[], int low, int high) {
    if (low < high) {
        int pivot = arr[high]; // 选最后一个元素为基准
        int i = low - 1;
        for (int j = low; j < high; ++j) {
            if (arr[j] <= pivot) {
                swap(arr[++i], arr[j]);
            }
        }
        swap(arr[i + 1], arr[high]);
        quickSort(arr, low, i);
        quickSort(arr, i + 2, high);
    }
}

三、搜索算法

1. 线性搜索
  • 逐个元素查找,时间复杂度 O (n),适合无序数据。

    cpp

    int linearSearch(int arr[], int n, int target) {
        for (int i = 0; i < n; ++i) {
            if (arr[i] == target) return i;
        }
        return -1;
    }
    
2. 二分搜索(Binary Search)
  • 要求数据有序,时间复杂度 O (log n)。

    cpp

    int binarySearch(int arr[], int n, int target) {
        int left = 0, right = n - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2; // 防溢出
            if (arr[mid] == target) return mid;
            else if (arr[mid] < target) left = mid + 1;
            else right = mid - 1;
        }
        return -1;
    }
    
3. 广度优先搜索(BFS)
  • 用于图或树的遍历,找最短路径(无权图)。

    cpp

    void bfs(vector<vector<int>>& graph, int start) {
        vector<bool> visited(graph.size(), false);
        queue<int> q;
        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);
                }
            }
        }
    }
    
4. 深度优先搜索(DFS)
  • 用于图或树的遍历,找连通分量、回溯算法等。

    cpp

    void dfs(vector<vector<int>>& graph, int node, vector<bool>& visited) {
        visited[node] = true;
        cout << node << " ";
        for (int neighbor : graph[node]) {
            if (!visited[neighbor]) {
                dfs(graph, neighbor, visited);
            }
        }
    }
    

四、图论算法

1. 最短路径算法
  • Dijkstra 算法:单源最短路径(非负权图)。

    cpp

    // 使用优先队列优化
    void dijkstra(vector<vector<pair<int, int>>>& graph, int start) {
        int n = graph.size();
        vector<int> dist(n, INT_MAX);
        dist[start] = 0;
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
        pq.push({0, start});
        while (!pq.empty()) {
            int currentDist, u;
            tie(currentDist, u) = pq.top(); pq.pop();
            if (currentDist > dist[u]) continue;
            for (auto& [v, w] : graph[u]) {
                if (dist[v] > dist[u] + w) {
                    dist[v] = dist[u] + w;
                    pq.push({dist[v], v});
                }
            }
        }
    }
    
  • Bellman-Ford 算法:单源最短路径(可处理负权边,检测负环)。
  • Floyd-Warshall 算法:多源最短路径(动态规划,O (n³))。
2. 最小生成树(MST)
  • Kruskal 算法:基于并查集,按边权排序(O (E log E))。
  • Prim 算法:基于优先队列,适合稠密图(O (E log V))。
3. 拓扑排序
  • 用于有向无环图(DAG),确定任务执行顺序。

    cpp

    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() == inDegree.size()) ? result : vector<int>(); // 检测是否有环
    }
    

五、动态规划(DP)

  • 核心思想:将复杂问题分解为重叠子问题,用表格存储中间结果避免重复计算。
  • 典型问题
    • 斐波那契数列

      cpp

      int fib(int n) {
          vector<int> dp(n + 1);
          dp[0] = 0; dp[1] = 1;
          for (int i = 2; i <= n; ++i) {
              dp[i] = dp[i - 1] + dp[i - 2];
          }
          return dp[n];
      }
      
    • 最长公共子序列(LCS)

      cpp

      int lcs(string& text1, string& text2) {
          int m = text1.size(), n = text2.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 (text1[i - 1] == text2[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];
      }
      
    • 背包问题:0-1 背包、完全背包等。

六、字符串算法

1. 字符串匹配
  • KMP 算法:利用部分匹配表(前缀函数)优化匹配,时间复杂度 O (n + m)。
  • Boyer-Moore 算法:从右向左匹配,适合文本搜索。
2. 字符串反转

cpp

void reverseString(string& s) {
    reverse(s.begin(), s.end()); // C++ 标准库函数
}
3. 最长回文子串
  • 动态规划法:

    cpp

    string longestPalindrome(string s) {
        int n = s.size();
        vector<vector<bool>> dp(n, vector<bool>(n, false));
        int start = 0, maxLen = 1;
        for (int i = 0; i < n; ++i) dp[i][i] = true; // 单个字符
        for (int i = n - 1; i >= 0; --i) {
            for (int j = i + 1; j < n; ++j) {
                if (s[i] == s[j]) {
                    if (j - i == 1 || dp[i + 1][j - 1]) {
                        dp[i][j] = true;
                        if (j - i + 1 > maxLen) {
                            maxLen = j - i + 1;
                            start = i;
                        }
                    }
                }
            }
        }
        return s.substr(start, maxLen);
    }
    

七、C++ 标准库算法

C++ 标准库(<algorithm>)提供了丰富的通用算法,可直接调用:

  • 排序sort(begin, end)(默认快速排序,可自定义比较函数)。
  • 查找find(begin, end, val)(线性查找)、binary_search(begin, end, val)(二分查找)。
  • 变换transform(begin, end, dest, func)(对元素应用函数)。
  • 统计count(begin, end, val)(统计元素出现次数)。
  • 合并 / 反转merge()reverse()swap() 等。

八、算法优化与进阶

  1. 贪心算法:每一步选局部最优解(如活动选择问题、哈夫曼编码)。
  2. 分治算法:分解问题为子问题(如归并排序、快速排序、大数乘法)。
  3. 回溯算法:深度优先搜索 + 剪枝(如全排列、子集生成、数独求解)。
  4. 随机化算法:快速选择(Randomized Quickselect)、拉斯维加斯算法等。
  5. 近似算法:用于 NP 难问题(如旅行商问题的近似解)。

学习资源推荐

  • 书籍
    • 《算法导论》(CLRS):经典算法理论教材。
    • 《C++ Primer》:深入理解 C++ 语言特性与标准库。
    • 《剑指 Offer》《LeetCode 题解》:通过实战掌握算法。
  • 在线平台

通过系统学习上述算法,并结合实际编程练习,可逐步提升在 C++ 中解决复杂问题的能力。

详细的介绍一下各类搜索算法

以下是对常见搜索算法的详细介绍,涵盖基础概念、分类、原理及典型应用场景:

一、搜索算法概述

定义:搜索算法是指在特定数据结构(如数组、树、图等)中查找目标元素或满足条件的解的方法。
核心目标:提高搜索效率(减少时间复杂度),降低空间消耗。
分类:根据搜索空间的特性,主要分为以下几类:

二、基础搜索算法

1. 线性搜索(顺序搜索)
  • 原理:从数据结构的起始位置开始,逐个元素与目标值比较,直到找到匹配项或遍历完所有元素。
  • 时间复杂度:平均 / 最坏情况为 O(n)(n 为数据规模)。
  • 适用场景
    • 数据量小或无序的数组 / 链表。
    • 不适合大规模数据或对效率要求高的场景。
  • 示例代码(C++)

    cpp

    int linearSearch(int arr[], int n, int target) {
        for (int i = 0; i < n; ++i) {
            if (arr[i] == target) return i;
        }
        return -1; // 未找到
    }
    
2. 二分搜索(折半搜索)
  • 原理:要求数据有序,每次将搜索区间缩小一半:
    1. 取中间元素与目标值比较;
    2. 若目标值较小,在左半区间继续搜索;若较大,在右半区间搜索;
    3. 重复直至找到目标或区间为空。
  • 时间复杂度:O(logn)(每次排除一半元素)。
  • 适用场景
    • 有序数组(不适用于链表,因无法快速定位中间元素)。
    • 常见变体:查找第一个 / 最后一个匹配元素、查找边界值等。
  • 示例代码(C++)

    cpp

    int binarySearch(int arr[], int n, int target) {
        int left = 0, right = n - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2; // 避免溢出
            if (arr[mid] == target) return mid;
            else if (arr[mid] < target) left = mid + 1;
            else right = mid - 1;
        }
        return -1;
    }
    

三、树结构相关搜索算法

1. 二叉树搜索(深度优先搜索 DFS 变种)
  • 原理:在二叉树中查找目标节点,分为以下三种遍历方式:
    • 前序遍历:根 → 左 → 右
    • 中序遍历:左 → 根 → 右(适用于二叉搜索树,遍历结果有序)
    • 后序遍历:左 → 右 → 根
  • 时间复杂度:O(n)(最坏情况下需遍历所有节点)。
  • 适用场景
    • 二叉树结构的搜索(如二叉搜索树、二叉堆等)。
    • 结合剪枝优化可用于回溯算法(如八皇后问题)。
2. 二叉搜索树(BST)搜索
  • 原理:利用二叉搜索树的特性(左子树节点值 < 根节点值 < 右子树节点值),递归或迭代地缩小搜索范围。
  • 时间复杂度:平均 O(logn),最坏 O(n)(退化为链表的 BST)。
  • 优化:平衡二叉树(如 AVL 树、红黑树)可保证最坏情况为 O(logn)。
3. 广度优先搜索(BFS)
  • 原理:从根节点开始,按层遍历所有节点(使用队列实现),适合找最短路径分层结构的问题。
  • 时间复杂度:O(n)(遍历所有节点)。
  • 适用场景
    • 树或图的最短路径问题(如无权图的单源最短路径)。
    • 查找分层结构中的目标节点(如按层级搜索二叉树)。

四、图论相关搜索算法

1. 深度优先搜索(DFS)
  • 原理:从起点开始,尽可能深入遍历图的节点,直到无法继续后回溯(使用栈或递归实现)。
  • 时间复杂度:邻接表存储为 O(V+E),邻接矩阵为 O(V2)(V 为顶点数,E 为边数)。
  • 适用场景
    • 查找图的连通分量、环检测。
    • 结合剪枝用于回溯算法(如迷宫路径搜索)。
2. 广度优先搜索(BFS)(图版本)
  • 原理:与树的 BFS 类似,从起点出发,逐层遍历所有相邻节点(使用队列避免重复访问)。
  • 时间复杂度:同 DFS。
  • 适用场景
    • 无权图的最短路径(如社交网络中的最近联系人)。
    • 拓扑排序的预处理(计算入度)。
3. Dijkstra 算法(单源最短路径)
  • 原理:适用于非负权图,从起点出发,逐步扩展最短路径已知的节点,使用优先队列(最小堆)选择当前最短路径的节点。
  • 时间复杂度
    • 朴素实现:O(V2)
    • 堆优化:O((V+E)logV)
  • 适用场景:导航系统中的最优路径规划、网络路由优化。
4. A * 算法(启发式搜索)
  • 原理:结合 BFS 的广度优先和 DFS 的启发式引导,通过启发式函数 f(n)=g(n)+h(n) 评估节点优先级(g(n) 为当前路径代价,h(n) 为估计到终点的代价)。
  • 关键条件:启发式函数 h(n) 需不高估实际代价(保证最优性)。
  • 时间复杂度:取决于启发式函数的有效性,理想情况下接近 O(解路径长度)。
  • 适用场景
    • 游戏地图寻路(如《星际争霸》路径规划)。
    • 机器人路径规划、网格地图搜索。

五、高级搜索算法

1. 双向搜索(Bidirectional Search)
  • 原理:同时从起点和终点出发进行 BFS,当两个搜索队列相遇时停止,可减少搜索空间。
  • 时间复杂度:理论上为 O(2n/2),比单向 BFS 的 O(2n) 更优。
  • 适用场景:状态空间较大的问题(如密码破解、棋类游戏)。
2. 分支限界法(Branch and Bound)
  • 原理:在遍历树或图的分支时,记录当前最优解,若某个分支的代价已超过当前最优解,则剪枝(丢弃该分支)。
  • 核心思想:通过剪枝缩小搜索范围,适用于最优化问题(如旅行商问题 TSP)。
  • 时间复杂度:取决于剪枝效率,最坏情况下仍为指数级。
3. 遗传算法(Genetic Algorithm)
  • 原理:模拟生物进化过程,通过选择、交叉、变异等操作生成候选解,逐步优化目标函数。
  • 特点:适用于复杂非线性问题,无需知道问题的具体数学结构。
  • 适用场景:全局优化问题(如函数极值求解、组合优化)。

六、搜索算法对比与选择

算法数据结构时间复杂度空间复杂度适用场景
线性搜索无序数组 / 链表O(n)O(1)小规模数据、无序结构
二分搜索有序数组O(logn)O(1)有序数组的快速查找
BFS树 / 图O(V+E)O(V)最短路径、分层搜索
DFS树 / 图O(V+E)O(V)连通性检测、回溯问题
Dijkstra非负权图O(ElogV)O(V)单源最短路径(非负权)
A*带权图启发式相关O(解空间)最优路径搜索(启发式引导)

七、总结

  • 基础搜索:线性搜索和二分搜索是其他算法的基石,需熟练掌握其适用条件。
  • 树与图搜索:BFS 和 DFS 是图论的核心算法,广泛用于路径搜索和遍历问题。
  • 高级搜索:A*、遗传算法等适用于复杂优化问题,需结合问题特性设计启发式或适应度函数。
  • 优化方向:通过数据结构优化(如优先队列、哈希表)或剪枝策略(如分支限界)提升搜索效率
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值