【数据结构】简介
【数据结构】简介
- 前言
- 前置数学知识
- 指数
- 对数十大公式
- 级数
- Π\PiΠ运算
- 算法
- 数据结构
- 数组
- 栈
- 队列
- 链表
- 树结构
- 图
- 堆
- 散列表(哈希表)
- 信息学奥赛大纲中的数据结构考点
- 入门级
- 提高级
前言
计算机领域有句著名的话:“算法+数据结构=程序”,这是瑞士计算机科学家兼Pascal
之父尼古拉斯·沃斯的名言(遗憾的是,这位编程领域的祖师爷在2024年1月1日
逝世),是所有程序设计的基础。它简洁明了地概括了程序设计中的两个核心部分:算法和数据结构。计算机中的算法与数据结构密切相关,算法依赖于数据结构,而数据结构也关系到算法的效率。
前置数学知识
同学们首先要掌握一些必要的数学知识
指数
即幂运算,需要同学们掌握幂运算的常用公式
- xAxB=XA+Bx^Ax^B=X^{A+B}xAxB=XA+B
- xAxB=XA−B\frac{x^A}{x^B}=X^{A-B}xBxA=XA−B
- (xA)B=XAB(x^A)^B=X^{AB}(xA)B=XAB
对数十大公式
这是高中数学课才会学习到的知识,没学过的同学可以简单地看做是求用于幂运算的幂的运算,同样也要掌握一些常用公式:
- 指数互化: x=logaN<=>ax=N(a>0,a≠1,N>0)x=\log_a{N}<=>a^x=N(a>0,a\neq1,N>0)x=logaN<=>ax=N(a>0,a=1,N>0)
- 两个特殊值:
- loga1=0\log_a{1}=0loga1=0
- logaa=1\log_a{a}=1logaa=1
- 两个基本转换:
- logaab=b\log_a{a^b}=blogaab=b
- alogaN=Na^{\log_a{N}}=NalogaN=N
- 加法: logaM+logaN=logaMN\log_a{M}+\log_a{N}=\log_a{MN}logaM+logaN=logaMN
- 减法: logaM−logaN=logaMN\log_a{M}-\log_a{N}=\log_a{\frac{M}{N}}logaM−logaN=logaNM
- 数乘: nlogaM=logaMn(n∈IR)n\log_a{M}=\log_a{M^n}(n\in{IR})nlogaM=logaMn(n∈IR)
- 换底公式: logaN=logbNlogba(b>0,且b≠1)\log_a{N}=\frac{\log_b{N}}{\log_b{a}}(b>0,且b\neq1)logaN=logbalogbN(b>0,且b=1)
- 底数真数皆变: logabMN=NblogaM(b≠0,n∈IR)\log_{a^b}{M^N}=\frac{N}{b}\log_a{M}(b\neq0,n\in{IR})logabMN=bNlogaM(b=0,n∈IR)
- 倒数: logab⋅logba=1\log_a{b} \cdot \log_b{a}=1logab⋅logba=1
- 连乘: logab⋅logbc=logac\log_a{b} \cdot \log_b{c} = \log_a{c}logab⋅logbc=logac
级数
将数列各项相加所得的和,就是级数。在高中数学课上会学到等差数列和等比数列的求和公式,即下图:
- {ana_nan}是等差数列
- 定义: an−an−1=da_n-a_{n-1} = dan−an−1=d
- 通项:
- an=am+(n−m)da_n=a_m+(n-m)dan=am+(n−m)d
- an=a1+(n−1)da_n=a_1+(n-1)dan=a1+(n−1)d
- 若m+n=p+qm+n=p+qm+n=p+q,则an+am=ap+aqa_n+a_m=a_p+a_qan+am=ap+aq
- 特殊情况:若m+n=2pm+n=2pm+n=2p,则an+am=2apa_n+a_m=2a_pan+am=2ap,apa_pap称为ama_mam与ana_nan的等差中项
- Sn=n(a1+an)2=d2n2+(a1−d2)nS_n=\frac{n(a_1+a_n)}{2}=\frac{d}{2}n^2+(a_1-\frac{d}{2})nSn=2n(a1+an)=2dn2+(a1−2d)n
- {ana_nan}是等比数列
- anan−1=q\frac{a_n}{a_{n-1}}=qan−1an=q
- 通项:
- an=am⋅qn−ma_n=a_m \cdot q^{n-m}an=am⋅qn−m
- an=a1⋅qn−1a_n=a_1 \cdot q^{n-1}an=a1⋅qn−1
- 公比: qn−m=anamq^{n-m}=\frac{a_n}{a_m}qn−m=aman
- 若m+n=p+qm+n=p+qm+n=p+q,则anam=apaqa_na_m=a_pa_qanam=apaq
- 特殊情况: 若m+n=2pm+n=2pm+n=2p,则anam=ap2a_na_m=a_p^2anam=ap2,apa_pap称为ama_mam与ana_nan的等比中项
- Sn=a1−anq1−q=a1(1−qn)1−qS_n=\frac{a_1-a_nq}{1-q}=\frac{a_1(1-q^n)}{1-q}Sn=1−qa1−anq=1−qa1(1−qn)
大家在刷题找题解的过程中,经常有发现大神们会用∑来表示前n项和,这就是级数的表示形式。例如∑i=1Ni=1+2+3+⋯+N\sum_{i=1}^Ni=1+2+3+\cdots+N∑i=1Ni=1+2+3+⋯+N。因此我们需要知道级数的表示方法及其含义,从而至少可以看懂大神们的题解。
Π\PiΠ运算
这里的Π\PiΠ,是π\piπ的大写,在数学中表示“求乘积”,即将求数列的前n
项的乘积。例如:Πi=1N=1×2×3×⋯×N=N!\Pi_{i=1}^N=1 \times 2 \times 3 \times \cdots \times N=N!Πi=1N=1×2×3×⋯×N=N!,同样至少要理解这个运算符的含义。
算法
- 在学习数据结构之前,同学们应该已经在
C++
基础课程中学习到了枚举法、递推和递归法、贪心算法、二分查找、动态规划等基础类算法了。 - 其实只要题目中对程序设计的要求能给足内存和时间,这些算法足以解决大部分的问题。但是重点就在于限制了内存和时间,需要大家想办法去优化算法和数据结构,让程序高效地计算结果。
- 例如求
1~10000
所有正整数的和,相信初学循环结构的同学也能写出答案;
int sum=0;
for(int i=1;i<=10000;i++){sum += i;
}
但是这个程序进行了10000
次加法才算出了结果。如果用等差数列前n
项和公式呢?
float sum = (1+10000)*10000/2;
- 一次表达式的计算就能直接得出答案。
- 这时候有同学可能会问了:我们写程序不就是想充分利用计算机能高效地执行重复事情的能力吗?为什么还让我们用公式来求呢?
- 其实,真正到了
CSP-S
的复赛,甚至后续的NOIP
、省选、NOI
等,我们就会发现,像上面这样的求和只是算法中的一小步,如果这一小步就需要占用10000
个运算量,那么程序肯定会超时。 - 众所周知,大部分题目的时间限制都在
1s
,而在CCF
为奥赛设置的标准计算机配置下,1s
内能进行的运算数量大约在10^7~10^8
之间,即1
千万到1
亿次之间,为了保险起见运算数尽量不能超过1
千万以免超时。 - 因此我们对于算法内部的一些计算,能推导出数学公式的尽量用数学公式来计算,节约运算数给更重要的算法步骤。
数据结构
- 在计算机科学中,数据结构是一种数据组织、管理和存储的格式。
- 在解决一些问题时,如果能将一些相关联的数据集中在一起形成新的数据集合,将集合作为一个整体被访问或处理,就能大大提高程序的运行效率。
- 根据数据的逻辑结构,数据结构大致可以分为4类:
- 集合:集合中的元素除了同属于一个集合外,没有别的关系;
- 线性结构:数据元素之间存在一对一的相互关系;
- 树结构:数据元素之间存在一对多的相互关系;
- 图结构:数据元素之间存在多对多的相互关系;
- 根据数据的存储结构,数据结构又可以分为顺序存储、链式存储、索引存储和哈希存储等。
- 我们在信息学奥赛中学习的数据结构更多地偏向于逻辑结构,同时也会简单涉及到一些存储结构的知识。
- 会学习到的数据结构具体有以下几个
数组
- 其实数组也是一种线性结构,一般用来存储相同类型的数据,可以通过数组名和索引(即下标)来访问和更新数组。数组中的元素存储是按照先后顺序进行的,即顺序存储。
- 在数组中查找一个元素的时间复杂度为
O(1)
,即直接通过索引访问;但是删除一个元素的时间复杂度为O(n)
,因为在删除后,还需要将后续元素都向前“走”一格。
栈
栈是一种特殊的线性表,只能在线性表的一端进行插入和删除等操作。栈是按照先进后出的原则存储数据。
队列
- 队列和栈一样,也是一种线性表,其限制是只能在一段插入,另一端删除,是按照先进先出的原则存储数据。
- 栈和队列在
C++
的STL
库中都有模版可供使用。
链表
- 链表是将元素按照链式存储的结构存储的线性表,但是在物理上具有非连续的特点。链表的每个节点都包含了本节点的数据和指向下一节点的指针。由于是通过指针来访问下一元素的,其灵活性更高。与数组相比,链表在修改和删除元素的速度更快,时间复杂度为
O(1)
,但是牺牲了查找元素的速度,时间复杂度为O(n)
。 - 那么有没有结合了数组与链表各自优点的数据结构呢?有知道的同学可以在评论区留言哦~
树结构
树是有n(n>=0)
个节点组成的有限集合,其各节点的关系犹如一棵树,将各个节点根据不同的层级关系进行排列。我们常使用的树其实是一颗“倒挂的树”,因为其根朝上,叶子朝下。
图
- 图结构是由一组节点和节点间的连线构成的数据结构。顶点通常用圆圈来表示,圆圈间的连线被称为边。根据边是否具有方向,图又可以分为有向图和无向图。
- 事实上,树结构可以看做是一类特殊的图结构,因此有部分的概念与算法其实是相通的。
堆
堆其实是一种特殊的树结构,一般用到的堆都是二叉堆。堆的特点是根结点的值是所有结点中最小的或者最大的,并且根结点的两个子树也是一个堆结构。
散列表(哈希表)
散列表是根据键(key)
和值(value)
直接进行访问的数据结构,其实现原理类似数学课上函数的“映射”知识。
信息学奥赛大纲中的数据结构考点
全国青少年信息学奥林匹克系列竞赛大纲中分别对入门级、提高级和NOI级的数据结构掌握进行了要求。
入门级
可以看出入门级对数据结构的考点还是以概念为主,在实际的CSP-J
比赛中,数据结构的知识也更多的出现在选择题和复赛的第3
、4
题上。
提高级
- 提高级的大纲对数据结构的要求明显提高了很多。从难度等级最低
5
的稀疏图等到难度等级8
的平衡树,加上算法要求中给出了十几个图论算法,这就要求学生在升上初三、最晚高中后,对基础算法应该是学习完毕的,从而将学习的重心放在数据结构上,特别是图和树等结构的代码表示上。 NOI
级的大纲就暂不展示了,其中的知识点难度系数都在8~10
之间,按照大纲中的分类,属于最难一档的。能够通过省选进入NOI
的学生,相信除了汗水与努力之外,离不开他们在程序和算法设计上的天赋。
完整版的《全国青少年信息学奥林匹克系列竞赛大纲》,可以留言获取。