【蓝桥杯】C语言常见高级算法

🌸个人主页:Yang-ai-cao
📕系列专栏:蓝桥杯    C语言
   🍍博学而日参省乎己,知明而行无过矣

目录

🌸个人主页:Yang-ai-cao

📕系列专栏:蓝桥杯    C语言

🍍博学而日参省乎己,知明而行无过矣

一、动态规划(Dynamic Programming)

例子:斐波那契数列

动态规划解法

例子:0-1 背包问题

动态规划解法

二、贪心算法(Greedy Algorithm)

例子:活动选择问题

贪心算法解法

三、回溯算法(Backtracking)

例子:N皇后问题

回溯算法解法

四、分治算法(Divide and Conquer)

例子:归并排序(Merge Sort)

五、图算法(Graph Algorithms)

例子:Dijkstra 算法(单源最短路径)

贪心算法(Greedy Algorithm)

例子:霍夫曼编码(Huffman Coding)

总结


一、动态规划(Dynamic Programming)

例子:斐波那契数列

动态规划解法
#include <stdio.h>// 计算斐波那契数列的第 n 项
int fib(int n) {// 创建一个数组来存储斐波那契数列int f[n+1];f[0] = 0;  // 第 0 项是 0f[1] = 1;  // 第 1 项是 1// 通过迭代计算第 n 项for (int i = 2; i <= n; i++) {f[i] = f[i-1] + f[i-2];  // 当前项等于前两项之和}return f[n];  // 返回第 n 项
}int main() {int n = 10;  // 计算第 10 项printf("Fibonacci number is %d\n", fib(n));  // 输出结果return 0;
}

例子:0-1 背包问题

动态规划解法
#include <stdio.h>// 返回两个整数中的最大值
int max(int a, int b) { return (a > b) ? a : b; }// 解决 0-1 背包问题
int knapSack(int W, int wt[], int val[], int n) {// 创建一个二维数组 K,用于存储子问题的解int K[n+1][W+1];// 填充 K 表for (int i = 0; i <= n; i++) {for (int w = 0; w <= W; w++) {if (i == 0 || w == 0) {K[i][w] = 0;  // 基本情况:没有物品或容量为 0} else if (wt[i-1] <= w) {// 选择当前物品或不选择当前物品,取最大值K[i][w] = max(val[i-1] + K[i-1][w-wt[i-1]], K[i-1][w]);} else {K[i][w] = K[i-1][w];  // 当前物品不能放入背包}}}return K[n][W];  // 返回最大价值
}int main() {int val[] = {60, 100, 120};  // 物品的价值int wt[] = {10, 20, 30};     // 物品的重量int W = 50;                  // 背包的容量int n = sizeof(val)/sizeof(val[0]);  // 物品的数量printf("Maximum value in Knapsack = %d\n", knapSack(W, wt, val, n));  // 输出结果return 0;
}

二、贪心算法(Greedy Algorithm)

例子:活动选择问题

贪心算法解法
#include <stdio.h>// 打印最大数量的可选活动
void printMaxActivities(int s[], int f[], int n) {int i = 0;  // 第一个活动总是被选择printf("Selected activities: %d ", i);// 选择其余活动for (int j = 1; j < n; j++) {if (s[j] >= f[i]) {  // 如果当前活动的开始时间大于等于上一个活动的结束时间printf("%d ", j);i = j;  // 更新上一个被选择活动的索引}}printf("\n");
}int main() {int s[] = {1, 3, 0, 5, 8, 5};  // 活动的开始时间int f[] = {2, 4, 6, 7, 9, 9};  // 活动的结束时间int n = sizeof(s)/sizeof(s[0]);  // 活动的数量printMaxActivities(s, f, n);  // 输出结果return 0;
}

三、回溯算法(Backtracking)

例子:N皇后问题

