数据结构与算法
morris131
这个作者很懒,什么都没留下…
展开
-
二叉树的前、中、后、层序遍历
二叉树的遍历遍历:把二叉树中所有节点都访问一遍且只访问一次。二叉树有以下四种遍历方式:前序遍历: 先访问父节点,再遍历左子树和右子树。中序遍历: 先遍历左子树,再访问父节点,再遍历右子树。后序遍历: 先遍历左子树,再遍历右子树,最后访问父节点。层序遍历:也叫层次遍历,从根节点开始往下一层一层的遍历节点。小结: 看访问父节点的顺序,就能确定是前序,中序还是后序遍历。前序遍历前序遍历的访问顺序为:父节点、前序遍历左子树、前序遍历右子树。下面的二叉树前序遍历的结果为7、4、2、1、3、5、原创 2020-07-26 18:39:39 · 18130 阅读 · 1 评论 -
数据结构与算法之二叉树
二叉树数组,链表和树的比较数组的优缺点:优点:通过索引方式访问元素,速度非常快,时间复杂度为O(1)。对于有序数组,还可以使用二分查找来提高查找的速度。缺点:如果要查找某个具体的值,时间复杂度为O(n),如果要在数组中插入某个值(按一定顺序)会整体的移动,效率较低。链表的优缺点:优点:插入一个值,只需要创建一个节点并将节点链接到链表中即可。缺点:在进行查找时,效率仍然较低,需要从头节点开始遍历,时间复杂度为O(n)。树的优点:能提高数据存储和读取的效率,比如利用二叉搜索树,既可以保原创 2020-07-25 18:44:12 · 17480 阅读 · 0 评论 -
数据结构与算法跳表之java实现
跳表一个有序链表的搜索、添加、删除的平均时间复杂度都为O(n),那么能否利用二分搜索优化有序链表,将搜索、添加、删除的平均时间复杂度降低至O(logn)呢?链表没有像数组那样的高效随机访问(O(1)时间复杂度),所以不能像有序数组那样直接进行二分搜索优化。那有没有其他办法让有序链表的搜索、添加、删除的平均时间复杂度降低至O(logn)?答案是使用跳表。跳表的介绍跳表(SkipList),又叫做跳跃表、跳跃列表,在有序链表的基础上增加了“跳跃”的功能,由William Pugh于1990年发布,设计原创 2020-07-20 11:33:03 · 16005 阅读 · 2 评论 -
十大排序算法快速排序之Java实现
快速排序快速排序(Quick Sort)是对冒泡排序的一种改进,采用的是分治策略(一般与递归结合使用),以减少排序过程中的比较次数。快速排序在1960年由查尔斯·安东尼·理查德·霍尔(Charles Antony Richard Hoare,缩写为C. A. R. Hoare)提出,昵称为东尼·霍尔(Tony Hoare)。算法步骤从数组中选择一个轴点元素(pivot),假设每次都选择索引为0的元素为轴点元素。利用pivot将数组分割成2个子数组,将小于pivot的元素放在pivot前面(左侧)原创 2020-07-19 14:10:11 · 12666 阅读 · 0 评论 -
数据结构之布隆过滤器
布隆过滤器如果要经常判断某个元素是否存在,你会怎么做?很容易想到使用哈希表(HashSet、HashMap),将元素作为key去查找。时间复杂度为O(1),但是空间利用率不高,需要占用比较多的内存资源。如果需要编写一个网络爬虫去爬10亿个网站数据,为了避免爬到重复的网站,如何判断某个网站是否爬过?很显然,HashSet、HashMap并不是非常好的选择。是否存在时间复杂度低、占用内存较少的方案?就是下面要学习的布隆过滤器。布隆过滤器(Bloom Filter)布隆过滤器(Bloom Filter)原创 2020-07-14 11:47:59 · 11042 阅读 · 0 评论 -
十大排序算法之归并排序
归并排序归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。算法步骤不断地将当前序列平均分割成2个子序列,直到不能再分割(序列中只剩1个元素)不断地将2个子序列合并成一个有序序列,直到最终只剩下1个有序序列divide实现 private E[] leftArray;原创 2020-07-12 12:25:37 · 17466 阅读 · 0 评论 -
排序算法之希尔排序
希尔排序1959年由唐纳德·希尔(Donald Shell)提出希尔排序。希尔排序的思想:把数组中的元素看作是一个矩阵,分成m列,逐列进行排序(一般采用插入排序),m从某个整数逐渐减为1,当m为1时,整个序列将完全有序。因此,希尔排序也被称为递减增量排序(Diminishing Increment Sort)。矩阵的列数取决于步长序列(step sequence),比如,如果步长序列为{1,5,19,41,109,…},就代表依次分成109列、41列、19列、5列、1列进行排序。不同的步长序列,执行效原创 2020-07-05 21:26:31 · 27966 阅读 · 1 评论 -
排序算法之插入排序
插入排序插入排序(Insertion Sorting)的基本思想是:把n个待排序的元素看成为一个有序数组和一个无序数组,开始时有序数组中只包含一个元素,无序数组中包含有n-1个元素,排序过程中每次从无序数组中取出第一个元素,把它依次与有序数组的元素进行比较,将它插入到有序数组中的适当位置,使之成为新的有序数组,直到最后无序数组没有元素为止。算法步骤将待排序数组第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置原创 2020-07-05 09:32:47 · 11837 阅读 · 0 评论 -
排序算法之堆排序
堆排序有关堆这个数据结构请参考数据结构之堆。有关批量建堆请参考完全二叉堆之批量建堆。堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。堆排序可以认为是对选择排序算法中寻找最小(大)元素的优化。一般升序采用大顶堆,降序采用小顶堆。算法思想对数组进行原地建堆(heapify)重复执行以下操作,直到堆的元素数量为1交换堆顶元素与尾元素堆的元素数量减1对0位置进行1次下滤(siftDown)操作原创 2020-07-04 17:53:11 · 14663 阅读 · 0 评论 -
完全二叉堆之批量建堆
批量建堆对堆的介绍请参考xxxx。批量建堆(Heapify):就是将已经存在n个元素的数组批量添加至堆中,而不是遍历数组一个一个将元素添加至堆中。遍历数组一个一个添加元素至堆中,时间复杂度为O(nlogn),而使用批量建堆,时间复杂度最低可以降为O(n)。批量建堆有2种实现方法:自上而下的上滤自下而上的下滤自上而下的上滤自上而下的上滤类似于从第2个元素开始依次添加。代码实现如下:for (int i = 1; i < size; i++) { siftUp(i);}原创 2020-07-02 09:29:30 · 13877 阅读 · 0 评论 -
图的遍历方式
图的遍历方式图的遍历:从图中某一顶点出发访问图中其余顶点,且每一个顶点仅被访问一次。图有2种常见的遍历方式(有向图、无向图都适用)广度优先搜索(Breadth First Search,BFS),又称为宽度优先搜索、横向优先搜索深度优先搜索(Depth First Search,DFS)广度优先搜索广度优先搜索:从起始节点开始一层一层的进行遍历,只有完全遍历完一层所有的节点后才会进入下一层的遍历。二叉树的层序遍历就是一种广度优先搜索。Graph<V, E>接口中添加内部接口原创 2020-07-02 08:07:06 · 18324 阅读 · 0 评论 -
数据结构之堆
思考假如需要设计一种数据结构,用来存放整数,要求提供3个接口:添加元素获取最大值删除最大值如果使用动态数组、双向链表和二叉树实现这个数据结构对应的时间复杂度如下表所示:添加元素获取最大值删除最大值说明动态数组\双向链表O(1)O(n)O(n)有序动态数组\双向链表O(n)O(1)O(1)全排序有点浪费平衡二叉搜索树O(logn)O(logn)O(logn)杀鸡焉用牛刀有没有更优的数据结构?使用堆,可以使得获取最大值的时间复杂原创 2020-07-01 10:33:38 · 17734 阅读 · 0 评论 -
java使用邻接表实现图
邻接表实现图图的表示方式有两种:邻接矩阵(Adjacency Matrix)邻接表(Adjacency List)本文采用类似邻接表的方式实现图。图的基础接口public interface Graph<V, E> { int verticesSize(); // 顶点数量 int edgesSize(); // 边的数量 void addVertex(V v); // 添加顶点 void addEdge(V from, V to); //原创 2020-06-30 09:39:19 · 14704 阅读 · 0 评论 -
数据结构之图的基本介绍
图的基本介绍线性表局限于一个直接前驱和一个直接后继的关系,树也只能有一个直接前驱也就是父节点。当我们需要表示多对多的关系时,就需要用到图。图的基本概念图(Graph)是一种数据结构,由顶点(vertex)和边(edge)组成,通常表示为G=(V,E):G:表示一个图V:表示图中顶点的集合,顶点集V有穷且非空E: 表示图中边的集合,边集E可以是空的边:两个顶点之间的连接。路径:一个顶点到另一个顶点的通路。比如下面的无向图中,从顶点D到顶点C的路径有:D->B->CD-&原创 2020-06-29 14:37:32 · 14313 阅读 · 0 评论 -
选择排序是一个稳定排序算法吗?
选择排序选择排序是一种简单直观的排序算法,无论什么数据都是O(n^2)的时间复杂度。所以用到它的时候,数据规模越小越好。算法步骤从数组中找出最小的那个元素,然后与最开始的元素交换位置忽略第一步中找到的最小元素,重复执行步骤1动图演示算法实现for (int i = 0; i < array.length - 1; i++) { int minIndex = i; // 保存最小元素索引 for (int j = i; j < array.length; j++原创 2020-06-28 09:30:05 · 21544 阅读 · 1 评论 -
冒泡排序
冒泡排序冒泡排序(Bubble Sort)的基本思想是:通过对待排序数组从头到尾遍历(从索引较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从数组头部移向尾部,就象水底下的气泡一样逐渐向上冒。算法步骤比较相邻的元素。如果第一个比第二个大,就交换他们两个。对每一对相邻元素重复第一步,从开始第一对到结尾的最后一对。这步做完后,数组最后一个元素将会是数组中最大的元素。针对所有的元素重复以上的步骤,除了最后一个。持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需原创 2020-06-27 16:57:00 · 16336 阅读 · 0 评论 -
计数排序
计数排序冒泡、选择、插入、归并、快速、希尔、堆排序,都是基于比较的排序,平均时间复杂度最低是O(nlogn)。计数排序、桶排序、基数排序,都不是基于比较的排序,它们是典型的用空间换时间,在某些时候,平均时间复杂度可以比O(nlogn)更低。计数排序(Counting Sort)于1954年由Harold H. Seward提出,适合对一定范围内的整数进行排序。计数排序的核心思想:统计每个整数在数组中出现的次数,进而推导出每个整数在有序数组中的索引。最简单的实现具体实现步骤如下:找出数组arr原创 2020-06-26 08:47:32 · 47711 阅读 · 2 评论 -
基数排序
基数排序基数排序(Radix Sort)是1887年由赫尔曼·何乐礼发明的,基数排序非常适合用于整数排序(尤其是非负整数)。它的执行流程为:依次对个位数、十位数、百位数、千位数、万位数…,进行排序(从低位到高位)。个位数、十位数、百位数的取值范围都是固定的0~9,可以使用计数排序对它们进行排序。思考:如果先对高位排序,再对低位排序,是否可行?不可行。基数排序图解代码实现// 找出数组中的最大值int max = array[0];for (int i = 1; i < array.原创 2020-06-25 18:22:37 · 12085 阅读 · 0 评论