数据结构和算法
目录
阶段一
第四节:顺序表剖析及利用数组手撸“动态数组ArryList”
第五节:链表剖析及自己手撸“单链表”实现基本操作(初始化、增、删、改等)
阶段二:用TS编写数据结构和算法
第五节:哈希表详解(哈希函数、增删改查、扩容/缩容、质数容量优化)
第七节:图结构详解(结构封装、添加定点/边、广度/深度优先遍历)
第十二节:红黑树性质、相对平衡的原理、与AVL树的区别、手写红黑树
第十五节:排序算法详解3(希尔排序、计数排序、桶排序、基数排序)--未完
第十七节:动态规划详解之斐波那契数列(递归、记忆搜索、动态规划、状态压缩)
第十八节:动态规划面试题(爬楼梯、买卖股票时机、最大子数组和)
阶段三:LeetCode刷题
第一节:字符串相关(最长公共前缀、无重复最长子串、最长回文子串)
第二节:栈相关(二叉树展开为链表、逆波兰表达式、两栈实现队列结构)
第四节:链表相关(删除倒数第N节点、相邻位置交换、反转链表)
第六节:动态规划相关(不同路径、礼物最大价值、最长递增子序列)
一. 什么是数据结构
必备网址:
https://www.cs.usfca.edu/~galles/visualization/Algorithms.html (动态图解)
1. 简介
数据结构,简单的来说,就是研究数据的存储方式。我们必须要知道,数据在计算机上存储空间的存放,绝对不是胡乱放的,是为了方便后期对数据的再运用,这就要求我们选择一种好的方式来存储数据,这就是数据结构的核心内容。
比如:我们可以用数组来存放{1,2,3,4,5,6},为了后期计算他们的和,或者取出来某个值,这个时候用数组存放是合理的,无缘由的数据存放是对存储空间的不负责!
2. 实际例子
(1). 像存储 1,2,{1,2,3}这种结构,用变量或者用数组来存储无疑是最佳方式,代码如下:
int a = 1; int b = 2; int[] myArray = { 1, 2, 3 };
(2). 像下图这种父子关系: 张亮是张平、张华和张群的父亲,同时张平还是张晶和张磊的父亲,当然可以用数组进行存储,如: {“张亮”,"张平",“张华”,"张群","张晶","张磊"},但是数组仅能存储数据,数据之间的关系根本无法体现。
针对此类数据,不光要存储数据,还要存储逻辑关系,即1对多的关系,数据结构中用 树 来存储。
(3). 导航无疑是出游旅行的必备神器,无论是哪款导航软件,其导航功能的实现都需要大量地图数据的支持。很明显,这些数据绝不是使用变量或数组进行存储的,那样对于数据的使用简直是个悲剧。
针对此类数据,数据结构提供 图 结构,来存储这种多对多关系。
最后总结:
数据结构是一门学科,它教会我们 "如何存储具有复杂关系的数据,从而更有利于后期我们对数据的使用"。
二. 数据结构有哪些
1. 数据结构的分类,大致如下图:
2. 线性表
线性表结构存储的数据往往是可以依次排列的,就像小朋友手拉手,每位学生的前面和后面都仅有一个小朋友和他拉手,具备这种“一对一”关系的数据就可以使用线性表来存储。例如,存储类似 {1,3,5,7,9} 这样的数据时,各元素依次排列,每个元素的前面和后边有且仅有一个元素与之相邻(除首元素和尾元素),因此可以使用线性表存储。
线性表并不是一种具体的存储结构,它包含顺序存储结构和链式存储结构,是顺序表和链表的统称。
(1). 顺序表
由于顺序表底层实现是基于数组的,因此对于初学者而言,可以把顺序表等价为数组,但实则不是这样的。数据结构是研究数据存储的一门学科,它囊括了各种存储结构,而数组知识各种编程语言中最基本的数据类型,并不属于数据结构的范畴。
顺序表需要提前申请一定大小的存储空间,并且这个空间的物理地址是连续的,例如:使用顺序表存储 {1,3,5,7,9},如下图:
(2). 链表
链表和顺序表不同,它在存储数据的时候,是随用随申请,因此数据的存储位置是相互分离的,也就是说,数据的存储位置是随机的。
为了给各个数据块建立“依次排列”的关系,链表给各数据块增设一个指针,每个数据块的指针都指向下一个数据块(最后一个数据块的指针指向 NULL),这样,看似毫无关系的数据块就建立了“依次排列”的关系,也就形成了链表,如图 下图 所示:
(3). 栈
栈是特殊的线性表,栈中的元素只能从线性表的一端进出(另一端封死),且要遵循“先入后出”的原则,即先进栈的元素后出栈。
如下图:像一个木桶,栈中含有 3 个元素,分别是 A、B 和 C,从在栈中的状态可以看出 A 最先进的栈,然后 B 进栈,最后 C 进栈。根据“先进后出”的原则,3 个元素出栈的顺序应该是:C 最先出栈,然后 B 出栈,最后才是 A 出栈。
(4). 队列
队列中的元素只能从线性表的一端进,从另一端出,且要遵循“先入先出”的特点,即先进队列的元素也要先出队列。
如下图:队列中有 3 个元素,分别是 A、B 和 C,从在队列中的状态可以看出是 A 先进队列,然后 B 进,最后 C 进。根据“先进先出”的原则,3 个元素出队列的顺序应该是 A 最先出队列,然后 B 出,最后 C 出。
3. 树
树结构用于存储【一对多】的逻辑关系的数据,如下图,其中张平只有一个父亲,但他却有两(多)个孩子,这就是“一对多”的关系,满足这种关系的数据可以使用树存储结构。
4. 图
图结构用于存储【多对多】的逻辑关系的数据,如下图,从 V1 可以到达 V2、V3、V4,同样,从 V2、V3、V4 也可以到达 V1,这就是“多对多”的关系,满足这种关系的数据可以使用图存储结构。
三. 逻辑结构和物理结构
1. 背景
数据的存储方式包括:线性表、树、图三种,而每种数据结构又细分为顺序存储结构和链式存储结构,数据存储方式如此之多,针对不同类型的数据选择合适的存储方式是至关重要的。
那么,到底如何选择呢?数据存储结构的选择取决于两方面,即数据的逻辑结构和存储结构(又称物理结构)。
2. 逻辑结构
数据的逻辑结构简单可以理解为:数据之间的逻辑关系。
一组数据成功存储到计算机的衡量标准是要能将其完整的复原。如果所存储的数据能将此成员关系图彻底复原,则说明数据存储成功。
图1:显示是一张家庭的成员关系图,从图中可以看到,张平、张华和张群是兄弟,他们的父亲是张亮,其中张平有两个儿子,分别是张晶和张磊。以上所说,父子、兄弟等这些关系都指的是数据间的逻辑关系,假设我们要存储这样一张家庭成员关系图,不仅要存储张平、张华等数据,还要存储它们之间的关系,两者缺一不可。
简单总结:数据之间的逻辑关系包括三种:一对一、一对多、多对多。
(1). 一对一:类似集合 {1,2,3,...,n} 这类的数据,每个数据的左侧有且仅有一个数据与其相邻(除 1 外);同样,每个数据的右侧也只有一个数据与其相邻(除 n 外),所有的数据都是如此,就说数据之间是“一对一”的逻辑关系
(2). 一对多:上面父子关系数据就属于“一对多”,因为对于张平来说,有且仅有一个父亲(张亮),但是有 2(多)个孩子;
(3). 多对多:如下图,从 V1 可以到达 V2、V3、V4,同样,从 V2、V3、V4 也可以到达 V1,对于 V1、V2、V3和 V4 来说,它们之间就是“多对多”的关系
最终结论:
(1). 线性表用于存储具有“一对一”逻辑关系的数据;
(2). 树结构用于存储具有“一对多”关系的数据;
(3). 图结构用于存储具有“多对多”关系的数据;
我们可以通过分析数据之间的逻辑关系来决定使用哪种存储结构,但具体使用顺序存储还是链式存储,还要通过数据的物理结构来决定 .
3. 物理结构
数据的存储结构,也就是物理结构,指的是数据在物理存储空间上选择集中存放还是分散存放。假设要存储大小为 10G 的数据,则集中存放就如图 3a) 所示,分散存放就如图 3b)所示。
分析:
集中存储,底层实现使用的是数组,需要一大块连续的物理空间,假设存储大小为1G的数据,若存储设备没有整块的超过1G大小的空间,就无法使用顺序存储,此时要选择链式存储,因为链式存储是随机存储数据,占用的都是存储设备中比较小的存储空间,因此有一定几率可以存储成功。
所以如果集中存储,就采用顺序存储结构,反之分散存储,就用链式存储结构。
结论:
数据的用途不同,选择的存储结构也不同。将数据进行集中存储,有利于后期对数据进行遍历操作;而分散存储有利于后期增加或删除数据。所以,如果后期需要对数据进行大量的检索遍历,就采用集中存储;反之,如果后期对数据进行频繁的增删改,就采用分散存储。
四. 数据结构和算法比较
1. 错误的理解
很多书籍或者教程都把数据结构和算法掺杂起来一起讲,到这很多初学者误认为数据结构就是算法,算法就是数据结构,这种观点是错误的。
科班出身的人会很清楚,在大学中《数据结构》是一门单独课,《算法导论》也是一门单独的课,二者完全是两个独立的学科,如果非要给他俩定义一种关系,那么他俩是互利互赢的,也就是【1+1 > 2】的关系。
2. 二者的职责到底是什么
分析:
通常,每个问题的解决都要经过两个步骤:
(1). 分析问题,从问题中提取有价值的数据,将其存储。
(2). 对存储的问题数据进行处理,最终得出问题的答案。
结论:
(1). 很明显,数据结构负责解决第一个问题,即数据的存储问题,针对数据不同逻辑结构和物理结构,选择最优的数据结构进行存储数据。
(2). 第二问题,就留给算法了,算法从表面来理解,就是解决问题的方法,评价一个算法的好坏在于解决相同问题的情况下,那种算法的效率高,那么我们就说哪个算法好。(这里的效率指的是处理数据、分析数据的能力)。
最终结论:
数据结构解决的是数据存储问题,算法用于处理和分析数据,二者完全是两个不同类目的学科。在解决问题的过程中,数据结构要配合算法选择最优的存储结构来存储数据,而算法也要结合数据存储的特点,用最优的策略来分析并处理数据,由此可以最高效地解决问题。
3. 例子
例如,有这样一个问题,计算“1+2+3+4+5”的值。这个问题我们可以这样来分析:
(1). 计算 1、2、3、4 和 5 的和,首先要选择一种数据存储方式将它们存储起来,通过前面的学习我们知道,数据之间具有“一对一”的逻辑关系,最适合用线性表来存储。结合算法的实现,我们选择顺序表来存储数据(而不是链表),如图下图所示:
(2). 接下来,我们选择算法。由于数据集中存放,因此我们可以设计这样一个算法,使用一个初始值为 0 的变量 num 依次同存储的数据做“加”运算,最后得到的新 num 值就是最终结果。
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。