回溯算法解法
#include <stdio.h>
#include <stdbool.h>#define N 4  // 棋盘大小// 打印棋盘
void printSolution(int board[N][N]) {for (int i = 0; i < N; i++) {for (int j = 0; j < N; j++) {printf(" %d ", board[i][j]);}printf("\n");}
}// 检查在 board[row][col] 放置皇后是否安全
bool isSafe(int board[N][N], int row, int col) {int i, j;// 检查当前行的左侧for (i = 0; i < col; i++)if (board[row][i])return false;// 检查左上对角线for (i = row, j = col; i >= 0 && j >= 0; i--, j--)if (board[i][j])return false;// 检查左下对角线for (i = row, j = col; j >= 0 && i < N; i++, j--)if (board[i][j])return false;return true;
}// 递归解决 N 皇后问题
bool solveNQUtil(int board[N][N], int col) {if (col >= N)  // 所有皇后已放置return true;for (int i = 0; i < N; i++) {if (isSafe(board, i, col)) {  // 检查放置在 board[i][col] 是否安全board[i][col] = 1;  // 放置皇后if (solveNQUtil(board, col + 1))  // 递归放置其余皇后return true;board[i][col] = 0;  // 回溯:移除皇后}}return false;  // 如果无法放置皇后
}// 解决 N 皇后问题
bool solveNQ() {int board[N][N] = { {0, 0, 0, 0},{0, 0, 0, 0},{0, 0, 0, 0},{0, 0, 0, 0} };if (solveNQUtil(board, 0) == false) {printf("Solution does not exist");return false;}printSolution(board);  // 打印解决方案return true;
}int main() {solveNQ();  // 解决问题return 0;
}

四、分治算法(Divide and Conquer)

例子:归并排序(Merge Sort)

