数据结构的总结思考

486 阅读5分钟

数据结构的分类

  • 按照结构分线性和非线性的

  • 线性结构的例如线性表,链表,数组,栈,队列等

  • 非线性的比如树,图,集合,Map等

  • 他们的作用:都是为了更好方便存取操作数据,在这里可以把算法和逻辑的执行过程看作Cpu,数据看作内存,数据结构为的是更好更快的让程序与数据交互。

  • 例如ArrayList,HashMap,TreeMap,LinkedList,Set,他们在概念上都有相似的接口,可以概括为元素集合的增删改查,移动,赋值。在使用效率上例如数组型结构,有元素下标的概念,存取元素依靠其int 类型的index,内部实现在空间上紧密的,也因此他的查改效率很高,复杂度为O(1),但是增删,移动,复杂度为o(n),其实按照System.Copy()实现,依然得保证类型相同和空间不灵活的局限

  • 链表,他的实现是将每个元素包装成带有同类型引用的Node,这个引用具有指向性,用来链接next,preious,他舍弃了index和Size的概念,元素之间在空间上不必要连续,增删改的效率很高为o(1),查的效率很低,因为舍弃了index,查找只能依赖元素之间的equal,时间复杂度为o(n),而且实际应用中,想要增删改,首先就得依照元素的id等找到这个元素,除非持有这个元素的引用,那这样整体的外部引用大大增加,会引起内存泄漏等问题。所以链表思想一般和其他数据结构相结合。

  • Map,在这个结构中,引入了Key-Value的概念,即查找用Key,数据存Value,Key作为查找类型不再局限于基本类型,Key-Value更是一种映射的关系,找到Key就找到Value了,找到Value也就找到Key了,Key是唯一的,Value却又可能是重复的,空的。

  • 常见的如hashMap,他的核心思想就是优化通过Key元素找到Value元素的效率,让时间复杂度由o(n)降为o(1),通查元素查找像链表是用元素之间equal来从头到尾依次判断,而数组查找是用index一步到位,那么这中间如果能让元素本身“代表”其在数据结构中的位置,通过Key元素算出index,这样就不用equal操作了,这时又进入了hashCode()方法,具体实现是,将Key内成员变量展开为基本类型,然后对基本类型作算术运算(基本类型可以转换成整型),x31+1,最后得出一个很长的数,这个数可以认为是独一无二的,之后通过高位取模运算(按照hashCode&Size位运算,就是hashCode除以数组的Size),得到一个小于Size的余数c,c就是Key在数组中的index,这样就实现了通过Key元素得到Key元素位置,这是再将Key-Value打包成Node,存在这个数组中,这个数组的元素类型就是Node,假如没有hashCode冲突,假如没有触发扩容,HashMap其实就是一个依靠元素生成index的数组。

  • HashMap的其他部分:如果发生hashCode冲突,也就是说两个不同的Key的hashCode,按照&Size位运算,得到的index相同,又不能把数组中index位放两个Node,怎么办,那就扩展Node,引入Node.next,将此index内所有hashCode冲突的Node,组合成链表,数组加链表的形式,形成了一个二维的Map,HashMap的作用,在于快速找到同一特征的子链表,如果幸运的话,头结点就是结果。增删改查效率兼备,优秀。

  • 二叉树或者说TreeMap:上述的HashMap,链表,数组,他们都不具备自排序的功能,即在增删改移动过程中,保持数据结构的有序性,假如我想顺序输出集合,亦或是我存取的元素,有大小之分,具备顺序性质,假如我用数组顺序输出,保持顺序,还需要内部排序,这样相当于隐形持有了另外一个有序数组,链表若要保持顺序,那增删改的时间复杂度就变成了o(n),HashMap是由hasCode映射的index,保持顺序,依然和数组一样,内部排序,这些数据结构都不能实现自排序功能。 *二叉树:一个有向性的分支型链表,Node.next被扩展成Node.right,Node.left,这样就可以在增删改过程中,比较node,node.right,node.left,三者的顺序关系,依次递归,生成一颗有序二叉树,同时在元素的查询中,通过其大小和二叉树的特性,将时间复杂度降为olog(n),增删改时间复杂度依然为o(1),同时保持数据结构有序,非常优秀。

*算法的实现,其实更多依然对数据结构的操作,数组的反转,排序,查找,链表的反转,验证有无环,二叉树的BFS,DFS,反转,HashMap的记录特性,栈,队列为了记录增删改的顺序信息等等。

以上就是我对算法和数据结构的比较浅显的了解,之后再补充....