修习此剑法者数不胜数,然能练至大成者寥寥无几。不知阁下可是这万里挑一之人?
本剑法练成前两式,可称“入门之境”,届时阁下算是正式迈进了数据结构的大门。
练成前三式,可称“小成之境”。
练成前四式,可称“过渡之境”,第四式尤为重要,因为这一式不算简单,也算不得最难,不好练啊。这是一个坎,你的能力会经历从初级到高级的过渡。这一式无论对于学习能力还是意志力都是一个考验。阁下可有信心习得此式?
练成前六式,可称“登堂入室”。能学会第六式,那么后面的内容,只要你有足够的意志力,对你而言不是难事。
练成前七式,可称“登峰造极”。学会第七式后,你已经超过了80%的人,然而“行百里者半九十”。越是到最后,越要坚持。
练成第八式,可称“高手之境”。查找一事于你而言便是小菜一碟。此时你已超过了90%的人。
练成第九式,可称“凤毛菱角”。排序一事于你而言便是随随便便。至此,剑法大成!
好,话不多说,开始练剑:
第一式:预备式
在“预备式”中,我们要明确以下几个问题:
1.数据结构在程序设计中的地位:
程序设计=数据结构+算法
2.数据是什么?
一种抽象的类或集合。数据不仅包括整形、实型等数值类型,还包括声音、图像等非数值类型。
3.数据元素是什么?
数据是一种“类”,元素是“实体”,所以数据元素是“某一种类的实体”。比如,在人类中,什么是数据元素呀?当然是人了。在车中,公交车、小轿车是数据元素。在畜类中呢?牛、🐏、🐎、鸡、🐖、🐕等都是数据元素。
4.什么是数据项?
一个数据元素可以由若干个数据项组成。数据项是数据不可分割的最小单位。
比如,人这样的数据元素,有眼睛、耳朵、鼻子、嘴巴、手、脚等数据项。也有姓名、年龄、性别等数据项。具体有哪些数据项,要看你针对的是什么系统了。
5.数据对象是什么?
性质相同的数据元素的集合(简而言之,就是:某一种类性质相同的实体的集合),是数据的子集。比如,张三、李四......具有相同的性质,他们组成的集合人就是一个数据对象。
什么叫性质相同呢?
就是指数据元素具有相同数量和类型的数据项。比如,张三、李四......都有姓名、生日、性别等相同的数据项。
6.什么是数据结构?
不同的数据元素之间不是独立的,而是存在特定的关系,将这些关系称为结构。所以数据结构就是:相互之间存在一种或多种特定关系的数据元素的集合。(首先是数据元素的集合,其次这些数据元素之间存在一种或多种特定关系)
7.数据结构分类:
按照观察角度不同分为:逻辑结构和物理结构。
(1).逻辑结构:
数据对象中数据元素之间的相互关系。(重点是关系哦)
逻辑结构呢,又分为以下四种:
①.集合结构
数据元素除了同属于一个集合外,它们之间没有其他关系。(如图1)
②.线性结构
数据元素之间是一对一的关系。(如图2)
③.树形结构
数据元素之间存在一种一对多的层次关系。(如图3)
④.图形结构
数据元素是多对多的关系。(如图4)
(2).物理结构:
是指数据的逻辑结构在计算机中的存储形式。
共分两类:
①.顺序存储结构:
是把数据元素存放在地址连续的存储单元里,其数据间的逻辑关系和物理关系是一致的(如图5)
②.链式存储结构:
是把数据元素存放在任意的存储单元里,这组存储单元可以是连续的,也可以是不连续的。数据元素的存储关系并不能反映其逻辑关系,因此需要用一个指针存放数据元素的地址,这样通过地址就可以找到相关联数据元素的位置。(如图6)
重点总结:
(如图7)
恭喜你,亲爱的,你已经学会了数据结构剑法的第一式。不过,这还算不得入门,待你习得第二式,便可算是正式入门了。Baby,准备好了吗?出发!
——本文于2024/4/23开始,将持续更新至结束,敬请期待!
第二式:算法
什么是算法?
算法是解决特定问题求解步骤的描述。
1.算法的魅力示例:
既然来学数据结构了,那么想必都起码已经学过一门语言了吧,现在我要求你写一个求“1+2+3+...+100”结果的程序,你会怎么写呢?
我想大多数人会这样写:(我以C语言为例)
int i, sum = 0, n = 100;
for(i = 1; i < = n; i++)
{
sum = sum + i;
}
printf(" %d ", sum);
你是不是这样想的?但这样是不是真的高效呢?
数学家高斯曾这样解决这道题:(如图8)
用C语言实现如下:
int i, sum = 0,n = 100;
sum = (1 + n) * n / 2;
printf("%d", sum);
看来,算法确实很重要啊,好的算法事半功倍,灵活简单又有效。
所以,在学习数据结构的过程中,算法于修习本剑法者而言是不可抛弃的内功之一。
好的,今天2024/4/24,今天有些困了,就先更这么些,本剑法第二式还未结束。
预知后续如何,点赞、关注、收藏,本人将持续更新至结束,敬请期待。
ok,继续:
2.算法的特性:
算法具有五个特性:输入、输出、有穷性、确定性、可行性。
(1).输入、输出:
算法可以没有输入、但不能没有输出,不然这个算法意义何在?你想一下,一个算法我用了你,对我没有一点影响,我用你干啥啊,对不对。
(2).有穷性:
算法不会出现死循环,每一个步骤都可以在可接受的时间内完成。(前者好理解,后者,你想啊,你写个算法我执行100年才执行完,我坟头草都几丈高了,有什么意义呢?)
(3).确定性:
算法的每一个步骤都有确定的意义,不会出现二义性。(不同的条件有不同的执行路径,每个步骤都被精确定义没有歧义)
(4).可行性:
算法的每一步都可以通过执行有限次数完成。
3.对本门中人算法设计的要求:
(1).正确:两个要求——能正确解决特定问题、满足前面提到的算法的5个特性。
(2).可读性强:便于阅读、便于理解、便于交流。能简单就简单,能说大白话就别说文言文。
(3).防出错能力强:对于各种出错有对应的处理措施,输入数据的不合法也可以做出相关处理。
(4).花费时间少:执行1s就解决问题的算法显然比执行1小时才解决问题的算法要高明得多。
(5).存储量低:能少占用存储空间就少占用。
好的,今天就先更这些,明天讲时间复杂度和空间复杂度。
对内容感兴趣的点赞 、收藏+关注。后续将持续更新到结束,敬请期待!
4.时间复杂度
定义:n为问题规模、随着n的增大,语句总的执行次数关于n的增长率就是时间复杂度。
记作:T(n)=O(f(n)),其中T(n)为时间复杂度,f(n)为语句总的执行次数关于n的增长率函数。
如,int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
printf("I love you!");
则,T(n)=O(n)
再如,int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
printf("I love you!");
则,T(n)=O(n^2)
如果你对于上面两题的时间复杂度存在问题,别慌,咱们接着往下走。
前面的T(n)=O(f(n))这种记法,称为大O记法。
当我们求出了大O中的f(n)时,那么时间复杂度也就出来了,怎么推导大O阶呢?
方法如下:
1.逐句分析代码中的基本语句,并将每一句执行次数依次相加。
2.将加法多项式中的常数项全替换为1
3.只保留多项式中的阶数最高项,其他项全部删除。
4.如果保留的阶数最高项不是1,那么去除和这个项相乘的常数,即去掉系数。
经过上面4步得到的便是一个代码运行的时间复杂度。
时间复杂度越小,算法越好。
常用时间复杂度所耗费时间从小到大依次是:
一般没有特别说明时,时间复杂度都是指最坏时间复杂度。(最坏时间复杂度就是执行次数最多的情况,不会再多了。)
5.空间复杂度
问题规模为n、随着n的增大,算法占用的存储空间的大小关于n的增长率就是空间复杂度。
记作S(n)=O(f(n))
那么,空间复杂度怎么计算呢?
若算法执行时需要的辅助空间相对于输入数据量而言是个常数,呢么S(n)=O(1).
那么其他复杂情况,具体怎么算呢?(这个问题呢非必要情况,没那么重要)
本门没有此法,需要诸位道友来发扬光大。