1.表
将形如
A
0
A_0
A0,
A
1
A_1
A1,
A
2
A_2
A2,… ,
A
n
−
1
A_{n-1}
An−1的数据结构称为表。这个表的大小是N。将大小为0的特殊的表称为空表( empty list)。
对于除空表外的任何表,可以说
A
i
A_i
Ai后继
A
i
−
1
A_{i-1}
Ai−1,并称
A
i
−
1
A_{i-1}
Ai−1前趋
A
i
A_i
Ai。表中的第一个元素是
A
0
A_0
A0,而最后一个元素是
A
n
−
1
A_{n-1}
An−1。
A
0
A_0
A0没有前驱元,
A
n
−
1
A_{n-1}
An−1没有后继元。
表可以顺序存储,也可以链式存储。
1.1 表的顺序存储
// 实现了Iterable接口的类可以拥有增强的for循环
public class MyArrayList<AnyType> implements Iterable<AnyType>{
private static final int DEFAULT_CAPACITY = 10; // 表的默认容量
private AnyType [ ] theItems; // 整个表的引用
private int theSize; // 表的尺寸(大小)
// 构造器
public MyArrayList( ) {
doClear( );
}
// 返回表的大小
public int size( ) {
return theSize;
}
// 判空
public boolean isEmpty( ) {
return size( ) == 0;
}
// 返回idx索引处的元素;如果索引超界,抛出异常
public AnyType get( int idx ) {
if( idx < 0 || idx >= size( ) )
throw new ArrayIndexOutOfBoundsException( "Index " + idx + "; size " + size( ) );
return theItems[ idx ];
}
// 设置索引idx处的元素为newVal,并返回原本idx处的元素;如果索引超界,抛出异常
public AnyType set( int idx, AnyType newVal ) {
if( idx < 0 || idx >= size( ) )
throw new ArrayIndexOutOfBoundsException( "Index " + idx + "; size " + size( ) );
AnyType old = theItems[ idx ];
theItems[ idx ] = newVal;
return old;
}
// 在强制类型转换的时候编译器会给出警告;下面一行语句告诉编译器忽略不检查警告信息
@SuppressWarnings("unchecked")
// 扩容。如果新容量小于现有尺寸,不做改变;否则,按新容量扩容
public void ensureCapacity( int newCapacity ) {
if( newCapacity < theSize )
return;
AnyType [ ] old = theItems;
theItems = (AnyType []) new Object[ newCapacity ];
for( int i = 0; i < size( ); i++ )
theItems[ i ] = old[ i ];
}
// 在列表的末尾增加元素x
public boolean add( AnyType x ) {
add( size( ), x );
return true;
}
// 在索引idx处增加元素x
public void add( int idx, AnyType x ) {
// 当列表中元素放满时,将列表容量扩大1倍
if( theItems.length == size( ) )
ensureCapacity( size( ) * 2 + 1 );
for( int i = theSize; i > idx; i-- )
theItems[ i ] = theItems[ i - 1 ];
theItems[ idx ] = x;
theSize++;
}
// 删除idx索引处的元素,并返回这个元素
public AnyType remove( int idx ) {
AnyType removedItem = theItems[ idx ];
for( int i = idx; i < size( ) - 1; i++ )
theItems[ i ] = theItems[ i + 1 ];
theSize--;
return removedItem;
}
// 清理列表中所有元素;将列表尺寸置0
public void clear( ) {
doClear( );
}
// 列表尺寸置0;容量设置为默认容量
private void doClear( ) {
theSize = 0;
ensureCapacity( DEFAULT_CAPACITY );
}
// 实现Iterable接口的集合必须提供一个称为iterator 的方法,
// 该方法返回一个Iterator类型的对象(此时该对象指向集合的首元素)
public java.util.Iterator<AnyType> iterator( ) {
return new ArrayListIterator( );
}
private class ArrayListIterator implements java.util.Iterator<AnyType> {
private int current = 0;
private boolean okToRemove = false;
public boolean hasNext( ) {
return current < size( );
}
public AnyType next( ) {
if( !hasNext( ) )
throw new java.util.NoSuchElementException( );
okToRemove = true;
return theItems[ current++ ];
}
public void remove( ) {
if( !okToRemove )
throw new IllegalStateException( );
// 删除的是current前面的元素
MyArrayList.this.remove( --current );
okToRemove = false;
}
}
// 系统输出
public String toString( ) {
StringBuilder sb = new StringBuilder( "[ " );
// 注意这里,this实际是一个容器,并不是一个普通的数组。
// 但由于实现了Iterable接口,所以可以使用这种增强的for循环,
// 这里会自动调用iterator( )方法
for( AnyType x : this )
sb.append( x + " " );
sb.append( "]" );
return new String( sb );
}
}
class TestArrayList {
public static void main( String [ ] args ) {
MyArrayList<Integer> lst = new MyArrayList<>( );
for( int i = 0; i < 10; i++ )
lst.add( i );
for( int i = 20; i < 30; i++ )
lst.add( 0, i );
lst.remove( 0 );
lst.remove( lst.size( ) - 1 );
System.out.println( lst );
}
}
1.2 表的链式存储
// 双链表
public class MyLinkedList<AnyType> implements Iterable<AnyType>{
// 链表节点定义
private static class Node<AnyType> {
public Node( AnyType d, Node<AnyType> p, Node<AnyType> n ) {
data = d; prev = p; next = n;
}
public AnyType data;
public Node<AnyType> prev;
public Node<AnyType> next;
}
private int theSize;
private int modCount = 0; // 该变量记录构造以来对链表所做改变的次数。用以帮助迭代器检测集合是否发生了变化
private Node<AnyType> beginMarker; // 头节点
private Node<AnyType> endMarker; // 尾节点
// 构造器:构造一个空链表
public MyLinkedList( ) {
doClear( );
}
// 清空链表
private void clear( ) {
doClear( );
}
// 清空链表的实现
public void doClear( ) {
beginMarker = new Node<>( null, null, null );
endMarker = new Node<>( null, beginMarker, null );
beginMarker.next = endMarker;
theSize = 0;
modCount++;
}
// 返回链表尺寸
public int size( ) {
return theSize;
}
// 判空
public boolean isEmpty( ) {
return size( ) == 0;
}
// 在链表的末尾增加元素x
public boolean add( AnyType x ) {
add( size( ), x );
return true;
}
// 在链表的idx索引处增加元素x
public void add( int idx, AnyType x ) {
addBefore( getNode( idx, 0, size( ) ), x );
}
// 在节点p之前增添元素x
private void addBefore( Node<AnyType> p, AnyType x ) {
Node<AnyType> newNode = new Node<>( x, p.prev, p );
newNode.prev.next = newNode;
p.prev = newNode;
theSize++;
modCount++;
}
// 获取idx索引处的数据
public AnyType get( int idx ) {
return getNode( idx ).data;
}
// 将idx索引处设置为新元素newVal,并返回旧元素
public AnyType set( int idx, AnyType newVal ) {
Node<AnyType> p = getNode( idx );
AnyType oldVal = p.data;
p.data = newVal;
return oldVal;
}
// 获取idx索引处的节点
private Node<AnyType> getNode( int idx ) {
return getNode( idx, 0, size( ) - 1 );
}
// 获取idx索引处的节点;索引idx必须在lower和upper之间,否则抛出异常
private Node<AnyType> getNode( int idx, int lower, int upper ) {
Node<AnyType> p;
if( idx < lower || idx > upper )
throw new IndexOutOfBoundsException( "getNode index: " + idx + "; size: " + size( ) );
if( idx < size( ) / 2 ) {
p = beginMarker.next;
for( int i = 0; i < idx; i++ )
p = p.next;
}
else {
p = endMarker;
for( int i = size( ); i > idx; i-- )
p = p.prev;
}
return p;
}
// 删除idx索引处的节点
public AnyType remove( int idx ) {
return remove( getNode( idx ) );
}
// 删除节点p
private AnyType remove( Node<AnyType> p ) {
p.next.prev = p.prev;
p.prev.next = p.next;
theSize--;
modCount++;
return p.data;
}
// 系统输出
public String toString( ) {
StringBuilder sb = new StringBuilder( "[ " );
for( AnyType x : this )
sb.append( x + " " );
sb.append( "]" );
return new String( sb );
}
// 实现了Iterable接口的集合中必须有iterator方法,且该方法必须返回Iterator
public java.util.Iterator<AnyType> iterator( ) {
return new LinkedListIterator( );
}
private class LinkedListIterator implements java.util.Iterator<AnyType> {
private Node<AnyType> current = beginMarker.next;
private int expectedModCount = modCount;
private boolean okToRemove = false;
public boolean hasNext( ) {
return current != endMarker;
}
public AnyType next( ) {
if( modCount != expectedModCount )
throw new java.util.ConcurrentModificationException( );
if( !hasNext( ) )
throw new java.util.NoSuchElementException( );
AnyType nextItem = current.data;
current = current.next;
okToRemove = true;
return nextItem;
}
public void remove( ) {
if( modCount != expectedModCount )
throw new java.util.ConcurrentModificationException( );
if( !okToRemove )
throw new IllegalStateException( );
MyLinkedList.this.remove( current.prev );
expectedModCount++;
okToRemove = false;
}
}
}
class TestLinkedList{
public static void main( String [ ] args ) {
MyLinkedList<Integer> lst = new MyLinkedList<>( );
for( int i = 0; i < 10; i++ )
lst.add( i );
for( int i = 20; i < 30; i++ )
lst.add( 0, i );
lst.remove( 0 );
lst.remove( lst.size( ) - 1 );
System.out.println( lst );
java.util.Iterator<Integer> itr = lst.iterator( );
while( itr.hasNext( ) ) {
itr.next( );
itr.remove( );
System.out.println( lst );
}
}
}
2. 栈
2.1 栈的顺序存储
public class MyArrayStack<AnyType>{
private static final int DEFAULT_CAPACITY = 5; // 栈的默认容量
private AnyType [ ] theItems; // 存储栈元素的数组
private int topOfStack; // 栈顶指针
// 构造器
public MyArrayStack( ) {
doClear( );
}
// 返回栈的大小
public int size( ) {
return topOfStack+1;
}
// 判空
public boolean isEmpty( ) {
return size( ) == 0;
}
// 在强制类型转换的时候编译器会给出警告;下面一行语句告诉编译器忽略不检查警告信息
@SuppressWarnings("unchecked")
// 扩容。如果新容量小于现有尺寸,不做改变;否则,按新容量扩容
public void ensureCapacity( int newCapacity ) {
if( newCapacity < topOfStack+1 )
return;
AnyType [ ] old = theItems;
theItems = (AnyType []) new Object[ newCapacity ];
for( int i = 0; i < size( ); i++ )
theItems[ i ] = old[ i ];
}
// 清理栈中所有元素;
public void clear( ) {
doClear( );
}
// 栈顶指针置为-1,即此时为空栈;容量设置为默认容量
private void doClear( ) {
topOfStack = -1;
ensureCapacity( DEFAULT_CAPACITY );
}
// 入栈
public void push(AnyType x){
// 当栈中元素放满时,将容量扩大1倍
if( theItems.length == size( ) )
ensureCapacity( size( ) * 2 + 1 );
theItems[ (topOfStack++)+1 ] = x;
}
// 出栈
public AnyType pop() {
// 这里是要判断数组超界的
// if(topOfStack<0)
// throw new Exception("栈已空,无法pop");
// 当给栈分配的空间有大量空余时,缩减容量
if( theItems.length > size( )*4 )
ensureCapacity( size( )*2 );
return theItems[ topOfStack-- ];
}
public AnyType top() {
// if(topOfStack<0)
// throw new Exception("栈已空,无法top");
return theItems[ topOfStack ];
}
}
class TestArrayStack {
public static void main( String [ ] args ) {
MyArrayStack<Integer> stack = new MyArrayStack<>( );
for( int i = 0; i < 13; i++ )
stack.push( i );
for( int i = 0; i < 13; i++ )
stack.pop();
stack.push(99);
System.out.println( stack );
}
}
2.2 栈的链式存储
(后续更新)
3. 队列
3.1 队列的顺序存储
public class MyArrayQueue<AnyType> {
private static final int DEFAULT_CAPACITY = 4; // 栈的默认容量
private AnyType [ ] theItems; // 存储队列元素的数组
private int front; // 队头指针
private int rear; // 队尾指针
private int currentSize; // 队列中元素个数
// 构造器
public MyArrayQueue( ) {
doClear( );
}
// 返回队列的大小
public int size( ) {
return currentSize;
}
// 判空
public boolean isEmpty( ) {
return size( ) == 0;
}
// 在强制类型转换的时候编译器会给出警告;下面一行语句告诉编译器忽略不检查警告信息
@SuppressWarnings("unchecked")
// 扩容。如果新容量小于现有尺寸,不做改变;否则,按新容量扩容
public void ensureCapacity( int newCapacity ) {
if( newCapacity < currentSize )
return;
AnyType [ ] old = theItems;
theItems = (AnyType []) new Object[ newCapacity ];
if(old==null)
return;
int i,k; // 新数组的索引位
if(rear<=front){
int j;
for(i = 0,j=front; i < size( )&&j<old.length; i++,j++ )
theItems[ i ] = old[ j ];
for(k=0; i < size( )&k<rear; i++,k++ )
theItems[ i ] = old[ k ];
}
else {
i=0;
for (k = front; k < rear; k++)
theItems[i++] = old[k];
}
front=0;
rear=i;
}
// 清理队列中所有元素;
public void clear( ) {
doClear( );
}
// 队列容量设置为默认容量
private void doClear( ) {
front=0;
rear=0;
ensureCapacity( DEFAULT_CAPACITY );
}
// 入队
public boolean enQueue(AnyType x){
if(currentSize==theItems.length){
ensureCapacity( currentSize*2+1 );
}
theItems[rear]=x;
rear=(rear+1)%theItems.length;
currentSize++;
return true;
}
// 出队
public AnyType deQueue(){
AnyType res=theItems[front];
front=(front+1)%theItems.length;
currentSize--;
if( theItems.length > size( )*3 )
ensureCapacity( size( )*2+1 );
return res;
}
}
class TestArrayQueue {
public static void main( String [ ] args ) {
MyArrayQueue<Integer> queue = new MyArrayQueue<>( );
for( int i = 0; i < 4; i++ )
queue.enQueue( i );
queue.enQueue( 5 );
for( int i = 20; i < 30; i++ )
queue.enQueue(i);
queue.enQueue(99);
for( int i = 0; i < 9; i++ )
queue.deQueue();
queue.deQueue();
queue.deQueue();
}
}
3.2 队列的链式存储
(后续更新)