#include <stdio.h>// 合并两个子数组
void merge(int arr[], int l, int m, int r) {int n1 = m - l + 1; // 左子数组的大小int n2 = r - m; // 右子数组的大小int L[n1], R[n2]; // 临时数组// 复制数据到临时数组 L[] 和 R[]for (int i = 0; i < n1; i++)L[i] = arr[l + i];for (int j = 0; j < n2; j++)R[j] = arr[m + 1 + j];// 合并临时数组到 arr[l..r]int i = 0, j = 0, k = l;while (i < n1 && j < n2) {if (L[i] <= R[j]) {arr[k] = L[i];i++;} else {arr[k] = R[j];j++;}k++;}// 复制 L[] 剩余元素while (i < n1) {arr[k] = L[i];i++;k++;}// 复制 R[] 剩余元素while (j < n2) {arr[k] = R[j];j++;k++;}
}// 归并排序
void mergeSort(int arr[], int l, int r) {if (l < r) {int m = l + (r - l) / 2; // 找到中点mergeSort(arr, l, m); // 排序左半部分mergeSort(arr, m + 1, r); // 排序右半部分merge(arr, l, m, r); // 合并已排序的部分}
}// 打印数组
void printArray(int A[], int size) {for (int i = 0; i < size; i++)printf("%d ", A[i]);printf("\n");
}int main() {int arr[] = {12, 11, 13, 5, 6, 7};int arr_size = sizeof(arr) / sizeof(arr[0]);printf("Given array is \n");printArray(arr, arr_size);mergeSort(arr, 0, arr_size - 1);printf("\nSorted array is \n");printArray(arr, arr_size);return 0;
}

五、图算法(Graph Algorithms)

例子:Dijkstra 算法(单源最短路径)

#include <stdio.h>
#include <limits.h>
#include <stdbool.h>#define V 9 // 顶点数量// 找到最小距离的顶点
int minDistance(int dist[], bool sptSet[]) {int min = INT_MAX, min_index;for (int v = 0; v < V; v++)if (sptSet[v] == false && dist[v] <= min)min = dist[v], min_index = v;return min_index;
}// 打印解
void printSolution(int dist[], int n) {printf("Vertex \t Distance from Source\n");for (int i = 0; i < V; i++)printf("%d \t\t %d\n", i, dist[i]);
}// Dijkstra 算法
void dijkstra(int graph[V][V], int src) {int dist[V]; // 最短距离数组bool sptSet[V]; // sptSet[i] 为 true 表示顶点 i 已包含在最短路径树中// 初始化所有距离为无穷大,sptSet[] 为 falsefor (int i = 0; i < V; i++)dist[i] = INT_MAX, sptSet[i] = false;dist[src] = 0; // 源顶点距离为 0for (int count = 0; count < V - 1; count++) {int u = minDistance(dist, sptSet); // 选取最小距离顶点sptSet[u] = true; // 标记为已处理for (int v = 0; v < V; v++)if (!sptSet[v] && graph[u][v] && dist[u] != INT_MAX && dist[u] + graph[u][v] < dist[v])dist[v] = dist[u] + graph[u][v]; // 更新距离}printSolution(dist, V); // 打印结果
}int main() {int graph[V][V] = { {0, 4, 0, 0, 0, 0, 0, 8, 0},{4, 0, 8, 0, 0, 0, 0, 11, 0},{0, 8, 0, 7, 0, 4, 0, 0, 2},{0, 0, 7, 0, 9, 14, 0, 0, 0},{0, 0, 0, 9, 0, 10, 0, 0, 0},{0, 0, 4, 14, 10, 0, 2, 0, 0},{0, 0, 0, 0, 0, 2, 0, 1, 6},{8, 11, 0, 0, 0, 0, 1, 0, 7},{0, 0, 2, 0, 0, 0, 6, 7, 0} };dijkstra(graph, 0); // 调用 Dijkstra 算法return 0;
}

贪心算法(Greedy Algorithm)

例子:霍夫曼编码(Huffman Coding)

#include <stdio.h>
#include <stdlib.h>#define MAX_TREE_HT 100// 最小堆节点
struct MinHeapNode {char data; // 字符unsigned freq; // 频率struct MinHeapNode *left, *right; // 左右子节点
};// 最小堆
struct MinHeap {unsigned size; // 当前大小unsigned capacity; // 容量struct MinHeapNode **array; // 数组指针
};// 创建新节点
struct MinHeapNode* newNode(char data, unsigned freq) {struct MinHeapNode* temp = (struct MinHeapNode*)malloc(sizeof(struct MinHeapNode));temp->left = temp->right = NULL;temp->data = data;temp->freq = freq;return temp;
}// 创建最小堆
struct MinHeap* createMinHeap(unsigned capacity) {struct MinHeap* minHeap = (struct MinHeap*)malloc(sizeof(struct MinHeap));minHeap->size = 0;minHeap->capacity = capacity;minHeap->array = (struct MinHeapNode**)malloc(minHeap->capacity * sizeof(struct MinHeapNode*));return minHeap;
}// 交换两个最小堆节点
void swapMinHeapNode(struct MinHeapNode** a, struct MinHeapNode** b) {struct MinHeapNode* t = *a;*a = *b;*b = t;
}// 最小堆化
void minHeapify(struct MinHeap* minHeap, int idx) {int smallest = idx;int left = 2 * idx + 1;int right = 2 * idx + 2;if (left < minHeap->size && minHeap->array[left]->freq < minHeap->array[smallest]->freq)smallest = left;if (right < minHeap->size && minHeap->array[right]->freq < minHeap->array[smallest]->freq)smallest = right;if (smallest != idx) {swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[idx]);minHeapify(minHeap, smallest);}
}// 检查是否只有一个元素
int isSizeOne(struct MinHeap* minHeap) {return (minHeap->size == 1);
}// 提取最小值节点
struct MinHeapNode* extractMin(struct MinHeap* minHeap) {struct MinHeapNode* temp = minHeap->array[0];minHeap->array[0] = minHeap->array[minHeap->size - 1];--minHeap->size;minHeapify(minHeap, 0);return temp;
}// 插入节点到最小堆
void insertMinHeap(struct MinHeap* minHeap, struct MinHeapNode* minHeapNode) {++minHeap->size;int i = minHeap->size - 1;while (i && minHeapNode->freq < minHeap->array[(i - 1) / 2]->freq) {minHeap->array[i] = minHeap->array[(i - 1) / 2];i = (i - 1) / 2;}minHeap->array[i] = minHeapNode;
}// 构建最小堆
void buildMinHeap(struct MinHeap* minHeap) {int n = minHeap->size - 1;for (int i = (n - 1) / 2; i >= 0; --i)minHeapify(minHeap, i);
}// 打印数组
void printArr(int arr[], int n) {for (int i = 0; i < n; ++i)printf("%d", arr[i]);printf("\n");
}// 检查是否是叶子节点
int isLeaf(struct MinHeapNode* root) {return !(root->left) && !(root->right);
}// 创建并构建最小堆
struct MinHeap* createAndBuildMinHeap(char data[], int freq[], int size) {struct MinHeap* minHeap = createMinHeap(size);for (int i = 0; i < size; ++i)minHeap->array[i] = newNode(data[i], freq[i]);minHeap->size = size;buildMinHeap(minHeap);return minHeap;
}// 构建霍夫曼树
struct MinHeapNode* buildHuffmanTree(char data[], int freq[], int size) {struct MinHeapNode *left, *right, *top;struct MinHeap* minHeap = createAndBuildMinHeap(data, freq, size);while (!isSizeOne(minHeap)) {left = extractMin(minHeap);right = extractMin(minHeap);top = newNode('$', left->freq + right->freq);top->left = left;top->right = right;insertMinHeap(minHeap, top);}return extractMin(minHeap);
}// 打印霍夫曼编码
void printCodes(struct MinHeapNode* root, int arr[], int top) {if (root->left) {arr[top] = 0;printCodes(root->left, arr, top + 1);}if (root->right) {arr[top] = 1;printCodes(root->right, arr, top + 1);}if (isLeaf(root)) {printf("%c: ", root->data);printArr(arr, top);}
}// 霍夫曼编码
void HuffmanCodes(char data[], int freq[], int size) {struct MinHeapNode* root = buildHuffmanTree(data, freq, size);int arr[MAX_TREE_HT], top = 0;printCodes(root, arr, top);
}int main() {char arr[] = {'a', 'b', 'c', 'd', 'e', 'f'};int freq[] = {5, 9, 12, 13, 16, 45};int size = sizeof(arr) / sizeof(arr[0]);HuffmanCodes(arr, freq, size); // 调用霍夫曼编码return 0;
}

