重学数据结构笔记
大学上数据结构课都逃了,后来发现其重要,期间又自己抱起书学了一遍,因为当时懒,自学的成果也不大,如今工作有一年了,也写过几个项目越来越感觉数据结构对个人思想的重要,如今趁裸辞的空窗期,好好恶补下,顺便写个笔记总结下。
1,数据结构,是相互之间存在一种或多种关系的数据元素的集合
从不同角度讨论,有不同的分类
物理结构:顺序存储结构,链式存储结构
逻辑结构:线性结构,集合结构,树形结构,图形结构
2.数据类型,是指一组性质相同的值得类型的集合以及在此集合上的一些操作
抽象数据类型:是只一个数学模型及定义在该模型上的一组操作(像java的类?)
3.算法,是解决特定问题求解步骤的描述,在计算机中表先为指令的有限序列。并且每条指令表示一个或多个操作
五个特性:输入输出、有穷性、确定性、可行性
好的算法设计应该具有,正确定,可读性,健壮性(例:当输入不合法时,不报莫名奇妙的错误),高效率,低存储量(用最短的是时间办最大的事)
算法效率统计方法:
事后统计法(笨法,外部因素太多,舍弃)
事前分析估算方法:例如:分析执行次数、执行时间
A算法:2n+3 ;B算法:3n+1 哪个快?答:不一定 n的值不同 情况不同
由上引出 函数的渐近增长:给定两个函数F(n)和G(n),如果存在一个整数N,使得对于所有的n>N,F(n)总是比G(n)大,那么我们说F(n)的增长渐近快于G
+1 +3并不影响算法最终变化,忽略常数,最高次项的常数也同理并不重要
最高次项指数大的增长的越快,判断一个算法的效率时,其他项可以忽略,只要关心最高阶项的阶数
基本可以分析出:某个算法随着n越来越大,可能会越来越优于另一算法,这其实就是通过时间复杂度估算算法时间效率
时间复杂度:T(n) = O(f(n)) 随着n的增大T(n)增长越慢的算法为最优算法
简单推到时间复杂度方法:1.用常数1取代所有加法常数。2,在1的基础上保留最高阶数。3,除去最高阶数的乘数 例:常数阶O(1)(只能是1不能是其他数字) 线性阶O(N) 平方阶O(N2) 对数阶 立方阶,指数阶还有其他....
常用的时间复杂度所耗费的时间顺序:O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n3)<O(2n)<O(n!)<O(nn)
最坏时间复杂度(默认),平均时间复杂度
空间复杂度:S(n) = O(f(n)) f(n)为语句关于n所占存储空间的函数
3.线性表,零个或多个元素的有限序列(因为是序列 所以是有序的)
前驱元素 后继元素
一维数组实现线性表,线性表的长度小于等于数组的长度
线性表的顺序存储结构,在存和读数据时时间复杂度都是O(1),删除和增加时是O(n)
线性表顺序存储结构 优点:不用为表示表中数据关系而额外增加空间,可快速存取;缺点:增删需要移动大量数据,当线性表长度变化较大时无法确定存储空间,造成存储空间碎片
线性表链式存储结构 头结点 指针域 数据域
对于插入或删除频繁的操作,单链表的效率优势明显
创建单链表 头插法 尾插法
静态链表,用数组来描述的链表叫静态链表 ,其对第一个元素和最后一个元素特殊处理,不存数据。通常把未使用的数组元素成为备用链表,而第一个元素的cur就存放备用链表的第一个节点的下标,
最后一个元素cur存放第一个有数据节点的下标。
静态链表的插入与删除只是修改数组cur游标,没有解决连续分配带来的表长问题,失去了顺序结构随机存取的特性,静态链表只是提供了给没有指针的高级语言实现单链表的方法
循环链表,将单链表尾节点的指针由空变为指向第一个节点
用尾指针来表示循环链表,可以最快找出链表的头尾O(1) 用头指针来表示循环链表访问尾部需要O(n)
双向链表,在单链表中每个节点再设置一个指向前驱的指针,就是双向链表
单链表获取下一节点时间复杂度是O(1) 获取上一节点是O(n)因为需要重新遍历才能获取到上一节点,为了解决此问题出现了双向链表
由于双向链表多了个指针域,所以内存增加了,但提高了时间性能,空间复杂度换时间复杂度
--------------------------------线性表----------------------------------
----------顺序存储结构---------------------链式存储结构--------------
---------------------------------单链表-静态链表-双向链表-循环链表-