数据结构

什么是数据结构?

天涯浪子 提交于 2020-02-26 11:39:36
本篇文章主要来介绍什么是数据结构。 首先让我们来看一张图片: 数据存储于计算机的内存中。内存如上图所示,形似排成 1 列的箱子,1 个箱子里存储 1 个数据。 数据存储于内存时, 决定了数据顺序和位置关系的便是数据结构 。 其实在我们生活中用到很多数据结构的知识,那么举一个我们生活中的栗子: 首先举一个从上往下顺序添加举个简单的例子。假设我们有1个电话簿——虽说现在很多人都把电话号码存在手机里,但是这里我们考虑使用纸质电话簿的情况——每当我们得到了新的电话号码,就按从上往下的顺序把它们记在电话簿上。 假设此时我们想给张飞打电话,但是因为数据都是按获取顺序排列的,所以我们并不知道张飞的号码具体在哪里,只能从头一个个往下找(虽说也可以从后往前找或者随机查找,但是效率并不会比从上往下找高)。如果电话簿上号码不多的话很快就能找到,但如果存了500个号码,找起来就不那么容易了。 再比如我们可以按姓名的拼音顺序对电话簿进行排列,接下来,试试以联系人姓名的拼音顺序排列吧。因为数据都是以字典顺序排列的,所以它们是有结构的。 使用这种方式给联系人排序的话,想要找到目标人物就轻松多了。通过姓名的拼音首字母就能推测出该数据的大致位置。 那么,如何往这个按拼音顺序排列的电话簿里添加数据呢?假设我们认识了新朋友柯南并拿到了他的电话号码,打算把号码记到电话簿中。由于数据按姓名的拼音顺序排列

数据结构与算法:链表

谁都会走 提交于 2020-02-26 10:29:37
一、链表和数组的区别 链表与数组相似,但链表是一种比数组稍微复杂的数据结构。数组需要一块连续的内存空间来存储数据,对内存的要求比较高,而链表则不需要,它通过「指针」将不连续的内存块串联起来。如果要申请一个 100MB 大小的数组和链表,当内存中没有连续的,或者没有足够大小的空间时,数组便会申请失败,而链表不会。 链表有很多种结构,常见的有: 单链表 、 双向链表 、 循环链表 。 二、单向链表 链表通过指针将不连续的内存块串联在一起使用,我们把其中的内存块称为「结点」,而为了将所有的结点串起来,链表中的结点除了存储数据之外,还会用指针记录链表结点的下一个结点的地址,我们把这个记录下一个结点的地址的指针叫做「后继指针next」,整个单链表如下图所示。 其中第一个结点和最后一个结点是比较特殊的,通常分别把它们称为「头结点」和「尾结点」。头结点用来记录链表的基地址,有了它就能遍历得到整个链表。尾结点并不指向任何结点,而是指向空地址 null ,表示链表上的最后一个结点。 与数组不同,链表的插入和删除操作并不需要大量的数据搬移,它只需要考虑相邻结点的指针改变,对应的时间复杂度为 O(1) 。同样,链表的访问元素操作也没有数组那样直接用首地址和下标通过寻址公式直接得到对应的内存地址,链表需要通过从指针一个一个结点地遍历,直到找到相应的结点。因此链表的随机访问时间复杂度为 O(n) 。 三

数据结构的基本概念

喜夏-厌秋 提交于 2020-02-26 08:15:27
数据结构 一、线性表 1. 顺序存储结构(顺序表) 一个线性表是n个具有相同特性的数据元素的有限序列。数据元素是一个抽象的符号,其具体含义在不同情况下不同。 2. 链表 链表里面节点的地址不是连续的,而是通过指针进行链接的。 二、哈希表 1. 哈希的导入 数组的特点是:寻址容易,插入和删除困难; 链表的特点是:寻址困难,插入和删除容易。 那么,我们综合两者的特性,做出一种寻址容易,插入和删除也容易的数据结构,这就是哈希表。 下面是哈希表的一种实现方法:拉链法。 在图的左边是一个数组,数组的每个成员包括一个指针,指向一个链表的头,根据元素的特征将元素分配到不同的链表中去,我们也是根据这些特征,找到正确的链表,再从链表中找到正确的元素。 2. 哈希表 哈希表就是把Key通过一个固定的算法函数——哈希函数,转换成一个整形数字,然后就将该数字对数长度进行取余,取余结果当作数组的下标,将value存储在以该数字为下表的数组空间里。 3. 哈希表的优缺点 优点 时间少:无论哈希表中的数据量,我们在操作时的插入,删除,查询都只需要O(1)的时间级。 速度快:在日常程序中,在特定时间内哈希表的查找速度总比树快。 编程简单:相对树来讲,哈希表编程实现相对简单。 缺点 哈希表基于数组,数组创建后难以扩展,故当哈希表被基本填满时,性能下降会非常严重,所以在创立哈希表时我们必须清楚表中将要存储多少数据。

