数据结构与算法-向量vector
数组是一组具有相同类型的数据,存储在连续的内存空间中。
一、简介
向量(vector)是数组的抽象与泛化,由一组元素按线性次序封装完成。很多语言中都有提供容器类
,如C++ STL 中的 vector,Java 中的 ArrayList。与链表、栈、队列一样,向量属于线性表结构。
二、部分操作
基于vector的算法有很多,此处简单记录几个有意思的。另外,篇幅有限,且许多排序算法可被向量与链表共用,后面单独细说。
2.1 访问
与数组一样,向量是存储在连续内存空间具有相同类型的数据(向量内部的数据存储正式以数组方式实现的),正因如此,向量的随机访问非常高效。只需知道a[0]的物理地址A,单个元素占用空间s和要访问的数据下标i,便可直接计算出
a[i]的物理地址 = A + i * s
,因此可以实现O(1)时间的随机访问。向量中各个元素下标称为秩,因此向量是循秩访问。
不仅如此,当CPU在需要获取数据时,先在CPU缓存中查找,如果查找不到再到内存中查找。而CPU从内存中读取数据时并不是仅仅读取要访问的地址,而是读取一个数据块并保存至缓存中。例如,此时CPU需要读取a[2],但是缓存中没有,于是到内存中查找。找到之后,CPU不仅将a[2]读至缓存,可能连a[1]、a[0]、a[3]、a[4]等一起读入缓存。当CPU需要读取a[4]时,可以直接从缓存内查到。读取速度就有了很大提升,这是链表等数据结构没有的特性。
2.2 查找
2.2.1 遍历查找
要实现查找功能,向量中存储的数据类型要有判等的能力,如在java中需实现equals方法。java的ArrayList中提供两种查找方法,一种是从前往后遍历,找到第一次出现的位置,另一种是从后向前遍历,找到最后一次出现的位置。算法复杂度为O(n)。代码如下。
/**
* Returns the index of the first occurrence of the specified element
* in this list, or -1 if this list does not contain the element.
* More formally, returns the lowest index <tt>i</tt> such that
* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,
* or -1 if there is no such index.
*/
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
/**
* Returns the index of the last occurrence of the specified element
* in this list, or -1 if this list does not contain the element.
* More formally, returns the highest index <tt>i</tt> such that
* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,
* or -1 if there is no such index.
*/