1 solutions
-
-2
基础数据类型 char(1字节),bool(1字节),short(2字节),int(4字节),float(4字节),double(8字节), 一般指针为4字节,结构体(struct)里面所占的空间为各成员所占内存之和,一个联合体(union)所占的空间为是最大成员的大小 一般来说,按照数据的逻辑结构对其进行简单的分类,包括线性结构(元素存在一对一的相互关系)、树形结构(元素存在一对多的相互关系)和图形结构(元素存在多对多的相互关系)。 线性结构 线性结构指的是数据元素之间存在着“一对一”的线性关系的数据结构。常用的线性结构有:一维数组,链表,栈,队列等。 1.链表 定义:链表和数组都可用于存储数据,其中链表通过指针来连接元素,而数组则是把所有元素按次序依次存储。 链式存储结构(链表)由一系列结点组成,每个结点包含两个部分:存储元素本身的数据域和存储下一个结点地址的指针域。用一组非连续的存储单元来存储结点数据 ,且链表的长度不是固定的。 优点1:存储空间是动态分配的,只要计算机内存空间还有空闲,就不会发生溢出。 优点2:插入或者删除元素方便,时间复杂度为O(1)。 缺点:查找元素不方便,时间复杂度为O(n)。链表不可以随机访问任意数据! 2.栈 栈 定义:有一叠碗,每一次取的时候取最上面的出来,放的时候放到最上面,先进来的后出去,后进来的先出去,具有先进后出(FILO,first in last out)的特性。 进行删除和插入的一端称为栈顶(top),另一端称为栈底,插入一般称为进栈(push),删除则称为退栈或出栈(pop)。 3.队列 队列(queue)和栈一样,是一种操作受限制的特殊线性表。它只允许在表的队头(head)进行出队操作,而在队尾(tail)进行入队操作。具有先进先出(FIFO,first in fist out)的特性。 队首/队头:队列的第一项。 队尾:队列的最后一项。 13333.png 4.树形结构 a.jpg 树形结构指的是数据元素之间存在着“一对多”的关系的数据结构。特点:根节点除外的每个结点有一个或多个后驱(child),一前驱(parent)。如图就是一棵树,我们看到它是若干结点(A、B、C等都是结点)的集合,是由惟一的根(结点A)和若干棵互不相交的子树(如B、E、F、K、L这5个结点组成的树就是一棵子树)组成的。其中每一棵子树又是一棵树,也是由惟一的根结点和若干棵互不相交的子树组成。 结点:A、B、C等都是结点,注意结点不仅包含数据元素,而且也含指向子树的分支。如A结点不仅包含数据元素A,而且包舍三个指向子树的指针。 根结点:一棵树至少有一个结点,这个结点就是根结点 叶子结点:又叫做终端结点,指度为0的结点,如F、G、I、J、K、L、M结点,都是叶子结点。 非终端结点:又叫分支结点,指度不为0的结点,如A、B、C、D、E、H结点,都是非终端结点。除了根结点之外的非终端结点,也叫做内部结点,如B、C、D、E、H结点.都是内部结点。 父结点:称上端结点为下端结点的父结点,如B是E和F的父节点 孩子结点:称下端结点为上端结点的子结点,如E是B的子节点 兄弟结点:称同一个父结点的多个子结点为兄弟结点,如E和F为兄弟结点 祖先结点:又称从根结点到某个子结点所经过的所有结点称为这个结点的祖先,如L的祖先有E,B,A 子孙结点:称以某个结点为根的子树中的任一结点都是改结点的子孙,如结点B,E,K都是结点A的子孙。 结点的度:结点拥有的子树个数或者分支的个数。如A结点有三棵子树、所以A结点的度为3。 树的度:树中各结点度的最大值。如图中结点度最大为3(A、D结点),最小为0(F、G、I、J、K、L、M结点),所以树的度为3。 树的深度(或高度):树中结点的最大层次。如例子中的树共4层,所以深度为4 5.二叉树 将一般的树加上如下这两个限制条件就得到二叉树。 (1)每个结点最多只有两棵子树,即二叉树中结点的度只能为 0 , 1 , 2 0,1,2. (2)子树有左右之分,不能颠倒。 根据二叉树的定义,可以知道二义树有 5 5种基本的形态,如下图 二叉树的5种基本形态为: 13333.png (a)空二叉树。 (b)只有根结点。 (c)只有左子树,右子树为空。 (d)只有右子树,左子树为空。 (e)既有左子树,又有右子树。 ① 满二叉树 13333.png 除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树。深度为 k k且含有 2 k − 1 2 k −1个结点。 ② 完全二叉树 叶节点只能出现在最下层和次下层,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树。(树中所含的 n n个结点和满二叉树中编号为1至 n n的结点一一对应。) 二叉树性质: 性质1:二叉树的第 i i层上最多有 2 i − 1 2 i−1 个结点(i>=1) 结点最多的情况即为满二叉树的情况。 性质2:高度(或深度)为 k k的二叉树最多有 2 k 2 k -1个结点 ( k > = 1 ) (k>=1) 性质3: n n个节点的完全二叉树深度为 l o g 2 n + 1 log 2 n +1 性质4:对任意一棵二叉树,如果其叶结点数为 n 0 n 0 ,度为2的结点数为 n 2 n 2 ,则一定满足: n 0 = n 2 + 1 n 0 =n 2 +1. 二叉树的遍历 a.jpg (一)先序遍历: 如果二叉树是空树,则什么都不做; 否则: 访问根结点; 先序遍历左子树; 先序遍历右子树。 先序遍历右图二叉树的结果为:124753689 (二)中序遍历: 中序遍历操作过程: 如果二叉树是空树,则什么都不做; 否则: 中序遍历左子树; 访问根结点; 中序遍历右子树。 中序遍历右图二叉树的结果为:742513869 (三)后序遍历: 后序遍历操作过程: 如果二叉树是空树,则什么都不做; 否则: 后序遍历左子树; 后序遍历右子树。 访问根结点; 后序遍历右图二叉树的结果为:745289631 6.字符串 定义:字符串指一串字符组成的串。 子串:子串被定义为字符串中任意个连续的字符组成的子序列,子串个数= n ∗ ( n + 1 ) 2 + 1 2 n∗(n+1) +1,非空子串的个数= n ∗ ( n + 1 ) 2 2 n∗(n+1) 注意:前提是字符串中的各个字符互不相同。 7.前/中/后缀表达式: ① 前缀表达式 又称波兰式;一种没有括号的表达式,与后缀表达式不同的是,将运算符写在前面, 操作数写在后面。如:前缀表达式 -1+2 3 的中缀形式为1−(2+3)。 ② 中缀表达式 就是我们平时最常用的表达式; ③ 后缀表达式 又称逆波兰式;与前缀表达式相反,将操作数写在前面,运算符写在后面。如:后缀 表达式 1 2 3 + − 的中缀形式为 1-(2+3)。 ④ 表达式互换 (1)前/后缀表达式转中缀表达式: 1.画出表达式树:表达式树是一种特殊的树,叶节点是操作数,其他节点为运算符 2.将表达式树前序遍历,可得前缀表达式;中序遍历可得中缀表达式;后序遍历可得后缀表达式。 (2)中缀表达式转前/后缀表达式 1.给中缀表达式加上括号: 1-2+3 →((1−2)+3) 2.把运算符移到括号前/后面(移到前面为前缀表达式,反之亦然): ((1-2)+3)→((12)−3)+ 3.删去括号,剩下的即为最终解: ((12)−3)+ → 12−3+ 也可以用上文的“表达式树”做,比较复杂,推荐以上加括号的方法。 图 图的定义:图是由结点的有穷集合 V V和边的集合 E E组成。 其中,为了与树形结构加以区别,在图结构中常常将结点称为顶点/节点,边是顶点的有序偶对,若两个顶点之间存在一条边,就表示这两个顶点具有相邻关系。(边(Edge):节点之间的连线) 有向图和无向图:如图中一个是有向图(a),即每条边都有方向,另一个是无向图(b),即每条边都没有方向。 13333.png 完全图:任意两点都有边相连。 简单路径:两点之间通过不重复的边相连。 连通图:任意两点都可以直接/间接到达,注意区别于完全图,完全图属于连通图, 连通图不一定属于完全图。 有向完全图:若有向图中有 n n个顶点,则最多有 n ( n − 1 ) n(n−1)条边(即图中任意两个顶点都有两条边相连) ,我们又将具有 n ( n − 1 ) n(n−1)条边的有向图称作有向完全图。 无向完全图:若无向图中有 n n个顶点,则最多有 n ( n − 1 ) / 2 n(n−1)/2条边(即任意两个顶点之间都有一条边), 我们又将具有 n ( n − 1 ) / 2 n(n−1)/2条边的无向图称作无向完全图。 顶点的度:与顶点 v v相关的边的条数称作顶点 v v的度。图(b)中,顶点D的度为2。 顶点的入度和出度:在有向图中指向顶点 v v的边的条数称作顶点 v v的入度,由顶点 v v发出的边的条数称作顶点 v v的出度。如图(a),顶点C的入度为0出度为2,顶点D的入度为1出度为1。 图的遍历 图的深度优先搜索遍历:它的基本思想是首先访问出发点 v v,并将其标记为己访问过;然后选取与 v v邻接的未被访问的任意一个顶点 w w,访问之;再选取与 w w邻接的未被访问的任一顶点访问之,重复进行如上步骤。 当一个顶点所有的邻接顶点都被访问过时,则依次退回到最近被访问过的顶点,若该顶点还有其他邻接顶点未被访问,则从这些未被访问的顶点中取一个重复上述的访问过程,直至图中所顶点都被访问过为止。 13333.png 深度优先搜索序列是:ADECB 图的广度优先搜索遍历: 它的基本思想是首先访问起始顶点v,然后选取与 v v邻接的全部顶点 w 1 . . . . . . w n w 1 ......w n 进行访问,再依次访问 w 1 … … w n w 1 ……w n 邻接的全部顶点(己经访问过的除外),依次类推,直到所顶点都被访问过为止。例如下图为一个图的广度优先搜索遍历过程。 13333.png 广搜序列为:ABCDEFGHI 排列组合 1.加法原理(分类计数原理): 完成一件事,有 n n类办法,如果在第1类办法中有 m 1 m 1 种不同的方法,在第2类办法中有 m 2 m 2 种不同的方法,…,在第 n n类办法中有 m n m n 种不同的方法,那么完成这件事共有: N = m 1 , + m 2 . . . m n N=m 1 ,+m 2 ...m n 种不同的方法。 2.乘法原理(分步计数原理): 完成一件事,需要分成 n n个步骤,如果做第1步 m 1 m 1 有种不同的方法,做第2步有 m 2 m 2 种不同的方法,……,做第n步有 m n m n 种不同的方法,那么完成这件事共有:N= m 1 × m 2 . . . . m n m 1 ×m 2 ....m n 种不同的方法。 两个原理的区别:一个与分类有关,一个与分步有关;加法原理是“分类完成”,乘法原理是“分步完成”。 3.排列 (1)排列:从 n n个不同的元素中取出 m ( m ≤ n ) m(m≤n)个元素,按照一定的顺序排成一列,叫做从 n n个不同的元素中取出 m m个元素的一个排列。相同的排列是指元素相同且顺序相同。 (2)排列数:从 n n个不同的元素中取出 m ( m ≤ n ) m(m≤n)个元素的所有排列的个数,叫做从 n n个不同的元素中取出 m m个元素的排列数,用符号 A n m A n m 表示。 排列数公式: A n m = n ( n − 1 ) ( n − 1 ) . . . ( n − m + 1 ) = n ! ( n − m ) ! A n m =n(n−1)(n−1)...(n−m+1)= (n−m)! n! (3)全排列:把 n n个不同的元素全部取出(从 n n个不同的元素中取出 n n个元素),按照一定的顺序排成一列,叫做 n n个不同的元素的一个全排列,全排列的个数叫做 n n个元素的全排列数,用符号 A n n A n n 表示。此时, A n n = n ( n − 1 ) ( n − 2 ) … … 3 ⋅ 2 ⋅ 1 = n ! A n n =n(n−1)(n−2)……3⋅2⋅1=n! n ! n!表示正整数 1 1到 n n的连乘,叫做 n n的阶乘。 规定: 0 ! = 1 0!=1。 4.组合 1.组合:从 n n个不同的元素中取出 m ( m ≤ n ) m(m≤n)个元素并成一组,叫做从 n n个不同的元素中取出 m m个元素的一个组合。即不关心被选元素的顺序。记为 C n m C n m 2.公式 C n m = A n m m ! = m ! m ! ( n − m ) ! C n m = m! A n m = m!(n−m)! m! 3.组合数的性质 C n m = C n n − m C n m =C n n−m ,规定 C m 0 = 1 C m 0 =1 C n m = C n − 1 m − 1 + C n − 1 m C n m =C n−1 m−1 +C n−1 m 5.排列组合解题技巧 先选后排:先将元素选出来,再进行排列,非常有效的降低问题的复杂度。 特殊优先:特殊元素,优先处理;特殊位置,优先考虑。 分排用直排: n n个元素,从中选出 m m个,将这 m m个元素排成若干排。分排问题的排列可以看做一排,避免考虑了复杂的前后排列,简化了问题。 分类法:当计算符合条件的数目比计算不符合条件数目简单时,将问题分成若干类,逐个求解,与“排除法”相对。 排除法:当计算符合条件的数目比计算不符合条件数目复杂时,简称正难则反。排除不符合要求的,剩下的就是符合题目要求的。与“分类法”相对。 捆绑法: n n个不同元素排成一列,要求 m m个元素必须相邻。可以特殊优先,把 m m个元素捆绑在一块单独处理。 S = A n − m + 1 n − m + 1 × A m m S=A n−m+1 n−m+1 ×A m m 插空法: n n个不同元素排成一列,要求 m m个元素不能相邻。先把不用特殊处理的元素进行排列,再把甲乙进行插空。 S = A n − m n − m × C n − m + 1 m S=A n−m n−m ×C n−m+1 m 隔板法/插板法:将 n n个相同元素分成 m m组,每组至少有一个元素。相当于把 m − 1 m−1个隔板插到 n n个元素形成的 n − 1 n−1个空隙里。 S = C n − 1 m − 1 S=C n−1 m−1 定序: n n个元素的全排列中有 m m个元素必须定序排列,这 m m个元素相邻或不相邻不受限制。 S = A n n A m m S= A m m A n n 复杂度 一个问题有很多种不同的算法,如何评价一个算法的好坏呢?这就需要时间复杂度和空间复杂度来衡量了。 定义 渐进时间复杂度,用符号O表示。一个算法里语句的执行次数可以用一个式子表示,取这个式子的最高次项且忽略系数表示该算法的时间复杂度。 例如,一个程序的语句执行次数为 2 n + 3 n 2 + 9 + 8 n 2n+3n 2 +9+8n,则该算法的时间复杂度为O(n^2)。 示例 for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) cin >> a[i][j]; 本代码中,cin >> a[i][j] 执行了 n 2 n 2 次,所以时间复杂度为O ( n 2 ) (n 2 )。 for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) cin >> a[i][j]; for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) cin >> b[i][j]; 本代码中,cin >> a[i][j] 执行了 n 2 n 2 次,cin >> b[i][j] 也执行了 n 2 n 2 次,忽略系数,时间复杂度还是 n 2 n 2 。 for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) cin >> a[i][j]; for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) for(int k = 1; k <= n; k++) cin >> b[i][j]; 本代码中,cin >> a[i][j] 执行了 n 2 n 2 次,cin >> b[i][j] 执行了 n 3 n 3 次,取最高次项,时间复杂度是O ( n 3 ) (n 3 )。 非递归程序的时间复杂度的计算 非递归程序的时间复杂度计算一般都比较简单,直接数循环。大多数算法都适用于此,但是也有例外,例如二分等,需要特别留心。 递归程序 假设某算法的计算时间表示为递归式: 对于 T(n) = T(n-1) + T(n-2) + 1,其时间复杂度是O ( 2 n ) (2 n )
- 1
Information
- ID
- 5
- Time
- 1000ms
- Memory
- 256MiB
- Difficulty
- 10
- Tags
- # Submissions
- 5
- Accepted
- 2
- Uploaded By