リニアテーブルは、組成物の同じタイプを有するn個のデータ要素の有限のシーケンスである単純なデータ型です。フォームとして0、A 1、...、N - 1。0サイズのテーブルは空のテーブルであり、前記Iの後継A I-1は、前記I-1前駆体A のI。
がprintlist、要素、makeEmptyホーム空のテーブルのテーブルを印刷戻るにアイテムの最初の発生の位置を見つけ、挿入及び除去され、典型的に挿入し、位置テーブルから要素を削除し、そして場所にfindKth要素が返され、次および前の位置をパラメータとして取り、細胞の前駆員後続値を返すであろう。
ArrayListの実装
テーブルの上のすべての操作は、アレイによって達成することができます。次のようにメモリアレイの概略図。
この構成の特長は、保存されています。データは連続、高速ランダムアクセス速度です。がprintlistは線形時間で行われ、findKth操作は、時定数を呼び出します。効率の挿入および削除が比較的低いため、最悪の場合、全ての要素が挿入された位置0である位置を戻す必要があります。
達成するために、アレイのリストに基づいて:
public class MyArrayList<T> implements Iterable<T>{
private static final int DEFAULT_CAPACITY=10;
private int size;
private T[] items;
public MyArrayList() {
doClear();
}
public void clear() {
doClear();
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public void trimToSize() {
ensureCapacity(size);
}
public boolean add(T x) {
add(size, x);
return true;
}
public void add(int idx, T x) {
if (items.length == size) {
ensureCapacity(size * 2 + 1);
}
for (int i = size; i > idx; i--) {
items[i] = items[i - 1];
}
items[idx] = x;
size++;
}
public T remove(int idx) {
T removedItem = items[idx];
for (int i = idx; i < size - 1; i++) {
items[i] = items[i + 1];
}
size--;
return removedItem;
}
private void doClear() {
size = 10;
ensureCapacity(DEFAULT_CAPACITY);
}
private void ensureCapacity(int newCapacity) {
if (newCapacity < size) {
return;
}
T[] old = items;
items = (T[]) new Object[newCapacity];
for (int i = 0; i < size; i++) {
items[i] = old[i];
}
}
public Iterator<T> iterator() {
return new ArrayListIterator();
}
private class ArrayListIterator implements Iterator<T> {
private int current = 0;
@Override
public boolean hasNext() {
return current < size;
}
@Override
public T next() {
if (!hasNext())
throw new NoSuchElementException();
return items[current++];
}
public void remove() {
MyArrayList.this.remove(--current);
}
}
}
単一のリスト
あなたはテーブルが削除の操作を頻繁に挿入する必要がある場合には、効率の配列の実装が低くなりすぎます。列は、ノードの数は、ノードがメモリに接続する必要はありません示しています。各ノードテーブル要素ノードの鎖を含む要素に続く要素を含みます。シングルチェーン店次の図:
削除だけで次の参照を実現することができる移動する必要があります:
メソッドを挿入二回引用され、その後調整し、ノードを追加する必要があります。
機能の単一のリスト:リンクは、ノードの一方向の方向である配列に対して、ランダムアクセス速度が遅い単一のリストであり、追加、高効率を取り除きます。
二重リンクリスト
二重に2つのデータ要素とチェーンと同様、単独でリンクされたリスト構造で連結され、二つの鎖は先行および後続ノードに向けられています。典型的には、双方向円形のリンクリストとして構成され、すなわち、リストの最初の要素は、次のチェーンの最後のノード、前鎖、リストの最後の要素を指して最初のノードを指示しました。ストレージ構造を次のように
二重リンクリストを削除します。
二重リンクリストを追加することは逆のプロセスではなく、描画削除されます。
達成するために二重にリンクされたリスト:
public class DoubleLink<T> {
// 表头
private Node<T> head;
// 节点数
private int count;
private class Node<T> {
public Node prev; // 前节点
public Node next; // 后节点
public T value;
public Node(T value, Node prev, Node next) {
this.prev = prev;
this.next = next;
this.value = value;
}
}
public DoubleLink() {
// 创建表头
head = new Node<>(null, null, null);
head.prev = head.next = head;
count = 0;
}
// 节点数
public int size() {
return count;
}
// 判断表是否为空
public boolean isEmpty() {
return count == 0;
}
// 获取第index位置的节点
private Node<T> getNode(int index) {
if (index < 0 || index >= count) {
throw new IndexOutOfBoundsException();
}
// 正向查找
if (index <= count / 2) {
Node<T> node = head.next;
for (int i = 0; i < index; i++) {
node = node.next;
}
return node;
}
// 反向查找
Node<T> rnode = head.prev;
int rindex = count - index - 1;
for (int j = 0; j < rindex; j++) {
rnode = rnode.prev;
}
return rnode;
}
// 获取第index位置节点的值
public T get(int index) {
return getNode(index).value;
}
// 将节点插入到index位置
public void insert(int index, T t) {
if (index == 0) {
Node node = new Node(t, head, head.next);
head.next.prev = node;
head.next = node;
count++;
return;
}
Node<T> inode = getNode(index);
// 创建新节点
Node<T> newNode = new Node<>(t, inode.prev, inode);
inode.prev.next = newNode;
inode.next = newNode;
return;
}
// 删除节点
public Node<T> delete(int index) {
Node<T> delNode = getNode(index);
delNode.prev.next = delNode.next;
delNode.next.prev = delNode.prev;
count--;
return delNode;
}
}