随笔分类 - 算法
摘要:基本思想:将待求解问题分解成若干子问题,先求解子问题,然后从子问题的解中得到原问题的解。与分治不同的是,经分解得到的子问题往往不是互相独立的。若用分治法来解这些问题,则得到的子问题数目太多,以至于最后解决原问题需要消耗指数时间。步骤设计:1 找出最优解的性质,并刻画其结构特征2 递归地定义最优值3 以自底向上的方式计算出最优值4 根据计算最优值得到的信息,构造最优解应用实例:矩阵连乘问题最长公共子序列最大子段和凸多边形最优三角剖分多边形游戏图像压缩电路布线流水作业调度背包问题最优二叉搜索树
阅读全文
摘要:算法思想:对于输入的子数组a[p:r],按下面三个步骤:1 分解:以a[p]为基准元素将a[p:r]分成三段,a[p:q-1],a[q],a[q+1:r],使a[p:q-1]中的任何元素都小于a[q],a[q+1:r]中的任何元素都大于a[q]2 递归求解:递归的对a[p:q-1],a[q+1:r]再进行排序3 合并:就地排序,不需要执行任何计算,便完成排序template <class Type>void QuikSort(Type a[],int p,int r){ if(p<r) { int q = Partition(a,p,r); QuikSo...
阅读全文
摘要:分治算法:用分治策略实现n个元素进行排序的方法。基本思想:将待排序元素分成大小大致相同的两个子集合,分别对两个子集合进行排序,最终排好序的子集合合并成所要求的排好序的集合。源码:/* * mergeSort.cpp * 合并排序算法,算法导论P.17 * Created on: 2011-12-21 * Author: LiChanghai *///#include <iostream>#include <vector>#include <iostream>#include <iterator>using namespace std;#defin
阅读全文
摘要:大整数乘法 分析算法计算复杂性时,加法乘法当做基本运算来处理,即一次加法或者乘法当做一个仅取决于计算机硬件处理速度的常数。正常的二进制整数X,Y要用O(n2)才能算出。如果分割为两段,X=A2^(n/2)+B,Y=C2^(n/2)+D。XY = (A2^(n/2)+B)(C2^(n/2)+D)=AC2^n+(AD+BC)2^(n/2)+BD要进行4次N/2位整数...
阅读全文
摘要:分治法的基本思想:将一个规模为n的问题,分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同。递归的解这些子问题,然后将各个子问题的解合并得到原问题的解。经典例子:二分搜索算法基本思想:1 将n个元素分成个数大致相同的两半,取n/2与x进行比较。2 如果找到,则终止,返回。3 如果小于n/2,则在小半部分继续查找。4 如果大于n/2,则在大半部分继续查找。算法描述代码:#include <iostream>using namespace std;template <class Type>int BinarySearch(Type a[],const Type &
阅读全文
摘要:1 #include <iostream> 2 #include <vector> 3 #include <cstdlib> 4 #include <ctime> 5 6 #define N 100 7 8 using namespace std; 9 10 int wall_row[N+1][N]; 11 int wall_col[N][N+1]; 12 13 class DisjSets 14 { 15 public: 16 explicit DisjSets(int numElements); 17 18 int find(int x) c
阅读全文
摘要:等价关系:自反性,对称性,传递性class DisjSets//不相交集的类架构{public: explicit DisjSets(int numElements); int find(int x) const; int find(int x); void unionSets(int root1,int root2); void unionSets2(int root1,int root2);private: vector<int> s;};DisjSets::DisjSets(int numElements) : s(numElements)//初始化{...
阅读全文
摘要:平均时间O(NlogN),最坏O(N^2)主要过程四步:1 如果S中元素为1 或者 0 ,直接返回2 取S中的任一元素v,称为 枢纽元3 将集合按照 枢纽元大小 分成两个集合4 两个子集合递归调用2 - 3选取枢纽元方法:1错误方法:直接选取第一个2安全方法: 随即选取一个枢纽元3三数中值分割法:选取数组的中值主要代码: 1 #include <iostream> 2 #include <vector> 3 using namespace std; 4 template <typename Comparable> 5 void quicksort( vect
阅读全文
摘要:采用分治的思想 以O(NlogN)最坏的情形运行时间运行如果对merge的每个递归调用都采用局部声明一个临时数组,那么在任一时刻就可能有logN个临时数组处在活动期代码如下: 1 #include <iostream> 2 #include <vector> 3 using namespace std; 4 template <typename Comparable> 5 void mergeSort(vector<Comparable> & a) 6 { 7 vector<Comparable> tmpArray(a.siz
阅读全文
摘要:说白了,也就是大堆,或者小堆,通过删掉堆顶点,然后存入数组,来实现排序:第一阶段:构建堆最多用2N次比较第二阶段:第i次deleteMax最多用到2【logi】次比较,总数最多2NlogN-O(N)次比较代码: 1 #include <iostream> 2 #include <vector> 3 using namespace std; 4 template <typename Comparable> 5 void heapsort(vector<Comparable> & a) 6 { 7 for(int i = a.size()/2
阅读全文
摘要:使用希尔增量时排序的最坏为:O(n^2);代码如下: 1 #include <iostream> 2 #include <vector> 3 using namespace std; 4 template <typename Comparable> 5 void shellsort(vector<Comparable> & a) 6 { 7 for(int gap = a.size()/2; gap > 0; gap /= 2) 8 for(int i = gap; i < a.size() ; i++) 9 {10 Comp
阅读全文
摘要:最简单的排序算法了,每一次j--到对应的值,不会减到0,这个纠结我好久 1 #include "stdafx.h" 2 #include <iostream> 3 #include <vector> 4 using namespace std; 5 6 template <typename Comparable> 7 void insertionSort(vector<Comparable> & a) 8 { 9 int j;10 for(int p=1 ; p<a.size() ; p++)11 {12 Com
阅读全文
摘要:按顺序输出序列: 1 #include <iostream> 2 #include <vector> 3 #include <queue> 4 #include <functional> 5 #include <string> 6 using namespace std; 7 template <typename PriorityQueue> 8 void dumpContents(const string & msg,PriorityQueue & pq) 9 {10 cout<<msg<
阅读全文
摘要:二项队列是 堆序 的集合,也叫 森林。其中每一种形式都有约束。二项树Bk由一个带有儿子的B0,B1,B2...组成,高度为k的二项树 恰好有2^k个结点。每一种高度只能出现一次...因此,只有1,2,4,8...等结点数目的二项树deleteMin操作需要快速的找出跟的所有子树的能力,因此需要一般树的表示方法:每个结点的儿子都在一个链表中,而且每个结点都有一个指向它的第一个儿子的指针。二项树的每一个结点包括:数据,第一个儿子,以及右兄弟下面是二项队列类构架及结点定义: 1 template <typename Comparable> 2 class BinomialQueue 3
阅读全文
摘要:斜堆是左式堆的自调节形式,是具有堆序的二叉树,但是不存在对树的结构限制。不含有npl信息。右路径可以任何时刻任意长,因此所有的操作最坏情况均为O(N)。与左式堆的区别:对于左式堆,查看是否左儿子,和右儿子满足左式堆的结构性质,如果不满足,交换。对于斜堆,无论是否满足,都要进行这种交换。斜堆可递归的定义如下:只有一个元素的堆是斜堆。两个斜堆通过斜堆的合并操作,得到的结果仍是斜堆。优点不需要附加空间保留路径长吗,不需要测试确定何时交换儿子
阅读全文
摘要:零路径长:从X到一个不具有两个儿子的结点的最短路径的长。性质:任一结点的零路径长比他的诸儿子结点的零路径长的最小值多1父节点属性值小于子节点属性值;堆中的任何节点,其左儿子的零路径长>=右儿子的零路径长;的二叉树。下面是左式堆的类型声明: 1 template <typename Comparable> 2 class LeftistHeap 3 { 4 public: 5 LeftistHeap(); 6 LeftistHeap(const LeftistHeap & rhs); 7 ~LeftistHeap(); 8 9 bool isEmpty() co...
阅读全文
摘要:容易证明:一棵高为h的完全二叉树有2^h 到 2^(h+1)-1个结点。这就意味着,完全二叉树的高是[logN]特点:任意位置i:左儿子在位置2i上,右儿子在位置2i+1上,父亲在i/2上一个堆数据结构将由一个Comparable数组和一个代表当前堆的大小的整数组成:优先队列的接口: 1 template <typename Comparable> 2 class BinaryHeap 3 { 4 public: 5 explicit BinaryHeap ( int capacity = 10 ); 6 explicit BinaryHeap ( const Vector<
阅读全文
摘要:选择键值,冲突的时候采取不同的策略散列函数:简单的散列函数:1 int hash(const string & key,int tableSize)2 {3 int hashVal = 0;4 for(int i = 0; i < key.length();++i)5 {6 hashVal + = key[i];7 }8 return hashVal % tableSize;9 }比较好的散列函数: 1 int hash( const string & key,int tableSize ) 2 { 3 int hashVal =...
阅读全文
摘要:B树即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right); 2.所有结点存储一个关键字; 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树;如:B树的搜索,从根结点开始,如果查询的关键字与结点的关键字相等,那么就命中;否则,如果查询关键字比结点关键字小,就进入左儿子;如果比结点关键字大,就进入右儿子;如果左儿子或右儿子的指针为空,则报告找不到相应的关键字;如果B树的所有非叶子结点的左右子树的结点数目均保持差不多(平衡),那么B树的搜索性能逼近二分查找;但它比连续内存空间的二分查找的优点是,改变B树结构(插入与删除结点)不需要移动大段的内存数据,甚
阅读全文
摘要:没看懂,多看几遍吧1 简介:伸展树,或者叫自适应查找树,是一种用于保存有序集合的简单高效的数据结构。伸展树实质上是一个二叉查找树。允许查找,插入,删除,删除最小,删除最大,分割,合并等许多操作,这些操作的时间复杂度为O(logN)。由于伸展树可以适应需求序列,因此他们的性能在实际应用中更优秀。伸展树支持所有的二叉树操作。伸展树不保证最坏情况下的时间复杂度为O(logN)。伸展树的时间复杂度边界是均摊的。尽管一个单独的操作可能很耗时,但对于一个任意的操作序列,时间复杂度可以保证为O(logN)。2 自调整和均摊分析: 平衡查找树的一些限制:1、平衡查找树每个节点都需要保存额外的信息。2、难于实现
阅读全文