从零开始的自我提升计划:计算机科学(四)

本系列为作者学习记录
感谢Jack-Cui视频的启发
视频地址:【计算机科学速成课】[40集全/精校] - Crash Course Computer Science

系列文章目录

从零开始的自我提升计划:计算机科学(一)
从零开始的自我提升计划:计算机科学(二)
从零开始的自我提升计划:计算机科学(三)



前言

本文内容包括:

  1. 算法入门-Intro to Algorithms
  2. 数据结构-Data Structures

一、算法入门

算法入门
通常,解决一个问题有许多不同的方法,这些不同的方法称为“算法”,即解决问题的具体步骤。一般来说,所用步骤越少越好,但是有时也会关心其他因素,例如占了多少内存。
记载最多的算法是“排序”,排序一般针对的是数组(Array)。最简单的是选择排序,即从数组中选出最小(最大)的元素,将其放在第一个位置,然后再选出次小(次大)放在第二个位置,不断重复这个过程,直到排序完整个数据。
算法的输入大小运行步骤之间的关系称为复杂度。使用大O表示法,例如上述的选择排序的复杂度即为 O ( n 2 ) O(n^2) O(n2),效率很低。另一种排序算法称为归并排序,例如数组内元素为:

[239, 307, 214, 250, 384, 299, 223, 312]

首先将其不断二分,直到每个数组大小为1,二分过程如下:

# 第一次二分
[239, 307, 214, 250]  [384, 299, 223, 312]
# 第二次二分
[239, 307] [214, 250] [384, 299] [223, 312]
# 第三次二分
[239] [307] [214] [250] [384] [299] [223] [312]

接下来就可以进行归并,归并过程选择归并前的数组内第一个元素进行比较,将更小的放在归并后的数组内。例如在第二次归并时,比较[239, 307]和[214, 250]两个数组内第一个元素的大小,即把214放入归并后数组的第一个位置内,然后再进行比较,此时比较的是[239, 307]和[250]两个数组内第一个元素的大小,不断重复这个过程,即可完成排序,过程如下:

# 第一次归并
[239, 307] [214, 250] [299, 384] [223, 312]
# 第二次归并
[214, 239, 250, 307] [223, 299, 312, 384]
# 第三次归并
[214, 223, 239, 250, 299, 307, 312, 384]

归并算法的复杂度更低,为 O ( n log ⁡ n ) O(n\log n) O(nlogn) n n n为比较+合并的次数, log ⁡ n \log n logn为合并步骤的次数。

另一个经典算法是图搜索,图是用线连接起来的一堆节点,可把图想象为地图,节点为城市,线是公路,每个城市之间的路程不同,用成本或者权重来代称。要计算某两个节点之间的最小成本,最简单的方法即尝试每一种路,计算总成本后排序,这就是蛮力方法,复杂度为 O ( n ! ) O(n!) O(n!)
另一种更简单的算法为Dijkstra算法,这个算法每轮计算总是从成本最低的节点开始。从初始位置开始(成本为0),计算到达相邻节点所需的成本,并记录在相应的节点位置处。然后计算下一个成本最低的节点到达其相邻节点所需成本(此时需要加上当前节点已经耗费的成本),如果相邻节点已经记录了成本,则比较当前所需成本和已记录的成本,将更小的那个成本记录在该节点处。
例如图中,第二轮计算时成本最小的点位KING’S LANDING,从KING’S LANDING到RIVERRUN的成本为25,加上当前节点的成本8,总成本为33,比RIVERRUN记录的成本10要高,因此RIVERRUN存储的成本仍为10。经过一轮一轮的计算,即可得到最小成本,该算法的复杂度为 O ( n 2 ) O(n^2) O(n2)
后面Dijkstra算法有了改进,复杂度降低为 O ( n log ⁡ n + l ) O(n\log n + l) O(nlogn+l) n n n为节点数, l l l是有多少条线,对图中的例子来说,有6个节点9条线,改进前的复杂度为 O ( 6 2 ) = 36 O(6^2) = 36 O(62)=36,改进后的复杂度为 O ( 6 log ⁡ 6 + 9 ) = 13.7 O(6\log 6 + 9) = 13.7 O(6log6+9)=13.7
Dijkstra算法

二、数据结构

数据结构
上节中提到一种基本的结构,数组,也叫列表或者向量。数组内的值是在内存中是连续存储的,访问数组内值,需要使用下标(index)
字符串与数组比较类似,但是它是由字母、数字、标点符号等组成的。在内存中存储字符串时,结尾通常有个表示字符串结尾的符号,NULL或者**\0**。计算机有很多处理字符串的函数,例如strcat将两个字符串连接起来。
在表示矩阵时,通常使用二维数组,即数组内的元素为数组。表示多维矩阵时,增加数组维度即可。
结构体可以将多个变量打包在一起,这些变量类型可以不同,因此结构体可以创造更加复杂的数据结构。例如使用结构体创建一个节点,存放一个变量和一个指针,指针指向内存的地址。将节点连接起来就可生成链表,链表可以是循环的,成为循环链表,也可以不循环,最后一个节点的指针为“NULL”。
队列也是一种使用链表的数据结构,通常有入队和出队操作,入队只能将新的节点放置在队尾,而出队只能从队首操作,即队列具有先进先出(FIFO)的特点。只需要将队列稍作修改,就可形成,栈的特点是后进先出,即出栈和入栈都只能从栈顶开始操作。
将节点的指针改为多个,分别指向不同的节点,就形成了,最顶端的节点称为“根节点”,根节点下属的节点称为“子节点”,子节点的上层称为“母节点”,无子节点的节点称为“叶节点”。若每个节点至多可以有2个子节点,则称为“二叉树”,树的特点是单向连接,只能从根到叶。
倘若想数据随意连接,可以使用“”来表示,上节中连接城市的图就是这种结构,节点之间可以随意指向。
上述为几种最主要的数据结构,在此之上,还有各种变体,例如“红黑树”和“”,不同的数据结构适用于不同的使用场景。

点击文中的“红黑树”和“堆”即可访问响应的资料。
另外这里推荐一个数据结构测试器,使用动画可视化数据结构,便于理解。
链接:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html


总结

本文介绍了算法入门和数据结构的基本内容,参考资料中详细介绍了红黑树和堆的原理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值