
算法导论学习
文章平均质量分 78
水中鱼_自由
123
展开
-
B树和B+树
B树:多路查找树,B树定义如下: 1、每个结点x有以下属性: (a)x.n,当前存储在结点x中的关键字个数为n; (b)x.n个关键字本身x.key1,x.key2…x.keyn,以非降序排列,即x.key1≤x.key2≤…≤x.keyn; (c)x.leaf,bool值,为true表示是叶子节点,false为非叶子节点 2、每个内部节点x含有x.n+1个孩子指针x.c1…x.c转载 2016-08-08 09:40:42 · 264 阅读 · 0 评论 -
C++排序算法总结
先上来时间复杂度 区分稳定与不稳定:快速、希尔、堆、选择不稳定,其他排序算法均稳定。 C++实现排序算法代码如下:#include<iostream>#include<vector>#include<limits>using namespace std;//插入排序,相当于打牌,相当于把一个值插入到已经排序好的一个数组中,//先把待排序的值放到一个临时变量里面,让排好序的数字从大到原创 2016-07-19 20:52:38 · 1676 阅读 · 0 评论 -
大数乘法
给定两个字符串,对其求积。原理:对于乘数和被乘数,例如9*9,计算的结果位数最多为2位,也就是说,任意一个数,乘以9,结果最多增加1位,所以,对于i位乘数和j位被乘数,所得到的结果最多为i+j位。在结果中,第i+j位的值为乘数中第i位乘以被乘数第j位和乘数第j位乘以被乘数第i位的值的和。在后期处理中,因为结果中的极有可能是大于9的,所以要进行向高位进位处理。 代码如下:void main(){原创 2016-05-14 16:55:42 · 353 阅读 · 0 评论 -
动态规划C++
对于动态规划,每个刚接触的人都需要一段时间来理解,特别是第一次接触的时候总是想不通为什么这种方法可行,这篇文章就是为了帮助大家理解动态规划,并通过讲解基本的01背包问题来引导读者如何去思考动态规划。本文力求通俗易懂,无异性,不让读者感到迷惑,引导读者去思考,所以如果你在阅读中发现有不通顺的地方,让你产生错误理解的地方,让你难得读懂的地方,请跟贴指出,谢谢!—-第一节—-初识动态规划——– 经典的转载 2016-05-10 22:12:34 · 772 阅读 · 0 评论 -
何时使用递归解决问题?-重建二叉树
将主问题分割成小问题的时,当发现小问题与主问题在本质上是一样的,即小问题重复主问题分割成小问题这个步骤时,分割成更小的问题,就要用递归方法解决。典型的应用:根据二叉树的前序遍历和中序遍历,创建一个二叉树结构问题。 思路如下:第一:根据前序遍历的第一个结点值为根结点,然后遍历中序遍历的输出,找到这个根节点在中序遍历中的位置,记录此位置pos,此时,在中序遍历左边的全部是根节点中左子树上面的结点,右边原创 2016-04-15 16:51:59 · 737 阅读 · 0 评论 -
二叉树搜索树的插入算法
对于给定一个要插入的节点,需要修改二叉树的结构,首先是要定位到要插入的位置,代码如下:void InsertNode(BiTree &T,char value){ BiNode *node=new BiNode(); node->data=value; node->left=NULL; node->right=NULL; if(T==NULL) {原创 2015-12-20 11:58:01 · 1392 阅读 · 0 评论 -
二叉搜索树的搜索和最值情况
二叉搜索树是一种排序树,其左子树的值<=根节点<=右子树,根据此公式,可以很方便的得出二叉树搜索树的最值,其代码如下:typedef struct BiNode{ char data; BiNode *left,*right;}BiNode,*BiTree;void TreeMinimum(BiTree &T)//**是对指针的引用,为根节点**{ while(T->le原创 2015-12-19 12:02:17 · 385 阅读 · 0 评论 -
二叉树的创建与遍历
二叉树是一个极其重要的数据结构,必须稳固掌握,在下就浅谈二叉树的基本操作。首先,是二叉树的创建,创建分为三种方式,先序,中序,后序,本博文以先序为例,其他两种类似。亲身测试,能执行。代码如下: h文件#ifndef _TREE_H#define _TREE_H#include<vector>#include<iostream>using namespace std;typedef str原创 2015-12-19 10:55:37 · 433 阅读 · 0 评论 -
散列表的插入和删除
散列表进行插入和删除都要借助于hash函数,根据要插入或删除的值,对应到相应的位置,再对该位置进行操作。代码如下:void collsion(hash_node *hash[],int elem, hash_node *news)//*hash[]传的是指针数组,其实传的是指针数组的首地址,即地址的地址,如果直接传数组元素的地址,返回并不指向该数组中元素的地址。处理冲突{ if(hash原创 2015-12-15 22:28:36 · 6655 阅读 · 0 评论 -
散列表(哈希表)之链接法浅谈
通俗意义上说,哈希表就是一个数组,每个数组元素存放的是链表的头结点。其作用是将全局域U中的所有元素m个映射到数组元素个数为n(n头文件中的内容struct hash_node{ int data; hash_node *next,*prev;};int Hash(int key);void CreateHash(hash_node *hash[],vector<int> &原创 2015-12-14 20:17:17 · 1094 阅读 · 0 评论 -
顺序统计量的选择
在选择顺序统计量中,期望的时间复杂度是O(n),主要是对于给定的数组,从其中选择出第k小的值。其与原理:利用了快速排序中的随机分割区间的函数,将第k小的值分割到一个区域里面,相当于把该问题划分的时候只划分了一个子问题,就没有O(lgn),根据快速排序的时间复杂度为O(nlgn)可知,其时间复杂度为O(n)。对于分割后返回的位置值,用之与k比较大小,便知道了第k小的值所在的子数组位置,一直递归,便能求原创 2015-12-10 10:40:30 · 619 阅读 · 0 评论 -
计数排序
计数排序是一种稳定排序:对于相同值的元素在输出数组中的相对次序和输入数组中的次序相同。且它不是一种比较排序,时间复杂度为O(n). 计数排序原理:对于每一个输入元素x,确定出小于等于x的元素个数,将x放到所有小于等于x的位置后面,有重复的,则放置一个x以后,将元素个数减1,以便下一次继续放置。 代码如下:void Insert::CountingSort(vector<int> &coll,ve原创 2015-12-09 16:35:50 · 369 阅读 · 0 评论 -
随机快速排序法
在上次博客中,写到了快速排序法,但是该算法有一个缺陷,那就是始终以最后一个元素值作为主元,不能得到很好的平衡性能,在随机快速排序法中,可以将数组中任意一个元素作为主元,这样就能很好的达到期望值为O(nlgn)。其原理:在数组下标中生成一个随机数,将此随机下标中元素的值与数组中最后一个元素的值进行交换,然后再利用最后一个元素当作主元进行分区。分区过后,再用快速排序去调用此随机算法分区,用分治法实现。代原创 2015-12-09 10:29:44 · 614 阅读 · 0 评论 -
快速排序算法总结
有了上一篇的区间划分以后,快速算法就比较容易实现,快速算法是一种原地排序算法,最坏情况下是O(n*n),平均时间是O(lgn)。其原理:通过区间划分,不断递归,最后只有一个元素,则已经排好序。所以采用分治法,但并不需要合并,因为两个子数组是就地排序的。代码如下:void Insert::QuickSort(vector<int> &coll,int p,int total){ if(p<t原创 2015-12-08 22:20:37 · 363 阅读 · 0 评论 -
快速排序之区间划分
快速排序的关键在于区间划分,是指将待排序的数组原地进行区间划分,原理是:将待排序的数组的最后一个元素作为主元,将小于主元的数组元素放在数组较小的下标,将大于主元的数组元素放在较大的下标。主元放在两者之间。(注意:是原地分区,所以分区后还是在待排序的数组里) 在初始化时,默认分区的两个子数组元素个数均为0.对待排序的数组进行遍历,将每个元素从下标0开始与主元比较,大于主元的,就放在右边,小于主元的原创 2015-12-08 16:19:29 · 1554 阅读 · 0 评论 -
堆排序总结
对于使用堆,其实质上是对完全二叉树进行操作,在理论上看成是树形结构,但在实际代码中,使用数组在进行相关的操作。由于堆会有动态增加元素的功能,所以最好使用容器,不要使用数组,现将以前代码都换成容器,但切记,一定要引用,因为如果是数组,传递给函数的是数组指针,可以直接修改值,而容器是对象,不能直接修改,所以要用引用。 其所有函数的相关代码如下://建堆void Insert::BuileMaxHea原创 2015-12-08 14:08:54 · 401 阅读 · 0 评论 -
堆插入
对于给定的堆,插入一个元素,使之满足最大堆性质。其原理是:为原来的堆末尾添加一个计算机所允许的最小元素,然后调用增加优先级函数,将要插入的值放置到合适的位置。因为要动态的增加元素,所以不能使用数组,应该使用容器。 代码如下void Insert::MaxHeapInsert(vector<int> &coll,int key){ coll.push_back(-65535); i原创 2015-12-08 14:03:40 · 505 阅读 · 0 评论 -
最大优先队列中增加优先级
最大优先队列是基于最大堆实现的。增加优先级的原理如下: 对于给定元素中下标要增加优先级,先将要增加的优先级的值赋给该下标的值,然后从该点开始,与其父节点相比较,直到找到合适的位置或者到根节点。代码如下:void Insert:: HeapIncreseKey(int A[],int value,int key){ if(key<A[value]) { cout<<"th原创 2015-12-07 18:54:01 · 400 阅读 · 0 评论 -
堆排序
堆是最大堆(其数组元素大小排序是杂乱的,数组元素之间只有堆结构关系),排序的结果为数组元素从小到大。 其原理:先把给定的数组进行建堆,建好的堆为最大堆,根元素值最大,而最后的那一个叶子元素值最小,即数组中最后下标值。将两个元素进行对换,这样最大值就到数组的最后一个下标处。再删除最后一个下标,将剩下的元素进行堆维护,形成最大堆,如此循环往复,直到最后只剩一个元素,为最小值。 代码如下:void I原创 2015-12-07 17:26:17 · 315 阅读 · 0 评论 -
建堆
建堆过程就是根据数组元素进行最大堆的创建,可以利用堆维护的性质,堆维护见博客。在进行创建时,将数组的最后一半元素视为叶子,对前一半利用堆维护的性质进行建堆。时间复杂度为O(n)代码如下:void Insert::BuileMaxHeap(int A[],int total){ int roots=total/2-1;//建堆时,把数组元素后一半的视为完全二叉树即堆的叶子. for(原创 2015-12-07 16:08:28 · 425 阅读 · 0 评论 -
堆维护
堆排序中,指的是最大堆排序,而最小堆是用于优先队列的。 最大堆排序:可以把堆看做是完全二叉树,不过其父节点的值大于自己点。一般使用数组来实现堆排序。堆维护就是通过算法使数组始终满足堆的条件。代码如下:void Insert::MaxHeapIFY(int A[],int local)//堆维护{ int total=14;//临时测试用的数组长度值 int left_child=原创 2015-12-07 15:16:18 · 2027 阅读 · 0 评论 -
维护堆性质中,堆(完全二叉树)中i结点的子树大小至多为2n/3的证明
思路源自于: http://bbs.sjtu.edu.cn/bbstcon,board,Algorithm,reid,1242723801,file,M.1242723801.A.html 在理解维护堆性质时,算法导论上面只简单提了一下子树的大小为2n/3,不明白,从网上理解得到如下结论。 已知: 当堆是满二叉树时:(ceiling表示其最大值) 最底层原创 2015-12-05 12:30:25 · 2038 阅读 · 1 评论 -
递归式时间复杂度的计算
写给自己! 递归式的时间复杂度很难人为的计算出来,根据算法导论知道一个应用公式: 使用时主要思路如下: 首先根据自己的递归代码写出T(n),T(n)为递归所用的总时间,其中,n为输入的规模,a为分解成子问题的个数,n/b为子问题输入的子规模,f(n)是一个渐进正的函数。a个子问题被分别递归的解决,时间各为T(n/b)。原创 2015-12-04 15:34:33 · 1997 阅读 · 0 评论 -
插入排序 C++实现
写给自己!! 插入排序算法,其如同打牌,手里总是已经排好续的牌,而桌面上的是未知牌,其思想是:拿起一张牌,与手中的牌从右到左(从大到小)进行比较,找到合适的位置插入即可。插入排序算法没有合并排序算好效率高,他随着输入的增大而增大。 代码思想:对于将要插入的第j个元素,与已经排序好的0…j-1个元素从j-1处开始比较,如果j-1比j的元素大,则将j-1处的元素往后移原创 2015-12-04 10:54:19 · 374 阅读 · 0 评论 -
合并排序 C++实现
写给自己的,避免忘记!! 合并排序算法采用先分治,再合并的思路。此思路根据算法导论原理,在合并算法中,是将两个已经排序好的数组进行合并。原创 2015-12-04 10:39:14 · 1640 阅读 · 0 评论