数据结构和算法

 目录

阶段一

       第一节:时间复杂度和空间复杂度

       第二节:线性表→顺序表→链表 逐个击破

       第三节:从多个角度分析顺序表、链表的区别和特点 

       第四节:顺序表剖析及利用数组手撸“动态数组ArryList”

       第五节:链表剖析及自己手撸“单链表”实现基本操作(初始化、增、删、改等)

       第六节:手撸“循环链表”及约瑟夫问题的解决

       第七节:栈简介、手撸顺序栈、手撸链栈和栈的应用

       第八节:队列简介、手撸顺序队列、手撸链队列和队列的应用

       第九节:树与二叉树深度剖析(一)

       第十节:树与二叉树深度剖析(二)

       第十一节:xxxxxxxxxxxxxxxxx

 

阶段二:用TS编写数据结构和算法

   第一节:邂逅数据结构和算法、线性结构、数组、栈详解

   第二节:队列详解和面试题剖析

   第三节:链表详解和面试题剖析

   第四节:时间、空间复杂度的详解(大O表示法)

   第五节:哈希表详解(哈希函数、增删改查、扩容/缩容、质数容量优化)

   第六节:树详解(各种概念术语、二叉搜索树的封装)

   第七节:图结构详解(结构封装、添加定点/边、广度/深度优先遍历)

   第八节:高阶链表详解(循环链表、双向链表)

   第九节:堆结构详解(上滤、下滤、最大堆、最小堆、二叉堆)

   第十节:高阶队列详解(双端队列、优先级队列)

   第十一节:平衡树、AVL树(简介、旋转详解、代码实操)

   第十二节:红黑树性质、相对平衡的原理、与AVL树的区别、手写红黑树

   第十三节:排序算法详解1(认识排序、冒泡、选择、插入排序)

   第十四节:排序算法详解2(归并排序、快速排序、堆排序)

   第十五节:排序算法详解3(希尔排序、计数排序、桶排序、基数排序)--未完

   第十六节:各种排序算法总结和性能测试

   第十七节:动态规划详解之斐波那契数列(递归、记忆搜索、动态规划、状态压缩)

   第十八节:动态规划面试题(爬楼梯、买卖股票时机、最大子数组和)

   第X节:xxxxxxxxxxxxxxxx

   第X节:xxxxxxxxxxxxxxxx

   第X节:xxxxxxxxxxxxxxxx--未完

   第X节:xxxxxxxxxxxxxxxx

 

 

阶段三:LeetCode刷题

   第一节:字符串相关(最长公共前缀、无重复最长子串、最长回文子串)

   第二节:栈相关(二叉树展开为链表、逆波兰表达式、两栈实现队列结构)

   第三节:队列相关(滑动窗口最大值、)

   第四节:链表相关(删除倒数第N节点、相邻位置交换、反转链表)

   第五节:二叉树相关(反转二叉树[递归/栈]、最大路径和)

   第六节:动态规划相关(不同路径、礼物最大价值、最长递增子序列)

   第七节:二叉树的先序、中序、后续遍历的多种递归写法

   第X节:xxxxxxxxxxxxxxxx

   第X节:xxxxxxxxxxxxxxxx

   第X节:xxxxxxxxxxxxxxxx--未完

   第X节:xxxxxxxxxxxxxxxx

 

 

 

一. 什么是数据结构

必备网址: 

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 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 

 

posted @ 2020-03-23 14:32  Yaopengfei  阅读(921)  评论(1编辑  收藏  举报