【数据结构】表、栈和队列

1.表

将形如 A 0 A_0 A0 A 1 A_1 A1 A 2 A_2 A2,… , A n − 1 A_{n-1} An1的数据结构称为。这个表的大小是N。将大小为0的特殊的表称为空表( empty list)。
对于除空表外的任何表,可以说 A i A_i Ai后继 A i − 1 A_{i-1} Ai1,并称 A i − 1 A_{i-1} Ai1前趋 A i A_i Ai。表中的第一个元素是 A 0 A_0 A0,而最后一个元素是 A n − 1 A_{n-1} An1 A 0 A_0 A0没有前驱元, A n − 1 A_{n-1} An1没有后继元。

表可以顺序存储,也可以链式存储。

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 队列的链式存储

(后续更新)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冷冰殇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值