算法是否真的摧毁了一款优秀游戏?数据结构的重要性究竟如何?

发表时间: 2019-12-29 08:08


来源 | 异步

前段时间大火的国产游戏——《太吾绘卷》,由于创新的玩法和精良的制作一度广受好评,然而随着玩家游戏的深入和时长的积累,发现该游戏在玩的过程中游戏外的问题很多很多。


首先是存档速度慢,然后是密集的计算导致功耗大量增加,风扇速度高居不下,甚至在高配置设备中也变得越来越卡。

究其原因,还是开发人员对于算法的理解问题。


该游戏存档是用的json,太吾绘卷在每个月存档时,都要把所有的数据在磁盘上重写一遍。实际上,大多数游戏公司正确的做法是只写入变化的部分而不会全量写入,而太吾绘卷的做法是把很多不变的,预设好的东西也全部重新写入,必然导致存档时占用了极大的空间。


同时,存档中有大量的0,这说明开发者不知道什么叫“稀疏矩阵”,结合之前的全量写入,这无疑又加剧了存档缓慢的问题。


所以算法和数据结构有多重要的呢,它足以让一款大火的游戏变得不再具有吸引力,哪怕你其他方面做得再好。带来了这么大的影响,恐怕游戏开发组接下来应该考虑更换程序员的事情了。

著名计算机科学家尼古拉斯·沃斯(Niklaus Wirth)有一句在计算机领域人尽皆知的名言“算法+数据结构=程序”(Algorithm+Data Structures=Programs)。


算法这么重要却没有引起国内顶级程序员的重视,不得不说这是一个遗憾。



其实,要想学习算法,方法大于努力,以下三个思路和方法可以指导你更好的学习算法:


一.记住算法思想,记住算法结构。


这个是数据结构与算法学习最基础的部分。


如果你把算法和数据结构系统的过了一遍,那你应该能够明确这些基本的概念和一些初步的延申问题,什么是数组,堆栈,队列,链表,字典树以及哈希表以及相关的问题,这里所说的记住,是指在自己的脑海中形成长久的记忆。例如以下实用问题:

常见的堆栈面试问题

· 使用堆栈计算后缀表达式

· 对堆栈中的值进行排序

· 检查表达式中的括号是否平衡


那么,记住数据结构又需要记住哪些呢?

第一步:记住数据结构最直观的东西


第二步:记忆某个数据结构的同时,还要记住数据结构的定义,性质与特点。例如在学习哈夫曼树的时候。


定义是WPL最小的二叉树。特点:(1)没有度为1的结点(2)n个叶子结点的哈夫曼树共有2n-1个结点(3)哈夫曼树的任意非叶节点的左右子树交换后仍是哈夫曼树。


在知道它的定义后,我们可以自己去设计一个算法。如果自己没想到,在看到先人的解决办法后,更要随手存下来,去记住它。



二、用编程语言实现数据结构的算法


很多时候,理解一个算法后,很容易在纸上去模拟一个算法的实现过程。


但,具体实现,则是另一回事。一定得先自己思考,然后再去看书中给的编程语言实现。这一过程已经不属于“数据结构与算法”的内容了。而是你综合素质的体现,如何真正理解问题和用编程技巧实现,很考验自己。


这一过程,很难靠记忆。需要在不断敲代码的过程中去体会一些直觉上的东西。如何用递归解决问题,如何使用循环,如何使用"哨兵”等等等等。当然,敲完后需要去思考总结,看看能不能总结出一些”小套路“并记住。


总之,实践出真知


三、记住特定情况特定的算法搭配


每介绍一种数据结构,都可以联系一个实际问题来作为“引子”,回答了“这种数据结构为什么会出现”。

比如上述案例中提到的稀疏矩阵,通俗地说,如果边的数量接近于与顶点的数量呈线性关系,那么这个图就是稀疏图,例如,具有n个顶点和O(n log n)条件的图一般被认为是稀疏图。


这些东西,我们也须理解记忆。每一数据结构都有其特性,去解决某一类问题,我们需要去记忆,去感悟。


威著作,助力学习



本书是作者Tim Roughgarden(斯坦福大学的教授,主要教授的课程有计算机科学、管理科学与工程。著有图书《算法详解(第1卷):算法基础》)结合在斯坦福大学教授算法课程的实际经验编写的系列教程中的第二本。


主要介绍图搜索及其应用,最短路径算法以及一些数据结构(如堆、搜索树、散列表和Bloom过滤器)的应用和实现。


本书是作者Tim Roughgarden(斯坦福大学的教授,主要教授的课程有计算机科学、管理科学与工程。著有图书《算法详解(第1卷):算法基础》)

结合在斯坦福大学教授算法课程的实际经验编写的系列教程中的第二本。

主要介绍图搜索及其应用,最短路径算法以及一些数据结构(如堆、搜索树、散列表和Bloom过滤器)的应用和实现。


查看目录

第1章 图的基础知识

1.1 基本术语

1.2 图的一些应用

1.3 图形的度量

1.3.1 小测验1.1邻接矩阵

1.4.3 和小测验1.3零代价的基本算法


2.1.3 高层思路

2.2.2 BFS正确性和运行时间

2.2.5 的答案

2.3 计算连通分量

2.3.1 (无向图连通分量)算法

2.3.4 UCC小测验2.2的伪码

2.4.3 什么时候存在拓扑顺序

2.5.3 的拓扑排序

2.5.5 小测验2.3为什么要使用深度优先的搜索

2.6.3 一个例子

2.6.6 和小测验2.6蝴蝶结

2.7.3 一些前提条件

3.1.3 的答案

3.2 Dijkstra算法

3.2.1 一种虚假的简化

3.3.2 Dijkstra选择正确的数据结构

4.1.2 其他操作

4.3 堆的应用

4.3.1 应用:中位值维护

4.4 Dijkstra算法的提速

4.4.1 维持不变性

4.4.4 数组形式的堆

4.5.3 操作

4.5.4 操作

4.6 本章要点

4.7 章末习题

挑战题

编程题

第5章 搜索树

5.1 有序数组

5.1.1 搜索树的属性

5.3.2 (高度)时间内实现Search

5.3.4 和Max

5.3.5 时间内实现OutputSorted操作

5.3.8 强化的搜索树支持Select的答案

*5.4 平衡搜索树

5.4.1 的答案

*6.4 更多的实现细节

6.4.1 负载和性能

6.4.2 管理散列表的负载

6.4.3 选择散列函数

6.4.4 选择冲突解决策略

6.4.5 小测验6.6的答案

6.5 布隆过滤器的基础知识

6.5.1 布隆过滤器支持的操作

6.5.2 布隆过滤器的应用

6.5.3 布隆过滤器的实现

*6.6 布隆过滤器的启发式分析

6.6.1 启发式假设

6.6.2 部分位被设置为1

6.6.3 假阳性率

6.6.4 结束语

6.6.5 小测验6.7的答案

6.7 本章要点

6.8 章末习题

编程题

附录A 快速回顾渐进性表示法


部分习题答案