五分钟自学编程:怎样才能学好笔试面试最爱考察的算法

醉酒当歌 提交于 2020-02-26 07:34:42
原创声明 本文作者:黄小斜 转载请务必在文章开头注明出处和作者。 本文思维导图 什么是算法 上回我们有一篇文章,讲述了作为一个新人程序员,如何学习数据结构这门课程,其实呢,数据结构和算法是息息相关的,为什么这么说呢,因为数据结构本身只是一个载体,而在数据结构之上产生作用和输出价值的东西其实是算法。 比如数据结构里的数组,看似非常简单的数据结构,却可以支持很多复杂的算法,比如动态规划,比如DFS和BFS,再比如字符串算法、二叉树算法等等。那么算法到底是什么东西呢,不妨让我们来看看官方的介绍。 根据百度百科的介绍,算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。 其实,算法的本质就是给你一组输入,运算之后给你一组输出,因此,算法帮人们解决很多问题把抽象的问题具体化,把一个问题转化成另外一个问题。 认识算法的N个阶段 我第一次遇到算法题,还是在我考研复习数据结构的时候,那个时候我看到的算法题其实都是很基础的题目,比如把数组中的两个元素置换,把两个链表合并成一个,但对于我来说已经是很有难度的事情了,那时候我连伪代码是什么都还不懂。 第二次认识算法,还是在研究生期间找实习工作的时候

数据结构之队列

こ雲淡風輕ζ 提交于 2020-02-26 06:22:14
文章来源: http://blog.seclibs.com/数据结构之队列/ 上一篇文章说了一种“功能受限”的顺序表——栈,现在再来说一个 “功能受限”的顺序表 —— 队列 (queue)。 队列也是一个常用的数据结构,在大部分资源有限的情况下,当没有空闲资源的时候,基本上都是使用队列这种数据结构来实现请求排队的。 队列,顾名思义,就是排的一条队,比如在买票的时候排的一条队伍,先来的先买,后来的后买,不允许插队,也就是先进先出的方式,栈是后进先出的方式。 栈支持入栈(push)和出栈(pop)两种操作,队列也是类似的,支持入队(enqueue)和出队(dequeue)两种操作,入队就是在尾部追加一个数据,出队就是在头部取走一个数据。 队列作为一种非常基础的数据结构,应用是非常广泛的,特别是一些具有某些额外特性的队列,比如循环队列、阻塞队列、并发队列。它们在很多偏底层系统、框架、中间件的开发中,起着关键性的作用。 队列在实现上跟栈也是类似的,可以使用数组或链表来进行实现,使用数组实现的叫做顺序队列,使用链表实现的叫做链式队列。但是栈只需要一个栈顶指针top就可以了,队列则需要头部head指针和尾部tail指针两个来标识。 比如说a、b、c、d四个数据入队以后,head指针将指向下标为0的位置,tail指针指向下标为4的位置 当进行两次出队的操作后,head指针将指向下标为2的位置

[golang] 数据结构-鸡尾酒排序

