(一)分类
数据结构分为5种。
1. 通用数据结构:数组,链表,树,哈希表
2. 专用数据结构:栈,队列,优先级队列
3. 排序:插入排序,希尔排序,快速排序,归并排序,堆排序
4. 图:邻接矩阵,邻接表
5. 外部存储:顺序存储,索引文件,B-树,哈希方法
(二)通用数据结构
若想存储真实世界中的类似人事记录,存货目录,合同表或销售业绩等数据,则只需一般用途的数据结构。如:数组,链表,树,和哈希表。它们被称之为通用的数据结构是因为它们通过关键字的值来存储并查找数据(而栈只允许存储一定的数据项)
通用数据库可以按照速度的快慢来分类:
数组和链表是最慢的,书相对较快,哈希表是最快的。
但使用最快的不一定是最好的,哈希表要求预先知道要存储多少数据,数据对存储空间的利用率也不是非常高。平衡树编程起来很麻烦。
数组:
当存储和操作数据库时,在大多数情况下数组是首先应该考虑的结构。数组在下列情况下很有用:
1. 数据量比较小
2. 数据量的大小事先可预测
如果存储空间足够大的话,可以放松第二条,创建一个足够大的数组来应付所有可
预见的数据输入。
如果插入速度很重要的话,使用无序数组。如果查找速度很重要的话,使用有序数组,并用二分查找。数据元素的删除总是很慢的,这事因为要填充空出来的单元,
链表:
如果存储的数据量不能预知或者需要频繁地插入,删除元素时,考虑使用链表。当有新的元素加入时,链表就开辟新的所需要的空间,所以它甚至可以占满全部可用的内存,在删除过程中没有必要像数组那样添补“空洞”。
在一个无序的链表中插入一个元素时是相当快的,查找和删除很慢,因此与数组一样,链表最好也应用于数据量相对较小的情况。
二叉搜索树
当确认数组和链表过慢时,二叉树是最先应该考虑的结构。树可以提供快速的O(logN)级的插入,查找和删除。遍历的时间复杂度是O(N)级的,这是任何数据结构遍历的最大值。
对于遍历一定范围内的数据可以很快得出访问数据的最大值和最小值。
对于程序来说,不平衡的二叉树要比平衡二叉树简单得多,但不幸的是,有序数组能将他的性能降至O(N)级,不比一个链表好多少,然而如果可以保证数据时随机进入的,就不需要用平衡二叉树。
二叉搜索树的特点:
1. 一个节点的左子节点的关键值小于这个节点,右子节点比这个节点大。
2. 查找key节点:查找从根节点开始,比较key与当前节点的大小(current),若key>current,current走向右边,否则走左边,直到找到key为止。
3. 插入,:首先确定要插入的位置,这和2类似,插入的值称为叶子节点。
4. 删除:被删除的节点分三种情况,是叶子节点,有一个子节点,有两个子节点。删除叶子节点只需把该节点改为null就可以了。删除有一个子节点的节点:这个节点有两个连接,连向父节点和连向它唯一的子节点。需要从这个序列中剪断这个节点,把它的子节点直接连到他的父节点上。当删除有两个子节点的节点时,用它的中序后继结点来代替它。找后继节点就是找比初始节点关键值大的节点集合中最小的一个。即先找到右子节点,然后一直找左子节点直到最后。而这个后继结点一定没有左子节点。
平衡搜素树:
在众多的平衡树中,红--黑树和2-3-4树,他们都是平衡树,并且无论插入数据是否有序,
他们都能保证性能为O(logN).。然而对编程来说,这些平衡树也很有挑战性的,其中最难的是红--黑树。他们也应用了附加存储而产生额外耗费,这对系统或多或少有些影响。
哈希表
哈希表的一个重要的概念是如何把关键字转换成数组下标。在哈希表中是通过哈希函数来解决的。哈希化解决冲突有两个方案:开放地址法和链地址法。
开放地址法:
线性检测:就是线性查找空白单元。即从要插入的位置的数组下标一直递增,直到找到空位。另外,哈希函数必须把关键字的范围压缩到数组的范围。即:key%arraySize;
二次探测:距离:X+12,X+22,X+32,X42,X+52等等,但容易产生二次聚集
在哈希化:让步长(constant)的范围限制在1到constant,stepSize=constant-(key%constant)
哈希表在数据存储结构中速度最快,这使他成为计算机而不是人与数据交互时的必要,哈希表通常用于拼写检查器和作为计算机语言编译器的符号表,在这些应用中,程序必须在几分之一的时间里检查上千的词或符号。
当人而不是计算机初始化操作数据的存储时,哈希表会很有用。正如前文所提到的,哈希表对数据的插入的顺序并不敏感,因此可以取代平衡树,但是哈希表的编程却比平衡树简单多了。
哈希表需要有额外的存储空间,尤其是对于开放定址法,因为哈希表用数组作为基本结构,所以,必须预先精确地知道待存储的数据量。
用链表地址法处理冲突的哈希表是最健壮的实现方法。若能预先精确的知道数据量,在这种情况下用开放定址法编程最简单,因为不需要用到链表类。
哈希表并不提供任何形式的有序遍历,或对最大最小值元素进行存取。如果这些功能重要的话,使用二叉搜索树更好一些。
数据结构 |
查找 |
插入 |
删除 |
遍历 |
数组 |
O(N) |
O(1) |
O(N) |
—— |
有序数组 |
O(logN) |
O(N) |
O(N) |
O(N) |
链表 |
O(N) |
O(1) |
O(N) |
—— |
有序链表 |
O(N) |
O(N) |
O(N) |
O(N) |
二叉树(一般情况) |
O(logN) |
O(logN) |
O(logN) |
O(N) |
二叉树(最坏情况) |
O(N) |
O(N) |
O(N) |
O(N) |
平衡树(一般和最坏情况) |
O(logN) |
O(logN) |
O(logN) |
O(N) |
哈希表 |
O(1) |
O(1) |
O(1) |
—— |