[定义1.1] 向量(Vector),是对数组结构的抽象,也称作数组列表(array list)。向量使得我们可以通过下标直接访问/插入/删除序列中的元素,通常将序列的下标称为秩(Rank)。
基于其底层的数据存储结构,又可以通过两种方式实现之。一种是基于顺序存储结构实现的;另一种是基于链式存储结构实现的。
1.2 向量接口
[程序1.1 Vector.java]
package com.data.structure;
import com.exception.utils.ExceptionBoundaryViolation;
/**向量*/
public interface Vector {
/**返回向量中元素数目*/
public int getSize();
/**判断向量是否为空*/
public boolean isEmpty();
/**取秩为r的元素*/
public Object getAtRank(int r) throws ExceptionBoundaryViolation;
/**将秩为r的元素替换为obj*/
public Object replaceAtRank(int r, Object obj)
throws ExceptionBoundaryViolation;
/**插入obj,作为秩为r的元素,返回该元素*/
public Object insertAtRank(int r, Object obj)
throws ExceptionBoundaryViolation;
/**删除秩为r的元素*/
public Object removeAtRank(int r) throws ExceptionBoundaryViolation;
}
1.3基于数组实现向量
1.3.1代码实现[程序1.2 Vector_Array.java]
package com.vector.impl;
import com.data.structure.Vector;
import com.exception.utils.ExceptionBoundaryViolation;
/**基于数组实现的向量*/
public class Vector_Array implements Vector{
private int N=1024;;//数组默认容量
private int n=0;//数组实际容量
private Object[] array;//底层数组
public Vector_Array(){
array=new Object[N];
n=N;
}
public Vector_Array(int n){
array=new Object[n];
this.n=n;
}
//Vector interface
/**返回向量中元素数目*/
public int getSize(){
return n;
}
/**判断向量是否为空*/
public boolean isEmpty(){
return 0==n;
}
/**取秩为r的元素*/
public Object getAtRank(int r) throws ExceptionBoundaryViolation {
if (0 > r || r >= n)
throw new ExceptionBoundaryViolation("BoundaryViolation");
return array[r];
}
/**将秩为r的元素替换为obj*/
public Object replaceAtRank(int r, Object obj)
throws ExceptionBoundaryViolation {
if (0 > r || r >= n)
throw new ExceptionBoundaryViolation("BoundaryViolation");
Object bak = array[r];
array[r] = obj;
return bak;
}
/*public Object insertAtRank(int r, Object obj)
throws ExceptionBoundaryViolation {
if (0 > r || r >= n)
throw new ExceptionBoundaryViolation("BoundaryViolation");
for (int i = n; i > r; i--)
array[i] = array[i - 1];
array[r] = obj;
n ;
return obj;
}*/
//Dynamic
/**插入obj,作为秩为r的元素,返回该元素*/
public Object insertAtRank(int r, Object obj)
throws ExceptionBoundaryViolation {
if (0 > r || r >= n)
throw new ExceptionBoundaryViolation("BoundaryViolation");
if (n >= N) {
N *= 2;
Object[] newArray = new Object[N];
for (int i = 0; i < n; i )
newArray[i] = array[i];
array = newArray;
}
for (int i = n; i > r; i--)
array[i] = array[i - 1];
array[r] = obj;
n ;
return obj;
}
/**删除秩为r的元素*/
public Object removeAtRank(int r) throws ExceptionBoundaryViolation {
if (0 > r || r >= n)
throw new ExceptionBoundaryViolation("BoundaryViolation");
Object bak = array[r];
for (int i = r; i < n; i )
array[i] = array[i 1];
array[n - 1] = null;
n--;
return bak;
}
}
其中insertAtRankDynamic方法是对insertAtRank方法的改进,即实现动态增加数组长度的功能,当数组到达它的最大容量时,自动增加为原来的2倍长度后,再插入数据。
1.3.2效率分析
①insertAtRank()方法
设pi是在第i个存储位置插入一个数据的概率,并设数组长度为n,当在任何位置上插入数据元素的概率相等时,有pi=1/(n 1),则向其插入一个数据元素需要移动的数据元素的平均次数为:
∑{i从0至n}pi (n-i) =1/(n 1) ∑{i从0至n} (n-i) =n/2
②removeAtRank()方法
设qi是第i个存储位置数据元素的概率,设数组长度为n,当在任何位置上数据元素的概率相等时,有qi=1/n,则删除一个数据元素需要移动的数据元素的平均次数为:
∑{i从0至n-1}pi (n-i) =1/n ∑{i从0至n-1} (n-i) =(n-1)/2
③时间复杂度
插入和删除操作的时间复杂度为O(n);读取操作的时间复杂度为O(1)。
1.3.3优缺点分析
基于数组实现向量的主要优点是支持随机读取,以及内存空间利用率高;主要缺点是需要预先给出数组的最大容量,并且插入和删除操作需要移动大量数据。
1.3.4 相关算法[程序1.3VectorUtils.java]
package com.vector.impl;
import com.exception.utils.ExceptionBoundaryViolation;
public class VectorUtils {
/**
* 在向量中实现定位功能:查找是否存在数据元素x,
* 如果存在,则返回表中第一个与x值相等的数据元素的秩(从0开始编号);
* 如果不存在,则返回-1
*/
public static int find(Vector v, Object x) {
if (v.isEmpty())
throw new ExceptionBoundaryViolation("Vector Empty");
for (int i = 0; i < v.getSize(); i ) {
if (v.getAtRank(i).equals(x))
return i;
}
return -1;
}
/**
* 向量(从0开始编号)就地置逆算法
*/
public static void inplaceConverse(Vector v) {
if (v.isEmpty())
throw new ExceptionBoundaryViolation("Vector Empty");
Object bak;
for (int i = 0; i < v.getSize() / 2; i ) {//a[i]<->a[n-i-1]
bak = v.getAtRank(i);
v.replaceAtRank(i, v.getAtRank(v.getSize() - 1 - i));
v.replaceAtRank(v.getSize() - 1 - i, bak);
}
}
}
| 操作选项: 加精 解精 奖惩 设专题 设公告 解公告 固顶 总固顶 解固顶 结帖 解结帖 锁帖 解锁 移帖 删帖 |
所在位置:
看看评论