算法设计与分析
Posted 一宿君
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法设计与分析相关的知识,希望对你有一定的参考价值。
一、概念和问答
1、算法,时间复杂性(时间复杂度),贪心法,分治法,搜索法,递归,算法分析。
- 算法:
对问题求解步骤的准确而完整的描述,是一些列有穷规则指令集合。
- 时间复杂度:
在算法运行期间所花费的时间
- 贪心法:
是一种在每一步选择中都采取当前状态下最有利的选择,从而希望结果是最有利的算法。
- 分治法(设计思想-分而治之):
将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同,然后递归求解子问题,最后子问题的解合并得到原问题的解。
- 搜索法:
利用计算机的高性能来有目的的穷举一个问题的部分或所有的可能结果,从而求出
问题的解的算法。 - 递归:
直接或间接调用自身的算法。
- 算法分析:
指对计算机算法的时间和空间复杂度进行定量的分析。
2、要会画递归调用时调用栈里的主要内容(局部变量、形式参数)。
- 每一次递归调用都会在栈中开辟新的一层:每一层包含一个地址(调用完后需返回到上一层执行的地址),这一层传来的形参和局部变量。
- 函数中的形式参数先进栈,然后局部变量进栈,当本次递归调用结束后,局部变量先出栈,形式参数再出栈。
3、对于哈夫曼树,哈夫曼编码,解码,自己要能够通过例子说明原理,比如能够画出哈夫曼树,能够根据哈夫曼树写出哈夫曼编码。
-
哈夫曼树:
1.权值分别为W1、W2…Wn的n个结点,构成只有根结点的n个二叉树,组成森林即n个数 的权值保存在数组W[ ]中
2.用selectMin( )方法:在森林中选出两个根结点权值最小的树,合并作为一棵新树的左右 子树且新树的根结点权值为其左右结点权值之和
3.从森林中删除刚才选取的两棵树,并将新树加入森林
4.重复2、3步骤,直到森林只剩一棵树为止,该树为哈夫曼树。 -
哈夫曼编码:
规定哈夫曼树的左分支代表0,右分支代表1,则从根结点到叶子结点所经过的
路径分支组成的0和1的序列为改结点对应字符的编码,即哈夫曼编码。 -
解码:
哈夫曼编码中若得到如a :01 b :101对应关系,通过这个关系直接将像“asdsdfdfg”直接
转换为“01110101”这样二进制编码。译码的时候,读取二进制编码,先读取一位,然后在关
系表中查找该二进制数对应的字符,如果没有找到,继续读取二位,然后继续在关系表中查
找该二位二进制对应的字符。如此循环,知道找到字符位置,然后将二进制数替换为相应的
字符,知道所有的数都替换完为止。
4、常见的最小生成树的构造方法有哪两种?要能够说明他们的算法思想。
- 常见的两种最小生成树的构造方法
Kruskal算法和Prim算法。
- Kruskal算法思想:
就是先把所有边取出来,然后按从小到大排序,每次取出一条边,
判断是否形成回路,如果是就丢弃,否则这条边就是我们想要的权值最小的边。 - Prim算法思想:
从一定点出发,找出此点邻接边中最短的边加入对应顶点,再次寻找这
两条边的最短邻接边,依次类推,加入所有没有被访问过的边。
二、重要算法
- 冒泡排序
#include "iostream" using namespace std; int main() { int nums[] = {6,1,5,9,2,5,7,0,4}; int length = sizeof(nums) / sizeof(int); for(int i = 0; i < length - 1; i++){ for(int j = 0; j < length - i - 1; j++){ if(nums[j] > nums[j + 1]){ int temp = nums[j]; nums[j] = nums[j + 1]; nums[j + 1] = temp; } } } for(int i = 0; i < length; i++) { printf("%d,",nums[i]); } }
- 折半查找
#include "iostream" int main(){ int nums[] = {0, 9, 11, 22, 23, 27, 42, 53, 65, 71, 91}; int length = sizeof(nums) / sizeof(int); int left = 0; int right = length - 1; int middle; int find = 27; while (left <= right) { middle = left + (right - left) / 2; if (find >= nums[middle]) { left = middle + 1; } else { right = middle - 1; } } printf("要查找的数:%d\\n",nums[right]); }
- 快速排序
#include "iostream" using namespace std; void quickSort(int a[], int l, int r) { if (l < r) { int i,j,x; i = l; j = r; x = a[i]; while (i < j) { while(i < j && a[j] > x) j--; // 从右向左找第一个小于x的数 if(i < j) a[i++] = a[j]; while(i < j && a[i] < x) i++; // 从左向右找第一个大于x的数 if(i < j) a[j--] = a[i]; } a[i] = x; quickSort(a, l, i-1); /* 递归调用 */ quickSort(a, i+1, r); /* 递归调用 */ } } int main() { int nums[] = {65, 11, 53, 9, 22, 27, 71, 0, 42, 91, 23}; int length = sizeof(nums) / sizeof(int); quickSort(nums, 0, length - 1); for(int i = 0; i < length; i++) { printf("%d,", nums[i]); } }
- 图的广度优先搜索算法
#include "iostream" #include "malloc.h" #include "Stack" #include "Queue" using namespace std; #define Element char typedef struct Node{ Element data; struct Node *lchild; struct Node *rchild; }*Tree; int index = 0; void treeNodeConstructor(Tree &root, Element data[]){ Element e = data[index++]; if(e == '#'){ root = NULL; }else{ root = (Node *)malloc(sizeof(Node)); root->data = e; treeNodeConstructor(root->lchild, data); //递归构建左子树 treeNodeConstructor(root->rchild, data); //递归构建右子树 } } //广度优先遍历 void breadthFirstSearch(Tree root){ queue<Node *> nodeQueue; //使用C++的STL标准模板库 nodeQueue.push(root); Node *node; while(!nodeQueue.empty()){ node = nodeQueue.front(); nodeQueue.pop(); printf("%c", node->data); if(node->lchild){ nodeQueue.push(node->lchild); //先将左子树入队 } if(node->rchild){ nodeQueue.push(node->rchild); //再将右子树入队 } } } int main(){ // 其中用'#'表示结点无左子树或无右子树 Element data[15] = {'A', 'B', 'D', '#', '#', 'E', '#', '#', 'C', 'F','#', '#', 'G', '#', '#'}; Tree tree; treeNodeConstructor(tree, data); printf("\\n\\n广度优先遍历二叉树结果: "); breadthFirstSearch(tree); return 0; }
- 三个二叉树遍历算法
以上是关于算法设计与分析的主要内容,如果未能解决你的问题,请参考以下文章