总结

  • 分治算法通过递归地将问题分解为子问题,解决这些子问题然后合并其解,适用于排序、搜索等问题。
  • 图算法如Dijkstra算法,通过逐步扩展最短路径树,找到图中从单个源到所有其他顶点的最短路径。
  • 贪心算法如霍夫曼编码,通过每一步选择局部最优解,最终构建出全局最优解,适用于数据压缩等问题。
  • 贪心算法每一步都选择当前最优的选择,适用于能够通过局部最优达到全局最优的问题。
  • 回溯算法系统地搜索所有可能的解,通过尝试构建解并在不满足条件时回溯,适用于需要探索所有可能解的问题。
  • 动态规划通过存储子问题的解来避免重复计算,适用于有重叠子问题和最优子结构的问题。

     

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/26459.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【学习笔记】Kali

纯个人总结&#xff0c;有什么不对的地方欢迎指正。 笔记根据个人学习进度持续更新… 一、 认识Kali 基础了解 Kali是一套基于Debian发行版的一款操作系统。&#xff08;这里讲一个误区&#xff0c;我以前一直以为kali就属于deepin下的操作系统&#xff0c;但是我知道deepin是…

【DPDK学习路径】四、输出hello world!

在 ./examples/ 目录下可以找到许多的示例程序&#xff0c;将其中的 l3fwd-vf/Makefile 拷贝到自己的工作目录下&#xff0c;新建一个 main.c 文件&#xff0c;编写其内容如下&#xff1a; #include<stdio.h>int main() {printf("hello world!\n");return 0; …

