翻译:程序员数据结构基础:选择正确的数据结构

本文转载自GameDev.net,仅供学习交流。因为刚刚开始学习翻译,难免有些疏漏,如果有哪些地方翻译的不正确,请不吝告知,万分感谢。

原文链接:http://www.gamedev.net/page/resources/_/technical/general-programming/data-structures-for-pre-college-programmers-choosing-the-right-structure-r2991

网络上的许多初学者还是学生。通常初学者通过在网上看教程,从书上复制代码和尝试一些感兴趣的东西来学习。

这篇文章是初级开发者所需要了解的数据结构基础系列文章中的一篇。前一篇文章分析了非线性数据结构。(Non-Linear Structures.

这篇文章是帮助初学者理解如何选择一个合适的数据结构或者容器类型。

数据结构

在该系列的前几篇文章中说明了最常用的一些数据结构,这里只是一个概括。

线性的结构包括:数组,动态数组和链表。他们之所以是线性的,是因为他们总是呆在你放置他们的地方。数组的随机访问 是非常快的,而且在数组末尾添加和删除数据具有适当良好的性能。如果你频繁地在中间添加或删除数据,链表将是一个非常好的选择。

线性端点数据结构包括:堆和队列等。他们的工作方式与现实世界中的同名操作非常相似。堆,比如一堆木板或者一个数据堆,你可以把东西放在(push)堆的最上面,可以直接用最早面的一块木板或者数据,或者你可以直接拿掉(pop)最上面的一个木板或都数据。队列,像一人排成一个队伍或一个队列数据,以从队尾加入,从队首移除的方式来工作。

非线性数据结构包括:数据字典,有序集和无序集。这些结构是内部非线性的,也就是说你把相关数据插入的顺序和取出数据的顺序是基本无关的。数据字典的工作方式与真正的字典非常相似,它拥有一个关键值(key:用来索引的)和值(value:数据值)。一个有序集(ordered set)跟排序过的只包含关键值(key)不包含值(value)的数据字典一样。至于无序集则是像一个数据的抓斗袋(类似抽奖的暗箱),但无序集这个名字是有点误导性的,实际是他们也是有序的,只是他们排序的方式对我们的使用来说是没有什么用的。这些非线性的数据结构非常适合快速的查找数据。

一个好的数据结构的影响

大多数时候,程序员只是需要遍历整个数据集合。通常,当我们需要从头访问每个数据项时,我们不关心数据内部是怎么排序的。这种常见的情况中,数据结构的选择不是很大的问题。

当有疑问的时候最普遍的选择是动态数组,它可以变成任意的大小,中规中矩,在后期有需要时也可以很容易的转换成其它的数据结构。

但有时候他也有一些问题。

在游戏中,一个很常见的问题就是寻路。你需要找出一个从a到b的路径。最常见的寻路算法是a星算法。在a星算法中你需要一个数据结构来存储部分路径。这个结构应该是排序过的,这样可以把我们最最想要的路径摆放在容器的最前面方便我们使用。如果该路被检测后发现不是一个完整的路径,该算法则会使他成为一个更大的路径的一部分并加入的相当的容器中。

使用动态数组作为a星算法的容器将会是一个糟糕的选择,原因如下:

  1. 从动态数组的开头移除一个数组是我们所能执行最低效的一个操作。
  2. 当加入了一个新的路径,我们对动态数组进行重新排序是非常低效的。

如果记得之前所说的,还有是这种类型的访问的最优化的数据结构。我们可以移除最前面的数据,把数据从最后面插入,并自动重排索引出最佳的路径。优先队列是a星算法容器类型的一个好的选择。它通常都内置在语言内部,并通过完善的测试。

根据使用的模式来写选择

使用什么样的数据结构,通常依据你所使用的设计模式。

动态数组 -- 默认的选择

当有疑问的时候,使用动态数组。在c++叫做vector,在java中叫做ArrayList,在c#中叫做List。

动态数组通常可以符合使用要求。它大多数操作都有好的性能 ,剩余的操作性能也不差。如果你发现你需要其它的数据结构,动态数组也是最容易进行修改的。

堆 -- 只有一端

如果你只在单独的一端添加或删除。使用堆,在c++中是stack,在java和c#中都叫Statck。

有许多算法依赖堆来实现。我的第一个反应就是双堆计算器(two-stack calculator)。数学问题像汉诺塔也可以通过堆来解决。当然,在游戏编程中,你可能用不到他们。

游戏工具经验解析数据。解析器在很大程度上依赖堆数据结构来保证配对项匹配正确。

如果你正在使用各种各样的ai类型。你可以发现堆数据结构对于自动机家族中的自动下推器是难以估计的实用。

队列 -- 先进先出

如果你需要从两端进行增删数据,那你你可以使用队列或者双端队列。在c++中叫做queue(队列)或者deque(双端队列).在java中你可以使用Queue或者Deque接口,都是基于LinkList实现的。在c#中只有一个Queue类型,没有内置双端队列(deque)。

如果你需要保证某些重要的东西第一时间被处理,但除非所有的事情都有序的发生,并且按优先级顺序完成。这时你可以使用优先级队列来处理,在c++中称为priority_queue.在java中称为PriorityQueue.C#中你需要自己来实现这个优先级队列。

非线性结构 -- 快速索引

如果你需要创建一个稳定的数据结构,并频繁的进行随机查找,那么你需要使用非线性数据结构。

非线性数据结构有的保存一对数据,有的保存独立的数据。有的是对用户友好的排序,有的是对计算机友好的排序。如果要列出他们之间的所有组合,又将是一篇文章。实际上,那些在之前的文章中已经详细的描述过了。 对于这些非线性结构哪些满足特定的需求,可以查看之前的关于非线性数据结构的文章

链表 -- 频繁有序的修改

如果你需要频繁的在容器中间进行操作数据(增删),而且你只需要顺序的遍历列表。你可以使用链表,在c++中称为list, 在java和c#中称为LinkedList。

当数据需要频繁的增删,并且在增删后必须保持有序状态时,链表是一个非常好的容器选择。

结论

选择正确的数据结构可以让算法的性能是非常大的改善。

理解主要的数据结构,包含他们的优缺点可以帮助你选择你所需要的数据结构。

我建议你们深入的研究学习这些主要的数据结构。深入学习这些数据结构的计算机科学学位课程通常会持续数星期内。

希望你已经了解了主要的数据结构,可以在没有进行数周深入的学习这些数据结构时可以选择一个好的数据结构。

这系列的文章已经结束了,感谢阅读。

本文转载自GameDev.net,仅供学习交流。因为刚刚开始学习翻译,难免有些疏漏,如果有哪些地方翻译的不正确,请不吝告知,万分感谢。

原文链接:http://www.gamedev.net/page/resources/_/technical/general-programming/data-structures-for-pre-college-programmers-choosing-the-right-structure-r2991

时间: 2024-08-07 04:33:39

翻译:程序员数据结构基础:选择正确的数据结构的相关文章

黑马程序员——java基础——选择、循环

-----------android培训.java培训.java学习型技术博客.期待与您交流!------------ 今天回顾了一下JAVA学习中的选择语句,循环语句,和数组,在JAVA中的选择语句和C语言中差不多有if.switch一个if语句由一个后跟到一到多个语句的布尔表达式组成.顺序结构的程序语句只能被执行一次.如果您想要同样的操作执行多次,,就需要使用循环结构. Java中有三种主要的循环结构: while循环 do…while循环 for循环 for循环的用法 先来说说哦For循环

黑马程序员_JAVA 基础加强学习笔记

一.面向对象 (一)继承  1.继承的好处: (1) 提高了代码的复用性. (2) 让类与类之间产生了关系,提供了另一个特征多态的前提. 注意: 子类中所有的构造函数都会默认访问父类中的空参数的构造函数,因为每一个子类构造内第一行都有默认的语句super();  如果父类中没有空参数的构造函数,那么子类的构造函数内,必须通过super语句指定要访问的父类中的构造函数. 如果子类构造函数中用this来指定调用子类自己的构造函数,那么被调用的构造函数也一样会访问父类中的构造函数. 2.final特点

黑马程序员——Java基础---集合框架工具类

黑马程序员——Java基础<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------ 一.概述 Java为操作Set.List和Map提供了一系列工具类,主要有Collections和Arrays.这两个工具类的特点:类中的方法都是静态的,不需要创建对象,直接使用类名调用即可.Collections:是集合对象

黑马程序员-正则表达式基础

正则表达式是一种描述字符串集的方法,它是以字符串集中各字符串的共有特征为依据的.正则表达式可以用于搜索.编辑或者是操作文本和数据.它超出了 Java 程序设计语言的标准语法,因此有必要去学习特定的语法来构建正则表达式.正则表达式的变化是复杂的,一旦你理解了它们是如何被构造的话,你就能解析或者构建任意的正则表达式了..正则表达式由一些普通字符和一些元字符组成. 普通字符包括大小写的字母和数字,而元字符则具有特殊的含义.在最简单的情况下,一个正则表达式看上去就是一个普通的查找串.例如,正则表达式"a

浅谈程序员的行业选择---程序人生

引言 本篇博文接着许久之前的一篇博文<浅谈程序猿的职业规划,看你如何决定自己的未来吧.>,继续探讨一下程序员行业相关的内容. 行业的选择不仅对于程序员来说非常重要,对任何一个人来说都是一样的.只不过对于程序员来说,行业更容易被忽略.从程序员每天热议的话题就能看出来,大部分的热议话题都是C#和Java哪个更牛B,或者IOS和Android哪个挣得钱多,很少看到程序员去讨论两个行业谁更有发展前景. 鉴于此,今天我们就来着重讨论一下程序员行业的选择,行业和语言一样,没有谁优谁劣,只是一种选择罢了.

黑马程序员——java基础——集合(Collection)

 黑马程序员--java基础--集合(Collection) ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 集合框架的构成及分类,如下图: 1.为什么出现集合类? 面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式. 2.数组和集合类同是容器,有何不同? 数组虽然也可以存储对象,但长度是固定的:集合长度是可变的.数组中可以存储基本数据类型,集合只能存储对象. 3.

黑马程序员--java基础学习笔记5

黑马程序员--java基础学习笔记6 一.笔记内容概述: 数组-第二种定义格式.数组-常见操作-遍历-最值-选择排序-冒泡排序-排序位置置换代码提取.数组-排序的性能问题.数组-常见功能-查找-折半查找.进制转换-查表法-整合. 二.常用内容介绍: 1.数组初始化的三种方式: int[] arr = new int[3]; int[] arr = new int[]{1,2,3}; int[] arr = {1,2,3}; 2.查表法: 如果数据中出现了对应关系,而且对应关系的一方是有序的数字编

黑马程序员——集合基础知识(Collection)

集合基础知识 数组:长度固定,可存基本数据和对象. 集合:只能放对象,不固定.容器也有共性,不断抽取成一个体系,集合框架.参阅顶层创建底层.顶层是collection.collection里有两个常见的接口,List和Set.常见集合有Arraylist,linkedlist,vector,hashSet TreeSet.为什么会出现这么多的容器呢,因为每一个容器对数据的存储方式都有不一样,.这个存储方式称之为数据结构!!因为他们的特点不一样 list因为有脚标存储和删除的效率很低,Set的效率

黑马程序员——集合基础知识(Map)

Map概念 要同时存储两个元素,他们之间有映射关系,每个键不能重复,每个键只能映射到一个值. 存储键值对,并且键是唯一的. 1.添加. put()如果添加的键原来有值,后添加的值会覆盖前面的值,并返回之前的值. 2.删除 remove()按键删除. 3.判断 4.获取 get(object key) size() value()拿值value返回的是值的集合... HashTable 底层是哈西数据结构,不可以存入null键null值,线程同步. HashMap 底层是哈西表数据结构,允许使用n