醉酒当歌 提交于 2020-02-26 05:05:21
吐个槽 又是一个不正经取名的排序算法。真要说和鸡尾酒间的关系,大概就是想喝到鸡尾酒(得到排序好的队列)就要摇晃酒杯让不同的成分混合均匀(向两个方向冒泡排序) 原理 鸡尾酒排序(Cocktail Sort)是 冒泡排序 的一种优化算法。原本的冒泡排序只能在一轮中挑出一个值移动到最后,而鸡尾酒则可以在一轮里挑最大的移到最后,再挑最小的移到最前面。实际上就是先正向进行一轮普通的冒泡排序,然后再逆向进行一轮反向冒泡,每轮冒泡都缩小一点范围。 复杂度 最好情况是正序排列的数列O(n),最坏情况是逆序O(n^2),平均还是O(n^2)。空间复杂度都是O(1)。 排序过程 特别找来一张图,方便理解。注意看图中红色标记的元素,每次向右都是把最大的元素交换到后面,向左都是把最小的交换到前面。 代码 package main import ( "time" "fmt" "math/rand" ) func main() { var length = 10 var list []int // 以时间戳为种子生成随机数,保证每次运行数据不重复 r := rand.New(rand.NewSource(time.Now().UnixNano())) for i := 0; i < length; i++ { list = append(list, int(r.Intn(1000))) } fmt

[golang] 数据结构-快速排序

落花浮王杯 提交于 2020-02-26 05:05:15
快速排序是个非常经典、高效、常用的排序算法。很多语言标准库里的排序算法都有用到它。 原理 快排原理其实比较简单,就是将原本很大的数组拆成小数组去解决问题。 要拆就得找个拆的位置。如果吧这个位置称为支点,那么快速排序问题就变成了不断的去找到拆分的支点元素位置。 通常找支点就是以某个元素为标准,通过交换元素位置把所有小于标准的元素都移到一侧,大于的移到另外一侧。移动元素的逻辑就是分别从最右侧元素向左找到比指定元素小的位置,再从最左侧开始向右找比指定元素大的位置。如果两个位置不相同就交换两个位置,在继续分表从两头相向寻找。找到合适的位置就是我们需要的支点。支点两边的元素再各自重复上面的操作,直到分拆出来的子数组只剩一个元素。分拆结束,顺序也就拍好了。 那么问题来了,以哪个元素为标准去比较呢?比如可以选第一个元素。 复杂度 理想情况下找到的支点可以把数组拆分成左右长度相近的子数组,此时时间复杂度为O(n*logn) 而最差情况则是每次找到的支点元素都在某一次,导致另一侧完全浪费,寻找支点的过程也浪费。这个时候用时会达到O(n^2)。 由于会打乱相同元素原有的顺序,所以快排也是一个不稳定排序。所以常用在普通类型数据的排序中。 代码实现 package main import ( "time" "fmt" "math/rand" ) func main() { var length = 10

数据结构与算法系列四(单链表)

China☆狼群 提交于 2020-02-26 03:09:12
1.引子 1.1.为什么要学习数据结构与算法? 有人说,数据结构与算法,计算机网络,与操作系统都一样,脱离日常开发,除了面试这辈子可能都用不到呀! 有人说,我是做业务开发的,只要熟练API,熟练框架,熟练各种中间件,写的代码不也能“飞”起来吗? 于是问题来了:为什么还要学习数据结构与算法呢? #理由一: 面试的时候,千万不要被数据结构与算法拖了后腿 #理由二: 你真的愿意做一辈子CRUD Boy吗 #理由三: 不想写出开源框架,中间件的工程师,不是好厨子 1.2.如何系统化学习数据结构与算法? 我想好了,还是需要学习数据结构与算法。但是我有两个困惑: 1.如何着手学习呢? 2.有哪些内容要学习呢? 学习方法推荐: #学习方法 1.从基础开始,系统化学习 2.多动手,每一种数据结构与算法,都自己用代码实现出来 3.思路更重要:理解实现思想,不要背代码 4.与日常开发结合,对应应用场景 学习内容推荐: 数据结构与算法内容比较多,我们本着实用原则,学习经典的、常用的数据结构、与常用算法 #学习内容: 1.数据结构的定义 2.算法的定义 3.复杂度分析 4.常用数据结构 数组、链表、栈、队列 散列表、二叉树、堆 跳表、图 5.常用算法 递归、排序、二分查找 搜索、哈希、贪心、分治 动态规划、字符串匹配 2.考考你 在上一篇【数据结构与算法系列三(数组)】中,我们知道了最基础的数据结构:数组

Skr-Eric的数据结构课堂(一)-- 概述、线性结构的基本实现模型、容器和二叉树结构

半城伤御伤魂 提交于 2020-02-26 02:07:29
数据结构概述 概念: 数据结构:计算机存储和组织数据的方式. 分为三层: 抽象层 (逻辑结构):数据之间(与计算机无关)的逻辑结构. 分为: 线性结构/非线性结构 其中,非线性结构分为:集合结构/树状结构/网状结构. A.线性结构(有序性/一对一的前后关系) 结构中必须存在唯一的首元素 结构中必须存在唯一的尾元素 除首元素外,结构中每一个元素有且只有一个前驱元素 除尾元素外,结构中每一个元素有且只有一个后继元素 B.集合结构(无序性/松散的) 确定性:要么属于集合要么不属于集合,不存在可能属于或者可能不属于的情况. 无序性:无前后顺序关系. 唯一性:各元素互不相同. C.树状结构(一对多的父子关系) 结构中必须存在唯一的根节点 除根元素外,结构中每一元素有且只有一个前驱元素 除叶元素外,结构中每一元素可拥有一个或多个后继元素 D.网状结构(多对多的映射关系) 结构中每一元素都可拥有任意数量的前驱元素和后继元素 结构中任意两个元素之间均可建立关联 逻辑层 (物理结构):数据具体在计算机内存中存储方式. 1.顺序存储结构:把逻辑上相邻的元素存储在相邻的物理内存位置中. 优缺点:节省内存空间/方便随机访问/增加或删除元素复杂/降低存储空间的利用率 2.链式存储结构:把逻辑上相邻的元素存储放在不连续的物理内存位置中,通过存放下一数据的链接域连接起来. 优缺点:浪费内存空间/随机访问不方便