程序=数据结构+算法
越工作越发现业务代码是很容易的,框架也是旧瓶装新水,大体差不多。
那么好的代码的区分在于算法,性能这些的差距。而数据结构是算法实现的基础,算法总是要依赖某种数据结构来实现的。
好久没有仔细看数据结构了,最近被频繁的算法,奈何我数据结构基础不好。决定好好复习一遍,并输出一份文档。
一.数据结构
1.什么是数据结构?
数据结构是计算机中对数据的一种存储和组织方式,同时也泛指相互之间存在一种或多种关系的数据的集合。
通俗说就是数据和数据之间的关系。
2.数据结构中的基本概念
- 数据(Data):数据是信息的载体,其能够被计算机识别、存储和加工处理,是计算机程序加工的“原材料”。数据包括的类型非常广,如基本的整数、字符、字符串、实数等,此外,图像和声音也都可以认为是一种数据。
- 数据元素(Data Element):数据元素是数据的基本单位,也称为元素、结点、顶点、记录等。一般来说,一个数据元素可以由若干数据项组成,数据项是具有独立含义的最小标识单位。数据项也可以称为字段、域、属性等。
- 数据结构(Data Structure): 数据结构指的是数据之间的相互关系,即数据的组织形式。
3.数据的存储结构
数据的存储结构主要是顺序存储和链式存储两种。
- 顺序存储结构
顺序存储结构是把数据元素存放在地址连续的存储单元里,其数据间的逻辑关系和物理关系是一致的。
顺序存储结构适用于频繁查询时使用。
数组是顺序存储结构的典型代表。
- 链式存储结构
链式存储结构中,相邻数据元素可随意存放,但所占存储空间分两部分,一部分存放结点值,另一部分存放表示结点间关系的指针。
链式存储结构适用于在较频繁地插入、删除、更新元素时使用。
链表是链式存储结构的典型代表。
- 索引存储方式
索引存储方式是采用附加的索引表的方式来存储结点信息的一种存储方式。索引表由若干索引项组成。索引存储方式中索引项的一般形式为:(关键字、地址)。其中关键字是能够唯一标识一个结点的数据项。
索引存储方式i可以细分为两类:
稠密索引:这种方式中每个结点在索引表中都有一个索引项,其中索引项的地址指示结点所在的存储位置。
稀疏索引:这种方式中一组结点在索引表中只对应一个索引项。其中索引项的地址指示一组结点的起始存储位置。
- 散列存储方式
散列存储方式是根据结点的关键字直接计算出该结点的存储地址的一种存储方式。
4.数据的逻辑结构
数据和数据本身之间的关系。
- 集合结构
集合结构中的数据元素同属于一个集合,他们之间是并列的关系,除此之外没有其他的关系。
- 线性结构
线性结构中的元素存在一对一的相互关系。
如一维数组,队列,栈。
- 树形结构
树形结构中的元素存在一对多的相互关系。
- 图形结构
图形结构中的元素是一种多对多的关系。
5.常用的数据结构
常用的数据结构有以下八种:
(1)数组(Array):数组是一种聚合数据类型,是将具有相同类型的若干变量有序地组织在一起的集合。数组可以说是最基本的数据结构。按照数组的类型,可以分为整形数组、字符型数组、浮点型数组、对象数组等。数组还可以有一维、二维及多维等表现形式。
(2)链表(Linked List):链表是一种数据元素按照链式存储结构进行存储的数据结构,这种存储结构在物理上具有非连续的特点。链表由一系列数据结点构成,每个数据结点包括数据域和引用域两部分。其中,引用域保存了数据结构中下一个元素存放的地址。
(3)栈(Stack):栈是一种特殊的线性表,其只能在一个表的一个固定端进行数据结点的插入和删除操作。栈按照后进先出的原则来存储数据。栈中没有数据时,称为空栈。
(4)队列(Queue):队列和栈类似,也是一种特殊的线性表。和栈不同的是,队列只允许在表的一端进行插入,而在另一端进行删除操作。进行插入操作的一端称为队尾,进行删除操作的一端称为队头。队列中没有元素时,称为空队列。
(5)树(Tree):树是典型的非线性结构,其是包含n个结点的有穷集合K。在树结构中,有且仅有一个根结点,该结点没有前驱结点。在树结构中的其他结点都有且仅有一个前驱结点,而且可以有m个后继结点,m>=0.
(6)图(Graph):图是另外一种非线性数据结构。在图结构中,数据结点一般称为顶点,而边是顶点的有序偶对。如果两个顶点之间存在一条边,那么就表示这两个顶点具有相邻关系。
(7)堆(Heap):堆是一种特殊的树型数据结构,一般讨论的堆都是二叉堆。堆的特点是其根结点的值是多有结点中最小的或者最大的,并且根结点的两个子树也是一个堆结构。
(8)散列表(Hash):散列表源自于散列函数(hash function),其思想是如果在结构中存在关键字和T相等的记录,那么必定在F(T)的存储位置可以找到该记录,这样就不用进行比较而直接去的所查记录。
二.算法
1.定义
算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表这用系统的方法描述解决问题的策略机制。
2.算法的特性
- 输入:算法可以有0到多个输入。
- 输出:算法至少要有一个输出。
- 有穷性:算法在有限的步骤可以执行出结果。
- 确定性:结果的确定性,一个输入对应一个输出。
- 可行性:算法能够解决实际问题。
3.算法的基本要求
- 正确性:完成的算法要能正确的解决问题。
- 可读性:有一定的可读性,让其他人能看懂,便于阅读、理解和交流。
- 健壮性:当输入数据不合法时,也能做出相关处理。
- 时间复杂度:算法的执行时间,执行时间短的效率高,时间长的效率低。
- 空间复杂度:程序保存所需要的存储空间,即程序的大小;算法在执行过程中需要消耗的存储空间。
来看一道最简单的算法:
package cn.kimtian.array.one;
/**
* 求从1加到指定数字的和
* @author kimtian
**/
public class AddOneToNums {
public static void main(String[] args) {
long total = 0;
long end = 999999999;
Long a = System.currentTimeMillis();
/**
* 第一种方式:循环从1加到100
**/
for (long i = 1; i <= end; i++) {
total += i;
}
Long b = System.currentTimeMillis();
System.out.println("第一种方式结果:"+total+",耗时:"+(b-a));
/**
* 第二种方式:循环从1加到100
**/
long total2 = 0;
Long c = System.currentTimeMillis();
total2 = (end + 1) / 2 * end;
Long d = System.currentTimeMillis();
System.out.println("第二种方式结果:"+total2+",耗时:"+(d-c));
}
}
执行结果可以发现,第二种方式执行时间更短。

这就是两种解决方式时间复杂度的不同。
不过时间复杂度和空间复杂度是相辅相成的,不能过于偏重一个而忽略另一个。有的算法执行时间很短,却是以消耗大量内存作为前提。所以说没有最好的算法,只有最合适的算法。
附:
常见的时间复杂度
- 常数阶O(1)
- 对数阶O(log2n)
- 线性阶O(n)
- 线性对数阶O(nlog2n)
- 平方阶O(n^2)
- 立方阶O(n^3)
- K次方阶O(n^k)
- 指数阶O(2^n)
随着规模n的不断增大,上述时间复杂度不断增大,算法的执行效率越低。
本文深入探讨了数据结构与算法的基础知识,详细介绍了数据结构的种类及其存储方式,包括顺序存储、链式存储、索引存储和散列存储。同时,文章还分析了算法的特性与基本要求,通过实例对比了不同算法的时间复杂度。
1460

被折叠的 条评论
为什么被折叠?



