挑战程序大赛(第2版)第一二章总结笔记
第一章
世界举办的著名的程序设计大赛有:
①Google Code Jam 需要队员在2到3个小时内完成4道程序设计题目。
②TOPCoder 需要在1个小时15分钟完成3道程序设计题目,其中还可以在程序设计阶段完成后,继续挑战查看别人代码的错误,这样可以获得额外的分数。
③ACM-ICPC 由美国计算机协会主办,需选手在5个小时内,完成10道程序设计题目,但是三位选手只能公用一台电脑,团队配合显得异常重要。
④JOI-IOI 面向中学生的一项程序设计比赛,只需要选手在规定的时间内,把问题就可以了,成绩与时间无关。
⑤OJ(Online Judge),在互联网上,OJ系统会自动评测以外竞赛中的题目,选手可以利用该系统自己练习,来提高自己的程序设计的能力。
第二章
递归函数:定义就是在一个函数的结尾返回时,返回的是自己本身的函数,再次利用本身的函数继续执行下去。
例如,我们可以举个例子:
Int fac(n):{ if(n>0) { Return fac(n-1)+n; } Else { Break; } }
这就是递归函数,这个程序就会一直加下去,知道n小于等于0为止;就会停止。还有很多这样的例子,比如斐波拉契数数列,求一个数n的阶乘等等,都可以利用递归函数。
栈:是一种支持Pop和push的数据结构。特点是先进后出,或者是后进先出。其中pushu是把数据压入栈内,而pop是把数据从栈内取出。
队列:也是一种支持pop和push的数据结构。特点是先进先出,或者后进后出,与栈的数据压入取出的方式不同。
深度优先搜索:从某个顶点访问,首先访问图的顶点,然后从该顶点出发访问左边的顶点或者右边的顶点,之后依次访问下一个顶点,直到把左边或者右边的顶点访问完,最后访问另一边的顶点。
例如上图中的二叉树,我们可以按照这样的顺序1->2->3->4->5->6->7->8->9->10->11,
也可以1->7->11->8->9->10->2->3->4->5->6
针对深度优先搜索,我们可以用C的方式:
Void DFSTraverseAL(ALGraph *G)
{/*深度优先搜索以邻接表存储的图*G*/
Int i; For(int i=0;i<G->vexnum;i++) Visited[i]=FALSE; /*访问标志数组初始化*/ For(i=0;i<G->vexnum;i++) If(!visted[i]) DFSAL(G,i); }
宽度优先搜索:定义是从顶点开始访问,然后依次访问顶点以下邻接的点,之后继续按照顶点未访问的邻接点访问,直到所有点全部访问完。
按照图上的二叉树的话,根据宽度优先搜索的定义可以这样访问:
1->2->7->3->6->8->11->4->5->9->10
Void BFSTraverseM(MGraph *G)
{/*深度优先搜索以邻接表存储的图*G*/
Int i; For(int i=0;i<G->vexnum;i++) Visited[i]=FALSE; /*访问标志数组初始化*/ For(i=0;i<G->vexnum;i++) If(!visted[i]) BFSML(G,i); }
动态规划(DP)一般可以遵循下面公式:
当j<w[i]
Dp[i+1][j]=dp[[i][j];
在其他的情况下
Dp[i+1][j]=max(Dp[i+1][j],Dp[i][j-w[i]]+v[i]
树,二叉树:
树:n(n>=0)个节点的有限集合,当n=0时,称为空树。任意一棵非空树满足以下条件:
(1)有且仅有一个特定的称为根的节点;
(2)当n>1;除根节点之外的其他节点被分为m(m>0)个互不相交的有限集合T1,T2,......Tn,其中每个集合又是一棵树,并称为该根节点的树。
图1
图1
在树中有一些术语:
1. 树的结点:由一些数据元素和若干指向其字数的分支组成。
2. 节点的度:节点所用所拥有的子树的个数,即分支数称为该节点的度。例如图1中的父亲指向的点的度为2,而兄弟指向的点度则为0.
3. 叶子结点:度为0的结点称为叶子节点。例如图1中有2个叶子节点。
4. 树的度:树中个节点的度的最大值。
二叉树:二叉树是数的树的一种。二叉树中每个节点最多有两个节点,所以二叉树的节点的度不会超过2。而且二叉树是一棵有序树,其左右子树不能交换。如果交换,那么得到的又是另一种二叉树。
在二叉树中,又有几种特殊的树:满二叉树,完全二叉树,斜树。满二叉树:在满足二叉树的定义情况下,所有叶子节点都在同一层上,并且叶子节点的上一层子树的节点的度一定为2,只有叶子节点的度为0.
完全二叉树:在满足二叉树的情况下,叶子节点只能出现在最下层和次下层,并且最下层的叶子节点只能在次下层子树的左部,并且次下层以上一定是满二叉树,满足最多只有一个度为1的节点的完全二叉树。
斜树:所有节点除开顶点之后,都在顶点左侧或者右侧,称为左斜树或者右斜树,也称为单枝二叉树。
优先队列:能够插入一个数值并且取出队列中最小的值的队列称为优先队列。
堆:满足二叉树的情况下,儿子本身的值不小于父亲的值。
在插入值的时候,在原来二叉树的末尾插上节点,然后观察二叉树的本身,如果儿子的值大于父亲的值则不交换,否则交换。
同样,在删除一个最小值得时候,删除顶点的值,然后从原来二叉树的末尾复制该节点,然后删除该节点,并且复制到顶点处,最后进行从上到下,从左到右,进行大小排序,按照从小到大的顺序。
堆的实现:如果赋予每个节点一个编号,按照从0到大的顺序排列,那么某个节点n(如果它存在左右儿子的情况下),那么他的做儿子满足2*n+1,右儿子满足2*n+2.
二叉搜索树的结构:
1. 插入一个数值。
2. 查询每个数值是否存在
3. 删除某个数值。
在二叉搜索树中,所有的点都满足,自己的左儿子的值小于自己的值,自己的右儿子的值大于自己的值。
查询
例如在查找上图中是否存在10,根据二叉搜索树的方法,先从顶点查找比7大,沿着右子树查找,顶点为15,比10大,沿着左子树查找,找到10.
插入
同样在插入值6,跟顶点比较值较小,往左子树下走,与2比较值较大,往右子树下走,与5比较值较大,往右子树下走,发现此位置无值,可以把值为6的数据插入到这。
删除
比如删除上图子树中的数据为2的值,一旦删除,左子树与右子树悬空,可以从左子树与右子树中找值,通过二叉树的定义可以找到数据为4的值。
图
图是由有穷非空顶点集合和顶点之间关系----边(或弧)的集合组成。一般的表示方式为:G=(V,E).其中G表示一个图,V是G的顶点的集合,E表示G的边的集合,集合E可以用P(u,v)表示一个顶点u和顶点v之间有一条直线相连。然后,就存在下面的关系:
1. G=(V,E)
2. V={u1,u2,u3.........un}
3. E={(u1,v1),(u2,v2).......(un,vn)}
图分为无向图和有向图:
上图中左边就为无向图,右边为有向图。同样有向图满足关系:
1. G=(V,E);
2. V={1,2,3,4,}
3. E={(2,1),(3,2),(4,3),(4,1),(4,2),(3,1)}
图中,如果赋予两个顶点之间有数据信息的话称为权。
权值可以表示这条线路的关系,如果是在一个电子线路图中,权值可以便是两个端点之间的电压值,电流值等等。如果是反应工程的图,可以表示一个子工程持续的时间。
上述图中为无向图的权值之间的关系。如果加上方向为有向图的权值之间的关系。
顶点之间的出度,入度:表示某一顶点依附其他顶点的边数。
上图中的无向图中,不用顶点的出入度有不等,但是无向图中一个顶点的出度和入度一定相等。
上图中的有向图中,不同顶点的出入度有不等,一个顶点的出度和入度也不一定相等。
领接矩阵存储结构也称为数组表示法,该表示法用一维数组存储图中顶点信息,用二维数组存储图中各顶点之间的邻接关系。
I j |
0 |
1 |
2 |
3 |
4 |
0 |
0 |
1 |
0 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
0 |
2 |
0 |
1 |
0 |
1 |
0 |
3 |
1 |
1 |
1 |
0 |
1 |
4 |
0 |
0 |
0 |
1 |
0 |
邻接表
领接矩阵会浪费许多存储空间,在邻接表中,只会存储与该顶点相关联的顶点信息,从而大大节约存储空间。
I j |
相关联的顶点 |
0 |
1 |
1 |
3 |
2 |
1 |
3 |
0,2 |
4 |
3 |