这是我参与8月更文挑战的第26天,活动详情查看: 8月更文挑战
数据结构
在我们日常编程中,我们经常会听到数据结构这样的概念,那这两个名词的概念到底是怎样的呢?
数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。通 常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。 数据结构可以划分为逻辑结构和物理结构,统一逻辑结构下对应不同的存储结构。
逻辑结构
逻辑结构反映的事数据元素之间的逻辑关系,元素之间是以怎样的形式相关关联在一起,与计算机的存储无关,只是逻辑上的概念,逻辑结构包含下面:
集合
将一堆的东西存放在一起,里面的每个称为元素,由一个或多个确定的元素所构成的整体
线性结构
一个有序数据元素的集合,一对一关联,我们比较常见的线性结构:线性表、栈、队列等
树形结构
是数据元素之间存在一对多的属性关系数据结构
图形结构
是数据元素之间存在多对多的属性关系数据结构,在计算机领域用的比较广泛
顺序存储
顺序存储是所有的结点元素存放在一块连续的存储区域中,用存储结点的物理位置来体现结点之间的逻辑关系的存储方法,比较常用的就是数组
链式存储
数据存储不联系,每个节点之间用指针连在一起,通过相连的指针可以查找到整个链存储的数据元素
索引存储
除建立存储元素信息存储之外,附加的根据一些特定信息建立索引来表示元素的地址信息,比较常见的数据库索引,加快查询速度
哈希存储
数据元素存放在一块连续的存储区域中。数据元素的存放位置是通过一个哈希函数计算而得的。哈希函数将数据元素作为自变量,计算得到的函数值是数据元素的存储地址
物理结构
物理结构指的是逻辑结构在计算机存储空间中的具体存放形式,一种逻辑结构可以根据需要表示成多重存储结构,常见的八大存储结构
数组(Array)
数组是用的比较常用,很多数据结构都是根据数组演变而来,存储的时候是连续的,一种线性结构,可以根据下标随机读取,扩容比较难
栈( Stack)
也是线程存储,和数组结构差不多,但是它只允许一段操作,进出只能一端操作,先进后出
队列(Queue)
与栈相试,也是一种顺序存储元素的线性数据结构,队列是一端进一端出,先进先出(FIFO)
链表( LinkedList)
链式存储,每个元素之间包含数据和前后节点指针
树( Tree)
树形结构是一种层级式的数据结构,由顶点(节点)和连接它们的边组成。 树类似于图,但区分树和图的重要特征是树中不存在环路
图(Graph)
图是一组以网络形式相互连接的节点。节点也称为顶点。 一对节点(x,y)称为边(edge),表示顶点x连接到顶点y。边可以包含权重/成本,显示从顶点x到y所需的成本
堆(Heap)
特殊的树,特点是根结点的值是所有结点中最小的或者最大的,且子树也是堆
散列表(Hash)
哈希法(Hashing)是一个用于唯一标识对象并将每个对象存储在一些预先计算的唯一索引(称为“键(key)”)中的过程。因此,对象以键值对的形式存储,这些键值对的集合被称为“字典”。可以使用键搜索每个对象。基于哈希法有很多不同的数据结构,但最常用的数据结构是哈希表
算法
算法个人理解就是采用怎样的方法更有效的处理数据,提高数据运算效率,就像我们读书的时候,针对同一道数学题有不同的解法,每种解法都有各自的优缺点。在算法中是根据时间复杂度及空间复杂度来判定一个算法的好坏。
时间复杂度
时间复杂度是指将结果运算出来后所花取得时间,使用大写O表示 ,时间复杂度可以分为下面的几种:
常数阶O(1)
只进行一次运算就可以得到结果
int i = 1,j=2,x
x=i;i=j;j=x;
线性阶O(n)
需要运行n次计算才可以得到结构,如果常用的for循环
for(int i = 0;i<=x;i++){
}
k次方阶O(n的k次方)
执行次数是数量的k次方,常用的两次for循环
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
}
}
指数阶O(2的n次方)
随着n的表达,运算次数呈指数增长
for(i=1;i<= 2^n;i++){
}
对数阶O(log2n)
执行次数呈对数缩减
for(i=1;i<=n;){
i=2^i;
}
线性对数阶O(nlog2n)
在对数阶的基础上,进行线性n倍乘积
for(i=1;i<=2^n;i++){
for(j=1;j<=n;j++){
}
}
时间复杂度由小到大依次为:Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n2)<...<Ο(nk)<Ο(2n)<Ο(n!)
空间复杂度
与时间复杂度类似,只是从空间角度来判断算法的好坏,比如运算中占用的空间大小。空间复杂度分固定空间和可变空间
- 固定空间主要包括指令空间、常量、简单变量等所占的空间,这部分空间的大小与运算的数据多少无关, 属于静态空间。
- 可变空间:主要包括运行期间动态分配的临时空间,以及递归栈所需的空间等,这部分的空间大小与算法有很大关系
算法思想
分而治之
就是把一个复杂的问题拆分成多个子问题来解决,等到每个子问题解决完成后再将结构合并,大数据中MapReduce就是采用的这种思想,这种思想需要具备下面的特点:
- 问题拆分到一定程度后可以得到很好的解决
- 问题可以进行拆解
- 拆解完成后,每个子解决可以合并在一起得到最终的结果
- 拆解的子问题要互相独立,互相之间存在依赖关系
动态规划
动态规划与分而治之类似,也是将问题拆解为若干个子问题,按照顺序求解子问题,待子问题解决后,进入下一阶段,根据上一阶段的结果来动态规划下一阶段的执行,依次解决各个子问题,最终得到问题的解法,动态规划算法同样有一定的适用性 场景要求:
- 最优化解:拆解后的子阶段具备最优化解,且该最优化解与追踪答案方向一致
- 流程向前,无后效性:上一阶段的解决方案一旦确定,状态就确定,只会影响下一步,而不会反向影响
- 阶段关联:上下阶段不是独立的,上一阶段会对下一阶段的行动提供决策性指导。这不是必须的,但是如果具备该特征,动态规划算法的意义才能更大的得到体现
贪心算法
同样对问题进行拆解,但是每一步的解决都从当前的问题点出发,获得子问题的最优解法,然后将每个子问题的全部最优解合在一起就做出是当前最好的选择,但是这种算法从整体看,得出的解并不一定是最优解。
回溯算法
类似枚举的做法,根据问题的可能性,列举出可能的解法方法,然后一步步寻找问题的解,就像走迷宫一样,一步步去尝试,当发现不满足时,就返回尝试别的路径。
分支限界
与回溯法类似,也是一种在空间上枚举寻找最优解的方式。但是回溯法策略为深度优先。分支法为广度优先。分支 法一般找到所有相邻结点,先采取淘汰策略,抛弃不满足约束条件的结点,其余结点加入活结点表。然后从存活表 中选择一个结点作为下一个操作对象。