数据结构笔记

常见的数据结构:数组、栈、链表、队列、树、图、堆、散列表等。每种数据结构都有独特的数据存储方式。

1.数组

可以在内存中连续存储多个元素的结构,在内存中的分配也是连续的,数组中的元素是通过数组下标进行访问,数组下标从开始。
优点:按照索引查询元素速度快;按照索引遍历数组方便,时间复杂度
O(1);
缺点:a.数组大小固定后无法扩容;b.数组只能存储一种类型数据;c.添加、删除的操作慢,因为要移动其他的元素;
适用场景:对于存储空间要求不大,很少增删的情况;

2.栈

一种特殊的线性表,仅能在线性表的一端操作,栈顶允许操作,栈底不行。
特点:先进后出,后进先出,从栈顶放入元素叫做入栈,取出元素叫做出栈。
因为他的特点,栈通常应用于实现递归功能方面的场景,例如斐波那契数列。

3.队列

与栈相同,也是一种线性表,不同的是,队列可以在一端添加元素,在另一端取出元素,也就是:先入先出,在一端放入元素的操作称之为入队,
取出元素为出队。
因为队列先入先出的特点,在多线程阻塞队列管理中非常适用。

4.链表

物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表的指针地址实现,每个元素包含两个节点,一个是数据域,一个是指针域,
数据域存储元素,指针域存储下一个节点地址。根据指针的的指向,链表又分为单链表、双链表、循环链表等。
优点:不需要初始化容量,可以任意加减元素。
添加或删除元素时只需要改变前后两个元素节点的指针域指向的地址即可,所以添加、删除很快;
缺点:因为含有大量的指针域,占用空间会比较大;查找元素需要遍历链表来查找,非常耗时,时间复杂度O(n)。
适用场景:数据量较小,需要频繁增加、删除操作的场景。

5.树

一种数据结构,它是由n(n>=1)个有限节点组成一个有层级关系的集合。

	a.特点:
		a.每个节点有零个或多个子节点;
		b.没有父节点的节点是根节点;
		c.每一个非根节点有且只有一个父节点;
		d.除了根节点以外,每个子节点可以分为多个不相交的子树;
	
	b.二叉树是树的特殊一种,具有以下特点:
		a.每个节点最多有两个子树,节点的度最大为2。
		b.左子树和右子树是有顺序的,次序不能颠倒。
		c.即使某节点只有一个子树,也要区分左右子树。
	
	c.二叉树是一种比较有用折中的方案,它添加,删除元素都很快,并且在查找方面也有很多算法优化,所以二叉树既有链表的好处,也有数组的好处,
	是两者的优化方案,在处理大批量的动态数据方面非常有用。
	
	d.二叉树有很多扩展的数据结构,包含完全二叉树、满二叉树、平衡二叉树、红黑树、B+树等,这些数据结构是在二叉树的基础上衍生出很多功能,例如,mysql的数据库索引结构
	用的就是B+树,还有HashMap的底层源码中用到了红黑树。
		
		i.完全二叉树:除了最后一层节点,其余层节点数都达到了最大值,同时最后一层的节点都是按照从左到右依次排布。
		ii.满二叉树:除了最后一层,其余层的节点都是两个子节点。
		iii.平衡二叉树:又称AVL树,它是一颗二叉排序树,具有以下特性:一颗空树或它左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一颗平衡二叉树。
			平衡二叉树(AVL)为了追求高度平衡,需要通过平衡处理使得左右子树的高度差必须小于等于1。高度平衡带来的好处是能够提供更高的搜索效率,
			其最坏的查找时间复杂度都是O(logN)。但是由于需要维持这份高度平衡,所付出的代价就是当对树种结点进行插入和删除时,需要经过多次旋转实现复衡。
			这导致AVL的插入和删除效率并不高。
		
		vi.红黑树:兼顾搜索和插入删除数据的效率;
			特征:
				每个节点要么是红要么是黑的。
				根节点是黑的。
				每个叶节点(指树未段NIL指针或null节点)都是黑色。
				如果节点是红色,子节点一定是黑色。
				任意节点而言,其到叶节点树尾端NIL指针的每条路径都包含相同的黑节点。
				
			红黑树通过将结点进行红黑着色,使得原本高度平衡的树结构被稍微打乱,平衡程度降低。红黑树不追求完全平衡,只要求达到部分平衡。
			这是一种折中的方案,大大提高了结点删除和插入的效率。
		红黑树VS平衡二叉树(AVL):
			相同点:都是二叉排列树;
			查询效率:红黑树一般时间复杂度为O(logN),最坏情况差于AVL;AVL时间复杂度稳定在O(logN);
			插入效率:红黑树:需要旋转操作和变色操作,插入节点最多只需2次旋转,变色需要O(logN);
						AVL:插入节点最多需要1次旋转,O(logN)级别;
			删除效率:红黑树删除一个节点最多需要三次旋转操作;AVL每一次删除操作最多需要O(logN)次旋转。
			优劣势:红黑树数据读取效率低于AVL,维护性强于AVL.
			应用场景:红黑树搜索、插入、删除操作差不多;AVL搜索的次数远远大于插入和删除。

6.散列表(哈希表)

根据键和值(key和value)直接进行访问的数据结构,通过key和value来映射到集合中的一个位置,这样就可以很快的找到集合中对应的元素。
记录的存储位置=f(key);
这里对应关系f成了散列函数,又称为哈希(hash函数),而散列表就是通过一个固定的算法函数,即所谓的哈希函数转换成一个整行数字,然后将
数组长度进行取余,取余结果当作数组的下标,将value存储在以该数字为下标的数组空间里,这种存储空间可以充分利用数组的查找优势来查找元素,
所以查询的速度比较快。

7.堆

看做一棵树的数组对象,特点:堆中某个节点的值总是不大于或不小于其父节点的值;堆总是一颗完全二叉树;
将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。
因为堆有序的特点,一般用于在数组中排序,称为堆排序;

8.图

图是由结点的有穷集合V和边的集合E组成。
其中,为了与树形结构加以区别,在图结构中常常将结点称为顶点,边是顶点的有序偶对,若两个顶点之间存在一条边,就表示这两个顶点具有相邻关系。
按照顶点指向的方向可分为无向图和有向图

两个栈(Stack)实现一个队列(Queue)

思路:始终维护s1作为存储空间,以s2作为临时缓冲区;入队时,将元素压入s1,出队时,将s1的元素逐个“倒入”(弹出并压入)s2,将s2的顶元素作为出队元素,
之后再将s2剩下的元素逐个“倒回”s1.
细节优化:出队时,将s1的元素逐个“倒入”s2时,原来s1栈底的元素,不用“倒入”s2(即只“倒”s1.Count()-1个),可直接作为弹出作为出队元素返回,
这样可以减少一次压栈操作。

变种:入队时,将元素压入s1;出队时,判断s2是否为空,如果不为空,则直接弹出顶元素;如果为空,则将s1的元素逐个“倒入”s2,把最后一个元素弹出并出队。(效率高,避免反复倒栈,仅在需要是倒一次)

你可能感兴趣的:(算法,数据结构,笔记)