总结
阿里十分注重你对源码的理解,对你所学,所用东西的理解,对项目的理解。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
是由零个或多个原子或子表组成的优先序列,是线性表的推广。
广义表的存储结构
广义表中的数据元素可以具有不同的结构,因此,难以用顺序存储结构表示,通常采用链式存储结构,每个数据元素可用一个节点表示。由于广义表中有两种数据元素,因此需要有两种结构的节点——一种是表结点,一种是原子结点。
表结点由三个域组成:
标志域、指示表头的指针的指针域和指示表尾的指针域;而原子域只需两个域:标志域和值域。
表结点由三个域组成:
标志域、指示表头的指针域和指向下一个元素的指针;原子结点的三个域为:标志域、值域和指向下一个元素的指针。
树
树的定义
树的逻辑表示:
树形表示法、
文氏图表示法、
凹入表示法、
括号表示法。
结点:
表示树中的元素,包括数据项及若干指向其子树的分支。
结点的度:
结点拥有的子树树;树的度:一棵树中最大的结点度数
叶子结点:
度为0的结点;
分支结点:
度不为0的结点;
孩子:
结点子树的根称为该结点的孩子;双亲:孩子结点的上层结点叫该结点的双亲;兄弟:同一双亲的孩子。
深度:
树中结点的最大层次数。
有序树:
树中各结点的子树从左至右是有次序的,不能互换。否则称为无序树。
树的性质
树中的结点数等于所有结点的度数加1。
度为m的树中第i层上至多有mi-1 个结点(i>=1)。
二叉树的概念
满二叉树:
定义—— 一棵深度为k且具有2k-1个结点的二叉树。特点——每一层上的结点数都是最大结点数。
完全二叉树:
定义—— 深度为k,有n个结点的二叉树当且仅当其每一个结点都与深度为k的满二叉树中编号从1至n的结点一一对应时,称为完全二叉树。
二叉树的性质
二叉树的第i层上至多有2i-1(i>=1)个结点。
深度为K的二叉树至多有2k-1个结点。
对任何一棵二叉树T,如果其叶子数为n0,度为2的结点数为n2,则n0=n2+1。
一个有n个结点的完全二叉树,编号最大的分支结点的编号是
一个有n个结点的完全二叉树,n0的个数是不小于n/2的最小整数。
二叉树的存储结构
用一组连续的存储单元存储二叉树的数据元素。在存储之前对二叉树的所有结点安排一个适当的序列,使得结点在这个序列中的相互位置能反应出结点之间的逻辑关系。
特点:
结点间关系蕴含在其存储位置中;浪费空间,适于存满二叉树和完全二叉树。
二叉树的链式存储结构
用一个链表来存储一棵二叉树,二叉树中每一个结点用链表中的一个链结点来存储。
遍历二叉树
遍历方法:
利用遍历结果确定二叉树:
先序遍历:
//先序遍历递归算法
void preorder(Tree t){
if(t==null)
return;
visit(t);
preorder(t.left());
preorder(t.right());
}
//先序遍历非递归算法
void PreOrderUnrec(Bitree t)
{
//创建栈来存放树的结点
SqStack s;
StackInit(s);
p=t;
while (p!=null || !StackEmpty(s))
{
while (p!=null) //遍历左子树
{
visite(p->data);
push(s,p);
p=p->lchild;
}//endwhile
if (!StackEmpty(s)) //通过下一次循环中的内嵌while实现右子树遍历
{
p=pop(s);
p=p->rchild;
}//endif
}//endwhile
}//PreOrderUnrec
中序遍历
//中序遍历递归算法
void inorder(Tree t){
if(t==null)
return;
inorder(t.left());
visit(t);
inorder(t.right());
}
// 非递归
void InOrderUnrec(Bitree t)
{
//创建栈来存放树的结点
SqStack s;
StackInit(s);
p=t;
while (p!=null || !StackEmpty(s))
{
while (p!=null) //遍历左子树
{
push(s,p);
p=p->lchild;
}//endwhile
if (!StackEmpty(s)) //通过下一次循环中的内嵌while实现右子树遍历
{
p=pop(s);
visite(p->data); //访问根节点
p=p->rchild;
}//endif
}//endwhile
}//InOrderUnrec
后序遍历
后序遍历递归算法
void inorder(Tree t){
if(t==null)
return;
inorder(t.left());
inorder(t.right());
visit(t);
}
//后序遍历非递归算法
/对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,此时该结点出现在栈顶,但是此时不能将其出栈并访问,因此其右孩子还为被访问。所以接下来按照相同的规则对其右子树进行相同的处理,当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。这样就保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是否是第一次出现在栈顶。/
void postOrder2(BinTree *root) //非递归后序遍历
{
stack<BTNode*> s;
BinTree *p=root;
BTNode *temp;
while(p!=NULL||!s.empty())
{
while(p!=NULL) //沿左子树一直往下搜索,直至出现没有左子树的结点
{
BTNode *btn=(BTNode *)malloc(sizeof(BTNode));
btn->btnode=p;
btn->isFirst=true;
s.push(btn);
p=p->lchild;
}
if(!s.empty())
{
temp=s.top();
s.pop();
if(temp->isFirst==true) //表示是第一次出现在栈顶
{
temp->isFirst=false;
s.push(temp);
p=temp->btnode->rchild;
}
else //第二次出现在栈顶
{
cout<btnode->data<<" ";
p=NULL;
}
}
}
}
线索二叉树
利用二叉链表的空指针域,建立指向该结点的前驱/后继结点的指针,方便二叉树的线性化使用。
对二叉链表以某种次序遍历使其变为线索二叉树的过程叫做线索化。有先序线索二叉树、中序线索二叉树(更实用)和后序线索二叉树三种。
建立中序线索二叉树
树的存储结构
双亲表示法:
用一组连续空间存储树的结点,每个节点包含两个域——数据域用来存放结点本身信息,双亲域用来指示本结点的双亲结点在数组中位置。
孩子表示法:
采用孩子链表,每个结点的孩子结点用单链表存储,再用含n个元素的结构数组指向每个孩子链表。
带双亲的孩子链表
孩子兄弟表示法:
用二叉链表作为树的存储结构。链表中结点的两个链域分为指向该结点的第一个孩子结点和下一个兄弟结点。
森林与二叉树的转换
将树转换为二叉树
将二叉树转换为树:
森林转换成二叉树:
二叉树转换成森林
哈夫曼树
结点的权及带权路径长度:若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。结点的带权路径长度为:从根节点到该结点之间的路径长度与该结点的权的乘积。
在一棵二叉树中,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称哈夫曼树。
图
图的概念
图是一种较线性表和树更为复杂的数据结构,在图形结构中,结点之间关系可以是任意的,图中任意两个数据元素之间都可能相关。
有向图和无向图
若无向图中的每两个顶点之间都存在着一条边,则称该无向图称作完全无向图;显然完全无向图中包含着e=n(n-1)/2条边。若有无向图中的每两个顶点之间都存在方向相反的两条边,则称该有向图称作完全有向图;显然完全有向图中包含有e=n(n-1)条边。
与图的边或弧相关的数叫做权,带权的图称为网。
对于有向图而言,度又分为出度和入度。顶点的出度——以顶点v为弧尾的弧的数目;顶点的入度——以顶点v为弧头的弧的数目;顶点的度为该顶点的出度和入度的和。
在无向图G中,如果从顶点v到顶点w存在路径,则称v到w是连通的。若图G中任意两个顶点之间都有路径相通,则称为连通图。
若无向图为非连通图,则图中各个极大连通子图称作此图的连通分量。任何连通图的连通分量只有一个,即本身,而非连通图则有多个连通分量。
在有向图中,若任意两个顶点之间都存在一条有向路径,则称此有向图为强连通图。
若有向图为非强连通图,其各个强连通子图称为它的强连通分量。
图的存储结构——邻接矩阵
邻接矩阵是表示顶点之间相邻关系的矩阵。
无向图的邻接矩阵:
有向图的邻接矩阵:
网的邻接矩阵:
图的存储结构——邻接表
邻接表存储方法是一种顺序分配与链式分配相结合的存储方法。它包括两部分:一部分是单链表,用来存放边的信息;另一部分是数组,主要用来存放顶点本身的数据信息。
无向图邻接表:
有向图的邻接表:
图的存储结构——十字链表
十字链表是有向图的另一种链式存储结构。可以看成是将有向图的邻接表和逆邻接表结合起来得到的一种链表。在十字链表中,每条弧和每个顶点分别对应着一个结点。
图的存储结构——邻接多重表
邻接多重表是无向图的另一种链式存储结构。邻接多重表和十字链表一样,每条边和每个顶点分别对应着一个结点。
图的遍历
从图中某个顶点出发游历图,访遍图中其余顶点,并且使图中的每个顶点仅被访问一次的过程。
根据搜索方法的不同,图的遍历有两种:深度优先搜索(DFS)和广度优先搜索(WFS)。
深度优先搜索
连通图深度优先搜索的算法:
广度优先搜索
广度优先搜索是一种分层的搜索过程,每向前走一步可能访问一批顶点,不像深度优先搜索那样有回退的情况。因此,广度优先搜索不是一个递归的过程,其算法也不是递归的。
连通图的广度优先搜索算法:
非连通图广度优先搜索:
无向图的连通分量和生成树
连通图生成树:
一个连通图的生成树是一个极小连通子图,它含有图中全部顶点,但只有构成一棵树的n-1条边。
当无向图为非连通图时,从图中某一顶点除法,利用深度优先搜索算法或广度优先搜索算法不可能遍历到图中的所有顶点,只能访问到该顶点所在的极大连通子图的所有顶点,该极大连通子图称为无向图的一个连通分量。
使用不同的遍历图的方法,可以得到不同的生成树;从不同的顶点出发,也可能得到不同的生成树。
最小生成树
在连通网的众多生成树中,各边权值之和最小的生成树称为最小代价生成树,简称最小生成树。
生成最小生成树算法——普里姆算法:
生成最小生成树算法——克鲁斯卡尔算法:
有向无环图
一个无环的有向图称为有向无环图,简称DAG图。
拓扑排序
在一个有向图中,若用顶点表示活动,有向边表示活动间的先后关系,称该有向图叫做顶点表示活动的网络,简称AOV网。
按照有向图给出的次序关系,将图中顶点排成一个线性序列,对于有向图中没有限定次序关系的顶点,则可以人为加上任意的次序关系。由此所得顶点的线性序列成为拓扑有序序列。
拓扑排序:
由某个集合上的一个偏序(集合中仅有部分成员之间可以比较)得到该集合上的一个全序(集合中全体成员之间均可以比较)的操作称为拓扑排序。
拓扑排序的算法:
关键路径
在一个有向图中,若用顶点表示事件,弧表示活动,权表示活动持续时间,称该有向图叫做边表示活动的网络,简称为AOE网。
查找
概述
查找表:
由同一类型的数据元素(或记录)构成的集合。
静态查找表
静态查找是指在静态查找表上进行的查找操作,在查找表中满足条件的数据元素的存储位置或各种属性。
静态查找表的查找算法主要有:
顺序查找:
从表的一端开始,顺序扫描线性表,依次将扫描到的关键字和给定值k进行比较,若当前扫描到的关键字与k相等,则查找成功;若扫描结束后,仍未找到关键字等于k的记录,则查找失败。
折半查找:
对给定值k,逐步确定待查记录所在区间,每次将搜索空间减少一半,直到查找成功或失败为止。
分块查找
动态查找表:
表结构在查找过程中动态生成的这样一种查找表。实现动态查找方法:二叉排序树、平衡二叉树、B-树和B+树。
二叉排序树
定义:左子树的所有结点均小于根的值;右子树的所有节点均大于根的值;它的左右子树也分别为二叉排序树。
二叉排序树插入新结点的过程:
二叉排序树插入新节点递归算法:
二叉排序树删除结点的算法:
二叉排序树查找算法分析:
平衡二叉树
平衡二叉树又称为AVL树,设二叉树中结点的左子树和右子树的深度分别为HL和HR。
若在构造二叉排序树的同时,使其始终保持为AVL树,则此时的二叉排序树为平衡的二叉排序树。将一棵非平衡二叉排序树调整成平衡二叉排序树的“旋转”,分为:LL平衡旋转、RR平衡旋转、LR平衡旋转、RL平衡旋转。
B-树:
http://haicang.blog.51cto.com/2590303/1134864
B-树又称基本B树或多路平衡查找树。它是构造大型文件系统索引结构的一种数据结构类型,适合在磁盘等直接存取设备上组织动态的查找表。
该公式包括没有任何关键字的叶子结点。
B-树的查找算法思路:
B-树的查找效率取决于以下两个因素:包含k的结点在B-树种所在的层数h;结点中ki的个数n。
B-树的生成:
B-树的删除:
B+树
B+树是B-树的变形,目的在于有效地组织文件的索引结构。
- m阶B+树与B-树的差异:
-
B+树种可以有两种查找方式:顺序查找——类似单链表的查找,直接在数据层进行查找。随机查找——类似B-树的查找,不同的是搜索到索引层的key与k相等时,还得继续搜索下去,直到数据层为止。
哈希表
-
哈希表,根据设定的哈希函数H(key)和处理冲突的方法将一组关键字key映射到一个有限的连续的地址集上,并以关键字key在地址集中的“像”作为记录在表中的存储位置,这种表便称为哈希表,这一映射过程称为哈希造表或散列,所得存储位置称哈希地址或散列地址。
-
将不同的关键码映射到同一个哈希地址上,该现象称为冲突。
哈希函数的构造方法
-
常用的哈希函数构造方法有:直接定址法、除留余数法、乘余取整法、数字分析法、平方取中法、折叠法、随机数法。
-
直接定址法:
- 除留余数法:
- 乘余取整法:
- 数字分析法:
- 平方取中法:
- 叠加法:
- 随机数法:
处理冲突的方法
-
开放定址法、链地址法、再哈希法、建立一个公共溢出区
-
开放定址法:
- 链地址法:
- 再哈希法:
- 建立一个公共溢出区:
红黑树
- 红黑树,一种二叉查找树,但在每个结点上增加一个存储位表示结点颜色,可以是Red或Black。通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因而是接近平衡的。
-
红黑树虽然本质上是一棵二叉查找树,但它在二叉查找树的基础上增加了着色和相关的性质使得红黑树相对平衡,从而保证了红黑树的查找、插入、删除的时间复杂度最坏为O(log n)。红黑树和AVL树的区别在于它使用颜色来标识结点的高度,它所追求的是局部平衡而不是AVL树中的非常严格的平衡。
-
红黑树的五个性质保证了红黑树的高度始终保持在logn:
-
红黑树的旋转操作:红黑树的旋转操作和AVL树一样,分为LL、RR、LR、RL四种旋转类型,差别在于旋转完成后改变的是结点的颜色,而不是平衡因子。
-
红黑树的插入和删除:http://blog.csdn.net/eric491179912/article/details/6179908
排序
–
排序概述
排序的分类:内部排序和外部排序(若待排序记录都在内存中,称为内部排序;若待排序记录一部分在内存,一部分在外存,则称为外部排序)。稳定排序和不稳定排序。
内部排序的算法:插入排序(希尔排序)、交换排序(快速排序)、选择排序(堆排序)、归并排序、基数排序。
插入排序
思想:每次将一个待排序的对象,按其关键码大小,插入到前面已经排好序的一组对象的适当位置上,直到对象全部插入为止。
具体实现算法:直接插入排序、折半插入排序、希尔排序
直接插入排序:
最后
喜欢的话别忘了关注、点赞哦~
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】