算法导论----学习笔记08
2014-11-29 10:59
281 查看
按照查找的引出的先后顺序介绍:
思想:先确定待查记录所在的范围(区间),然后逐步缩小范围找到或找不到该记录为止。如果mid对应值大于key,high = 密度-1;如果mid对应值小于key,low
= mid + 1;否则找到结果。
性能分析:对于任意的n,当较大(n>50)时,假设表中每个记录的查找概率相等(1/n),则查找成功时折半查找的近似平均查找长度为=
log2(n+1)-1。
其中:
假设开始时数组A中记录个数比某个斐波那契数小1,即n=Fu-1,然后将给定值key和查找序列中A[Fu-1]进行比较,
若相等,则查找成功
若key > A[Fu-1],则在A[Fu-1+1]至A[Fu-1]区间的数组中进行查找;
若key < A[Fu-1],则继续在A[0]至A[Fu-1-1]区间的数组中进行查找;
性能分析:斐波那契查找的平均性能比折半查找好,但最坏情况下的性能 (虽然仍为O(lgn)) 却比折半查找差。
小小优点:分割时只需进行加、减运算。
其中,A[l]和A[h]分别为有序表中具有最小关键字和最大关键字的下标
性能比较:它只适合于关键字均匀分布的数组,在这种情况下,对数组较长的数组来说,其平均性能比折半查找好。
由于上面讨论的查找都是等概率的查找,如果待查找数为非等概率出现,那么上述的方法并非是使平均查找长度最短
-----------------------------------------------------------------------------------------------我是分割线----------------------------------------
最优二叉树(哈夫曼树)
思路:使用动态规划思想
[b]二、最优二叉查找树的最优子结构[/b]
最终的递归公式为:
[b]对于1≤i≤n.
且j≥i,
我们有:[/b]
w(i,j)=w(i,j−1)+pj+qj
三、代码实现(C++):
1. 静态查找(树)表
以下介绍的是有序表查找,无序表只能顺序查找二分查找
作为有序表查找的一种非常普通且实用的方法。大家并不陌生。思想:先确定待查记录所在的范围(区间),然后逐步缩小范围找到或找不到该记录为止。如果mid对应值大于key,high = 密度-1;如果mid对应值小于key,low
= mid + 1;否则找到结果。
性能分析:对于任意的n,当较大(n>50)时,假设表中每个记录的查找概率相等(1/n),则查找成功时折半查找的近似平均查找长度为=
log2(n+1)-1。
斐波那契查找
原理:根据斐波那契序列的特点对表进行分割。其中:
假设开始时数组A中记录个数比某个斐波那契数小1,即n=Fu-1,然后将给定值key和查找序列中A[Fu-1]进行比较,
若相等,则查找成功
若key > A[Fu-1],则在A[Fu-1+1]至A[Fu-1]区间的数组中进行查找;
若key < A[Fu-1],则继续在A[0]至A[Fu-1-1]区间的数组中进行查找;
性能分析:斐波那契查找的平均性能比折半查找好,但最坏情况下的性能 (虽然仍为O(lgn)) 却比折半查找差。
小小优点:分割时只需进行加、减运算。
插值查找
原理:是根据给定值key来确定进行比较关键字A[i]的查找方法。其中,A[l]和A[h]分别为有序表中具有最小关键字和最大关键字的下标
性能比较:它只适合于关键字均匀分布的数组,在这种情况下,对数组较长的数组来说,其平均性能比折半查找好。
由于上面讨论的查找都是等概率的查找,如果待查找数为非等概率出现,那么上述的方法并非是使平均查找长度最短
-----------------------------------------------------------------------------------------------我是分割线----------------------------------------
最优二叉树(哈夫曼树)
思路:使用动态规划思想
[b]二、最优二叉查找树的最优子结构[/b]
最终的递归公式为:
[b]对于1≤i≤n.
且j≥i,
我们有:[/b]
w(i,j)=w(i,j−1)+pj+qj
伪码:
<span style="color:#000000;"></span><pre name="code" class="cpp">OPTIMAL-BST(p, q, n) let e[1 .. n + 1, 0 .. n], w[1, n + 1, 0 .. n], and root[1..n, 1..n] be new tables for i = 1 to n + 1 e[i, i - 1] = q<sub>i-1</sub> w[i, i - 1] = q<sub>i-1</sub> for l = 1 to n for i = 1 to n - l + 1 j = i + l - 1 e[i, j] = ∞ w[i, j] = w[i, j -1] + p<sub>j</sub> + q<sup>j</sup> for r = i to j t = e[i, r - 1] + e[r + 1, j] + w[i, j] if t < e[i, j] e[i, j] = t root[i, j] = r return e and root
三、代码实现(C++):
//最优二叉查找树 #include <iostream> using namespace std; const int MaxVal = 9999; const int n = 5; //搜索到根节点和虚拟键的概率 double p[n + 1] = {-1,0.15,0.1,0.05,0.1,0.2}; double q[n + 1] = {0.05,0.1,0.05,0.05,0.05,0.1}; int root[n + 1][n + 1];//记录根节点 double w[n + 2][n + 2];//子树概率总和 double e[n + 2][n + 2];//子树期望代价 void optimalBST(double *p,double *q,int n) { //初始化只包括虚拟键的子树 for (int i = 1;i <= n + 1;++i) { w[i][i - 1] = q[i - 1]; e[i][i - 1] = q[i - 1]; } //由下到上,由左到右逐步计算 for (int len = 1;len <= n;++len) { for (int i = 1;i <= n - len + 1;++i) { int j = i + len - 1; e[i][j] = MaxVal; w[i][j] = w[i][j - 1] + p[j] + q[j]; //求取最小代价的子树的根 for (int k = i;k <= j;++k) { double temp = e[i][k - 1] + e[k + 1][j] + w[i][j]; if (temp < e[i][j]) { e[i][j] = temp; root[i][j] = k; } } } } } //输出最优二叉查找树所有子树的根 void printRoot() { cout << "各子树的根:" << endl; for (int i = 1;i <= n;++i) { for (int j = 1;j <= n;++j) { cout << root[i][j] << " "; } cout << endl; } cout << endl; } //打印最优二叉查找树的结构 //打印出[i,j]子树,它是根r的左子树和右子树 void printOptimalBST(int i,int j,int r) { int rootChild = root[i][j];//子树根节点 if (rootChild == root[1] ) { //输出整棵树的根 cout << "k" << rootChild << "是根" << endl; printOptimalBST(i,rootChild - 1,rootChild); printOptimalBST(rootChild + 1,j,rootChild); return; } if (j < i - 1) { return; } else if (j == i - 1)//遇到虚拟键 { if (j < r) { cout << "d" << j << "是" << "k" << r << "的左孩子" << endl; } else cout << "d" << j << "是" << "k" << r << "的右孩子" << endl; return; } else//遇到内部结点 { if (rootChild < r) { cout << "k" << rootChild << "是" << "k" << r << "的左孩子" << endl; } else cout << "k" << rootChild << "是" << "k" << r << "的右孩子" << endl; } printOptimalBST(i,rootChild - 1,rootChild); printOptimalBST(rootChild + 1,j,rootChild); } int main() { optimalBST(p,q,n); printRoot(); cout << "最优二叉树结构:" << endl; printOptimalBST(1,n,-1); }
相关文章推荐
- 算法导论学习笔记-第2章 算法入门
- 算法导论学习笔记-第十六章-贪心算法
- 算法导论学习笔记(8)——动态规划之矩阵链乘法
- 算法导论学习笔记(六):计数排序与基数排序
- 算法导论学习笔记(15)——用于不相交集合的数据结构
- 算法导论学习笔记-第十一章-散列表
- 算法导论学习笔记——基数排序
- Introduction to Algorithms 算法导论 第2章 算法入门 学习笔记及习题解答
- 算法导论学习笔记(16)——图的基本算法
- Introduction to Algorithms 算法导论 第4章 递归式 学习笔记及习题解答
- 算法导论学习笔记-第十四章-数据结构的扩张
- 算法导论--第六章学习笔记
- 算法学习导论学习笔记-第6章 堆排序
- 算法导论 学习笔记。
- Introduction to Algorithms 算法导论 第3章 函数的增长 学习笔记及习题解答
- 算法导论学习笔记-第五章-概率分析和随机算法
- 算法导论学习笔记-1
- 算法导论学习笔记---第三章
- 韩顺平_PHP程序员玩转算法公开课(第一季)08_阶段性就业指导_学习笔记_源代码图解_PPT文档整理
- 算法导论学习笔记(11)——贪心算法之哈夫曼树