一,序列
本文將定義并實現一個通用的序列 ADT,從而將向量ADT與列表ADT中的所有方法集成起來——也就是說,這一ADT 將同時支持以秩或位置來訪問其中的元素。因此,這種數據結構將適用于解決更多的實際問題。
二,序列ADT(AbstractDataType)
序列ADT將同時支持向量ADT與列表ADT中的所有方法,此外,還支持以下兩個方法——正是借助這兩個方法,我們才得以將秩和位置的概念聯系起來:
操作方法 | 功能描述 |
---|---|
rank2Pos(r) | 若0 ≤ r < getSize(),則返回秩為r 的元素所在的位置 ;否則,報錯 輸入:一個(作為秩的)整數 輸出:位置 |
pos2Rank(p) | 若p 是序列中的合法位置,則返回存放于p 處的元素的秩 ;否則,報錯 輸入:一個位置 輸出:(作為秩的)整數 |
三,基于雙向鏈表實現序列
接口:
package dsa.Sequence;
import other.Position;
import dsa.List.ExceptionPositionInvalid;
import dsa.List.List;
import dsa.Vector.ExceptionBoundaryViolation;
import dsa.Vector.Vector;
/*
* 序列接口
*/
public interface Sequence extends Vector, List {
// 若0 <= r < getSize(),則返回秩為r的元素所在的位置;否則,報錯
public Position rank2Pos(int r) throws ExceptionBoundaryViolation;
// 若p是序列中的合法位置,則返回存放于p處的元素的秩;否則,報錯
public int pos2Rank(Position p) throws ExceptionPositionInvalid;
}
實現:
package dsa.Sequence;
import other.Position;
import dsa.Deque.DLNode;
import dsa.List.ExceptionPositionInvalid;
import dsa.List.List_DLNode;
import dsa.Vector.ExceptionBoundaryViolation;
/*
* 基于雙向鏈表實現序列
*/
public class Sequence_DLNode extends List_DLNode implements Sequence {
// 檢查秩r是否在[0, n)之間
protected void checkRank(int r, int n) throws ExceptionBoundaryViolation {
if (r < 0 || r >= n)
throw new ExceptionBoundaryViolation("意外:非法的秩" + r + ",應該屬于[0, "
+ n + ")");
}
// 若0 <= r < getSize(),則返回秩為r的元素所在的位置;否則,報錯--O(n)
public Position rank2Pos(int r) throws ExceptionBoundaryViolation {
DLNode node;
checkRank(r, getSize());
if (r <= getSize() / 2) {// 若秩較小,則
node = header.getNext();// 從前端開始
for (int i = 0; i < r; i++)
node = node.getNext();// 逐一掃描
} else {// 若秩較大,則
node = trailer.getPrev();// 從后端開始
for (int i = 1; i < getSize() - r; i++)
node = node.getPrev();// 逐一掃描
}
return node;
}
// 若p是序列中的合法位置,則返回存放于p處的元素的秩;否則,報錯--O(n)
public int pos2Rank(Position p) throws ExceptionPositionInvalid {
DLNode node = header.getNext();
int r = 0;
while (node != trailer) {
if (node == p)
return (r);
node = node.getNext();
r++;
}
throw new ExceptionPositionInvalid("意外:作為參數的位置不屬于序列");
}
// 取秩為r的元素--O(n)
public Object getAtRank(int r) throws ExceptionBoundaryViolation {
checkRank(r, getSize());
return rank2Pos(r).getElem();
}
// 將秩為r的元素替換為obj--O(n)
public Object replaceAtRank(int r, Object obj)
throws ExceptionBoundaryViolation {
checkRank(r, getSize());
return replace(rank2Pos(r), obj);
}
// 插入obj,作為秩為r的元素--O(n);返回該元素
public Object insertAtRank(int r, Object obj)
throws ExceptionBoundaryViolation {
checkRank(r, getSize() + 1);
if (getSize() == r)
insertLast(obj);
else
insertBefore(rank2Pos(r), obj);
return obj;
}
// 刪除秩為r的元素--O(n)
public Object removeAtRank(int r) throws ExceptionBoundaryViolation {
checkRank(r, getSize());
return remove(rank2Pos(r));
}
}