平时学习java遇到的数据结构有:数组,链表,二叉树(红黑树),哈希表(数组+链表),栈,队列。我们平时最常用的集合也是在这些的基础上进行数据的读写。
1,基本概念
1.1、时间复杂度
/**
把程序的相对执行时间函数 T(n) 简化为一个数量级,用大写的O表示,T(n)=O(f(n))。
时间复杂度的推导原则:
如果运行时间是常数量级,则用常数1表示;
如果函数中有多项,则保留最高阶项并去除前面的系数;
常见的时间复杂度:O(1) < O(logn) < O(n) < O(n^{2})
*/
1.2、空间复杂度
/**
对一个算法在运行过程中临时占用存储空间大小的量度,用大写的O表示,S(n)=O(f(n))。
时间复杂度的推导:
常量空间:当算法的存储空间大小固定,和输入规模没有直接的关系是,空间复杂度记为 O(1) ;
线性空间:算法分配的空间是一个线性的集合(如数组),并且集合大小和输入规模 n 成正比,空间复杂度记为 O(n);
二维空间:算法分配的空间是一个二维数组集合,并且集合的长度和宽度都与输入规模 n 成正比,空间复杂度记为 O(n^{2}{\color{Red} }{\color{Red} });
常见的空间复杂度:O(1) < O(n) < O(n^{2})
*/
1.3、性能对比
查找 | 修改 | 添加 | 删除 | |
数组 | O(1) | O(1) | O(n) | O(n) |
列表 | O(1) | O(1) | O(1) | O(1) |
栈 | O(1) | O(1) | ||
队列 | O(1)(循环队列) | O(1)(循环队列) | ||
哈希表 | O(1) | 约等于O(1) | 约等于O(1) | 约等于O(1) |
2、数组
/**
定义:有限个相同类型的变量所组成的有序集合
特点:
数组中的每个元素有自己的下标,从0开始,直到数组长度-1 ;
在内存中顺序存储(在内存中占用了连续完整的存储空间),可以很好的实现逻辑上的顺序表
数组实际元素的数量可能小于数组的长度 ;
适合读操作多,写操作少的场景 ;
数组属于线性的数据结构;
数组内存结构分析:数组是引用数据类型,存放在堆内存中(数组名存放在栈内存中,是一
个地址,数组的内容存放在对堆内存中)
*/
3、链表 linked list
/**
定义:在物理上 非连续、非顺序 的数据结构,由若干节点组成。
单向链表:每一个节点包含两部分。一部分是存放数据的变量 data , 另一部分是指向下一个节点的指针 next ;
双向链表:除了 data 和 next 指针,还有指向前置节点的 prev 指针
特点:
在内存中随机存储(每个节点分布在内存的不同位置,依靠 next 指针关联起来),可以很好的实现逻辑上的顺序表
链表中的数据只能根据指针按顺序进行访问 ;
适合插入删除多的场景 ;
链表属于线性的数据结构
*/
4、栈 stack
/**
定义:是一种线性数据结构,栈中的元素只能先入后出。
特点:
栈中的元素只能先入后出(First In Last Out,简称FILO)
最早进入的元素存放的位置叫做 栈底(bottom),最后进入的元素存放的位置叫做 栈顶(top) ;
栈属于线性数据结构,既可以用数组来实现,也可以用链表来实现
出栈和入栈只会影响到最后一个元素
栈的输出顺序和输入顺序相反,通常用于“历史”的回溯
栈的基本操作:
入栈(push):只允许从栈顶一侧放入元素,新元素的位置将会称为新的栈顶。
出栈(pop):只有栈顶中元素才允许出栈,出栈元素的前一个元素将会称为新的栈顶
举例:一段封闭,一段开口的圆筒,往圆筒里放入乒乓球。先放入的靠近圆筒底部,后放入的靠近圆筒入口。要想取出乒乓球,只能按照和放入顺序相反的顺序来取。
*/
5、队列 stack
/**
定义:是一种线性数据结构,队列中的元素只能先入先出。
特点:
队列中的元素只能先入先出(First In First Out,简称FIFO)
队列的出口端叫做 队头(front), 队列的入口端叫做 队尾(rear) ;
队列属于线性数据结构,既可以用数组来实现,也可以用链表来实现
在物理存储上,队尾的位置也可以在队头之前
队列的输出顺序和输入顺序相同,通常用于“历史”的回放
队列的基本操作:
入队(enqueue):只允许在队尾的位置放入元素,新元素的下一个位置将会称为新的队尾。
出栈(dequeue):只允许在队头一侧移出元素,出队元素的后一个元素将会称为新的队头。
举例:公路上的一条单行隧道,所有通过隧道的车辆只允许从隧道入口驶入,从隧道出口驶出,不允许逆行。要想让车辆驶出隧道,只能按照他们驶入隧道的顺序来驶出。
*/
6、哈希表 hash table
/**
定义:也叫散列表,本质上是一个数组。提供了键(key)和值(value)的映射关系。
哈希函数:通过哈希函数,可以把字符串或其他类型的 Key,转化成数组的下标 index。
哈希冲突:不同的 Key 通过哈希函数获得的下标有可能相同
哈希表的基本操作:
写操作(put):在表中插入新的键值对。如调用 hashMap.put("002931","旺旺"),意思是插入一组Key为002931,Value为王五的键值对。
读操作(get):通过给定的 Key ,在哈希表中查找对应的 Value。
*/