HTML静态网页成品作业(HTML+CSS+JS)—— 美食企业曹氏鸭脖介绍网页(4个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;使用Javacsript代码实现 图片轮播切换&#xff0c;共有4个页面。 二、…

css3新增的伪类有哪些

CSS3 引入了许多新的伪类选择器&#xff0c;这些选择器为开发者提供了更多的样式控制选项。以下是一些 CSS3 中新增的主要伪类选择器&#xff1a; 结构性伪类&#xff1a; :root&#xff1a;选择文档的根元素&#xff08;通常是 <html>&#xff09;。:empty&#xff1a;…

使用pyqt对yolov5进行简答部署

YOLOv5是一种高效的实时目标检测算法&#xff0c;广泛应用于各类计算机视觉任务中。为了实现便捷的图形用户界面&#xff08;GUI&#xff09;&#xff0c;我们采用了PyQt框架。PyQt是一个Python绑定的Qt库&#xff0c;用于创建跨平台的应用程序。 在本研究中&#xff0c;我们首…

「React」RSC 服务端组件

前言 RSC&#xff08;React Server Components&#xff09;是React框架的一个新特性&#xff0c;它允许开发者编写只在服务器端渲染的组件。与传统的服务器端渲染&#xff08;SSR&#xff09;不同&#xff0c;RSC的目标是提升性能和用户体验&#xff0c;同时减少客户端加载的J…

【每日一练】day3

✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天开心哦&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; &#x1f388;丠丠64-CSDN博客&#x1f388; ✨✨ 帅哥美女们&#xff0c;我们共同加油&#xff01;一起…

OLED柔性屏的显示效果如何

OLED柔性屏的显示效果非常出色&#xff0c;具有多方面的优势。以下是关于OLED柔性屏显示效果的详细分析&#xff1a; 色彩表现&#xff1a;OLED柔性屏的每个像素都可以独立发光&#xff0c;因此色彩准确性极高。黑色呈现得非常深邃&#xff0c;而亮部则展现出鲜明而生动的细节。…

vue3+electron搭建桌面软件

vue3electron开发桌面软件 最近有个小项目, 客户希望像打开 网易云音乐 那么简单的运行起来系统. 前端用 Vue 会比较快一些, 因此决定使用 electron 结合 Vue3 的方式来完成该项目. 然而, 在实施过程中发现没有完整的博客能够记录从创建到打包的流程, 摸索一番之后, 随即梳理…

事件、方法实现 on_radioGreen_clicked ,on_chkBoxUnder_clicked,Qfont,QPalette

Vertical Layout 、Horizontal Layout 实验窗体自适应布局 接上篇界面布局&#xff0c; 实验checkBox、radioBox 的事件槽&#xff0c; 使用Qfont组件变更纯文本框QPlainTextEdit中字体的下划线、加粗、斜体效果 使用调色板组QPalette变更纯文本框QPlainTextEdit中文本颜色 UI…

VsCode中C文件调用其他C文件函数失败

之前一直使用CodeBlocks&#xff0c;最近使用vscode多&#xff0c;感觉它比较方便&#xff0c;但在调用其他C文件的时候发现报错以下内容基于单C文件运行成功&#xff0c;否则请移步 博文&#xff1a;VSCode上搭建C/C开发环境 报错信息 没有使用CodeRunner插件&#xff0c;弹…

❤追本溯源篇-林太白

❤追本溯源篇-林太白 总结当前博客下所有的技术和相关文章 (点赞收藏不断更新) 工具使用 ❤ Chrome浏览器使用 设置Chrome浏览器 http://t.csdnimg.cn/P68jK

DDei在线设计器-配置主题风格

DDeiCore-主题 DDei-Core插件提供了默认主题和黑色主题。 如需了解详细的API教程以及参数说明&#xff0c;请参考DDei文档 默认主题 黑色主题 使用指南 引入 import { DDeiCoreThemeBlack } from "ddei-editor";使用并修改设置 extensions: [......//通过配置&am…

Java对指定不规则的jsonString读取并操作

当我们在做项目的时候有时候会对接第三方的接口&#xff0c;假如对方返回的结果是一个不规则的json字符串&#xff0c;这个时候我们就需要对于返回结果一条一条的进行读取并操作&#xff1a; 一、json例子&#xff1a;不是数组&#xff0c;单纯的只是一行一行的数据 {"n…

Web前端右侧悬浮:实现技巧与深度解析

Web前端右侧悬浮&#xff1a;实现技巧与深度解析 在Web前端开发中&#xff0c;右侧悬浮功能作为一种常见的交互设计元素&#xff0c;能够为用户提供便捷的操作入口&#xff0c;提升用户体验。然而&#xff0c;实现这一功能却并非易事&#xff0c;需要开发者掌握一定的技巧和方…

机器学习在医学领域中的应用|文献精析·24-06-13

小罗碎碎念 2024-06-13&#xff5c;文献精析&#xff1a;机器学习在医学领域中的应用 为了系统性地和大家梳理一下机器学习在医学领域中的应用&#xff0c;我特意去找了一篇文献&#xff0c;把其中有价值的信息筛选出来了。但是我没选的内容不代表不重要&#xff0c;感兴趣的可…

一文讲清:bom管理系统是什么?在生产管理中有什么作用?

在制造业中&#xff0c;物料清单&#xff08;Bill of Materials&#xff0c;简称BOM&#xff09;扮演着至关重要的角色。物料清单&#xff08;BOM&#xff09;是制造或维修产品所需的材料、组件和零件的结构化综合列表&#xff0c;以及所需材料的数量、名称、描述和成本。简而言…

解释 RESTful API, 如何使用它构建 web 应用程序

RESTful API&#xff08;Representational State Transfer&#xff09;是一种设计风格和架构原则&#xff0c;用于构建可扩展和可维护的网络应用程序。它基于 HTTP 协议&#xff0c;并使用标准的 HTTP 方法&#xff08;GET、POST、PUT、DELETE&#xff09;来执行对资源的操作。…

Web前端项目实例描述:构建交互式在线书店

Web前端项目实例描述&#xff1a;构建交互式在线书店 在数字化时代&#xff0c;Web前端技术发挥着至关重要的作用&#xff0c;它为用户提供了直观、友好的界面体验。本次&#xff0c;我将为大家详细描述一个Web前端项目实例——构建交互式在线书店。该项目涵盖了多个关键方面&…

ssm学生成绩管理系统-海豚

ssm学生成绩管理系统-海豚 ssm学生成绩管理系统。 功能:登录&#xff0c;学生信息管理&#xff0c;课程信息&#xff0c;成绩信息&#xff0c; 技术&#xff1a;java&#xff0c;ssm&#xff0c;mybatics&#xff0c;jsp 平台&#xff1a;eclispe或者idea&#xff0c;mysql5.7…