随笔分类 -  算法

摘要:算法思想:借助最大堆的性质,堆的根节点是最大的节点,每次迭代将根节点从堆中摘除,用最末一个叶子节点替代原先的根节点,此时新生成的树不具有堆的性质,所以要对树的结构进行调整,让新树的根下降到较低的层次(最大堆的根节点不小于它的子节点),以此来重新构造一个最大堆。算法步骤:1、首先建立最大堆2、排序思想是每次迭代都把根元素与最后一个元素交换,同时剔除根元素(heapSize - 1),再对交换上来的根进行调整,保持堆的性质。 1 // 最大堆调整 2 // i为待调整的根节点 3 void maxHeapify(int *A, int i, int size) { 4 // 根编号为0的左... 阅读全文
posted @ 2013-10-09 17:21 StrikeW 阅读(249) 评论(0) 推荐(0)
摘要:问题定义: 求数组A中一个连续的和最大的子数组。比如数组[4,5,-6,7,-3,1]的最大子数组是[4,5,-6,7],和为10。解法一:分治法 可以把问题转化成求两个子数组的最大子数组问题。令mid为数组A[low, high]的中间位置,则A[low, high]的最大子数组所处的位置存在如下三种情况:1、完全位于A[low, mid]之中2、完全位于A[mid+1, high]之中3、横跨中点mid对于1、2两种情况相当于将问题的规模缩小为原来的一半,因此只需要递归求解即可。第3种情况需要单独考虑。首先可知横跨中点mid的子数组中一定包含元素A[mid],则我们可以将第3种情况一分.. 阅读全文
posted @ 2013-10-08 22:18 StrikeW 阅读(446) 评论(0) 推荐(0)
摘要:1 vector split(const string& src, const string& sep) { 2 vector tokens; 3 int lastPos = 0, // 上次找到的sep的位置 4 index, 5 sepLen = sep.length(); 6 while ( -1 != (index = src.find(sep, lastPos) )) { 7 // substr(起始位置,字符串长度) 8 tokens.push_back(src.substr(lastP... 阅读全文
posted @ 2013-09-11 00:35 StrikeW 阅读(199) 评论(0) 推荐(0)
摘要:如果仅仅需要对图进行DFS和BFS遍历,那么最好使用邻接表表示法。因为邻接表表示法中每一个链表里存的是与头节点相邻的所有节点,因此在DFS和BFS的遍历过程中能够很方便的找出相邻的节点。如果要找单源最短路径(Dijkstra算法),那么最好使用邻接矩阵表示法,因为每次找出distance数组中的最短路径后,要更新distance数组,此时需要知道某个节点与其他节点之间的距离,邻接矩阵直接通过下标adjMatrix[v][w]即可获取,而邻接表需要遍历以v为头节点的链表,找到以w为终点的边节点。 阅读全文
posted @ 2013-09-07 16:05 StrikeW 阅读(414) 评论(0) 推荐(1)
摘要:DFS(深度优先遍历)图中蓝色的是顶点之间的边。从某一个顶点v开始,遍历与其相邻的顶点w0,w1,...,wn,在访问w1之前,先访问w0,并且遍历完w0的所有相邻顶点。DFS是一个递归的过程,有前进和回退。C++代码实现: 1 #include 2 #include 3 #include 4 #include 5 #include 6 using namespace std; 7 #define N 100 8 9 char vertex[N];10 // vector在这相当于邻接表的用法!11 vector a[N];12 bool vis[N];13 int n,e;14 ... 阅读全文
posted @ 2013-09-05 00:45 StrikeW 阅读(356) 评论(0) 推荐(0)
摘要:银行家算法是经典的死锁避免算法,由两个部分构成。所需要的数据结构:(n是系统中的进程数量,m是资源类型的数量)Available:长度为m的向量,表示当前系统各资源的可用数量。Available[j]==k,表示类型为j的资源 ,可用数量为k。Max:nxm的矩阵,表示所有进程对资源的最大需求量。Max[i][j]==k,表示进程Pi对类型为j的资源的最大需求量为k。Allocation:nxm的矩阵,表示当前时刻,进程所占有的资源情况。Allocation[i][j]==k,表示进程Pi当前占有k个j类型的资源。Need:nxm的矩阵,表示进程对资源的申请情况。Need[i][j]==k,表 阅读全文
posted @ 2013-09-04 19:52 StrikeW 阅读(365) 评论(0) 推荐(0)
摘要:根据算数基本定理,一个合数可以分解成多个素数的乘积。输入:一个正整数输出:它的所有质因数思路 2是最小的素数,所以从2开始,不断地用2去除正整数n,如果可以被除尽,那么输出质因数2,如果除不尽,2加1到3,再用3去除。直到最后n变成1了,则结束循环。 我之前有个顾虑就是在循环时如何保证当前的除数是素数?后来发现因为2是素数,所以如果n能被其他偶数整除,那么首先就会被除数2整除,并且往后我们会判断能否继续被2整除,只有当2除不尽时,除数才会开始递增。质因数分解中有一个规律:首先找出的质因数比后找出的质因数小。C++代码实现:#include int main(){ int T, n; sca.. 阅读全文
posted @ 2013-09-02 23:58 StrikeW 阅读(478) 评论(0) 推荐(0)
摘要:中学学过的方法是这样的:假设我要把十进制2991转换成十二进制,那么就用12来除2991,余数是十二进制数的最低位,继续用12除之前所得到的的商,余数是十二进制数的第二位,以此类推。直到最后所得商数为0,算法终止。需要注意的是十六进制中,10~15是用英文字母ABCDEF来表示的,这个需要特别处理。C++代码:#include #include #include void mySwap(char& a, char& b) { char temp = a; a = b; b = temp;}// 翻转字符串void reverseStr(char src[]) { int i = 阅读全文
posted @ 2013-09-02 16:14 StrikeW 阅读(1833) 评论(0) 推荐(0)
摘要:这几天一直都在看跟递归有关的内容,于是就顺便复习了一下同样具有递归的分治法思想的归并排序和快排。以前因为一直难以理解递归的思想,导致我理解起快排和归并排序非常的痛苦,所以产生了排斥的心理,现在认真学习了一番发现其实递归的思想并不难理解。归并排序的算法步骤1、将数组A[p, r]等分成两个子数组:A[p, q]和A[q+1, r],其中q = (p+r)/2。2、分别对两个子数组进行归并排序。3、合并两个已有序的子数组。核心步骤是第三步,归并排序就是在经过第三步后使得数组由无序变为有序的,所以我们首先要写出第三步的算法,用一个函数merge来实现。既然是要合并两个数组,那函数的参数就是两个有已有 阅读全文
posted @ 2013-08-29 17:37 StrikeW 阅读(389) 评论(0) 推荐(0)