表、栈和队列

一、表
表有两种实现方式:数组实现链表实现
数组实现:表是通过在高端进行插入操作建成,且建成后主要是对表进行访问(查询)操作,而非插入、删除;
!!ArrayList类提供了可增长数组的实现。其优点:对get和set的调用花费常数时间;缺点:新项的插入和现有项的删除代价昂贵(除非变动在末端)。
链表实现:对表的操作主要是插入和删除,访问操作较少。
!!LinkedList类提供了List ADT的双链表实现。其优点:新项的插入和现有项的删除开销小(假设变动项位置已知);其缺点:不易于做索引,对get的调用代价昂贵。
补充Java Collections API中表的知识点:
(1)Collection接口扩展了Iterable接口。
实现Iterable接口的类可拥有增强的for循环;
实现Iterable接口的集合必须提供iterator方法(返回Iterator类型的对象)。
如果对正在被迭代的集合进行结构上的改变(除非调用迭代器自己的remove方法),那么迭代器将不再合法。

 public static void removeEvensVer2(List<Integer> lst){
     for(Integer x:lst){
        if(x%2==0)
           lst.remove(x);//抛出异常
     }
 }

(2)如果ArrayList的大小有早期估计,那么ensureCapacity可设置容量为足够大的量,避免后期扩展;再有,trimToSize可在所有的添加操作完成后使用,避免浪费空间。
(3)ListIterator扩展了List的Iterator功能。previous和hasPrevious使得对表从后向前遍历。
1.表的数组实现
1)数组是由固定容量创建的,但在需要时,可以扩展其容量;

  int[] arr = new int[10];
  //扩展数组arr
  int[] newArr = new int[arr.length*2];
  for(int i=0;i<arr.length;i++){
      newArr[i] = arr[i];
  }
  arr = newArr;

2)实现代码

public class MyArrayList<Type> implements Iterable<Type> {

    private static final int DEFAULT_CAPACITY = 10;//默认大小
    private int theSize;
    private Type[] theItems;

    public MyArrayList(){
        clear();
    }
    public int size(){
        return theSize;
    }
    public boolean isEmpty(){
        return theSize==0;
    }
    //初始化
    public void clear(){
        theSize = 0;
        ensureCapacity(DEFAULT_CAPACITY);
    }
    //查找
    public Type get(int id){
        if(id>=theSize || id<0){  //注意判断范围
            throw new ArrayIndexOutOfBoundsException();
        }
        return theItems[id];
    }
    //更新
    public Type set(int id,Type t){ //返回被替换的值
        if(id>=theSize || id<0){  //注意判断范围
            throw new ArrayIndexOutOfBoundsException();
        }
        Type old = theItems[id];
        theItems[id] = t;
        return old;
    }
    //删除
    public Type remove(int id){
        if(id>=theSize || id<0){  //注意判断范围
            throw new ArrayIndexOutOfBoundsException();
        }
        Type old = theItems[id];
        for(int i=id;i<theSize-1;i++){
            theItems[i] = theItems[i+1];
        }
        theSize--;
        return old;
    }
    //添加
    public boolean add(Type t){
        add(theSize,t);
        return true;
    }
    public void add(int id,Type t){
        /*while(id>=theItems.length){  //此处有疑问
            ensureCapacity(2*theItems.length);
        }*/
        if(theItems.length == size()){
            ensureCapacity(2*size()+1);
        }
        for(int i=theSize-1;i>=id;i--){
            theItems[i+1] = theItems[i];
        }
        theItems[id] = t;
        theSize++;
    }
    //设置容量
    public void ensureCapacity(int newCapacity){
        if(newCapacity<theSize){  //注意 判断适用性
            return;
        }
        Type[] old = theItems;
        //theItems = new Type[newCapacity];
        theItems = (Type[]) new Object[newCapacity];  //注意 引用新数组 的创建
        for(int i=0;i<theSize;i++){
            theItems[i] = old[i];
        }
    }
    public java.util.Iterator<Type> iterator(){
        return new ArrayListIterator();
    }
    //内部类(编译器编写使内部类对象和外部类对象相关联所需的附加代码)
    private class ArrayListIterator implements java.util.Iterator<Type>{
        private int current = 0;

        public boolean hasNext(){
            //return current!=theSize;
            return current<size();
        }
        public Type next(){
            if(!hasNext()){   //判断
                throw new java.util.NoSuchElementException();
            }
            return theItems[current++];
        }
        public void remove(){
            MyArrayList.this.remove(--current);
        }
    }
}

2.表的链表实现(双链表)

  public class MyLinkedList<AnyType> implements Iterable<AnyType> {
        //Node类是private的,因此数据成员的可见性是无关紧要的。MyLinkedList外面的类不能访问Node类
    private static class Node<AnyType>{
        public AnyType data;
        public Node<AnyType> prev;
        public Node<AnyType> next;

        public Node(AnyType d,Node<AnyType> p,Node<AnyType> n){
            data = d; prev = p; next = n;
        }
    }

    private int theSize;
    private int modCount = 0;//对链表所做改变的次数(add、remove)
    private Node<AnyType> beginMarker;//头节点
    private Node<AnyType> endMarker;//尾节点

    public MyLinkedList(){
        clear();
    }
    //初始化
    public void clear(){
        theSize = 0;
        modCount++;

        beginMarker = new Node<AnyType>(null,null,null);
        endMarker = new Node<AnyType>(null,beginMarker,null);
        beginMarker.next = endMarker;
        /*endMarker = new Node(null,null,null);
        beginMarker = new Node(null,null,endMarker);
        endMarker.prev = beginMarker;*/
    }
    public int size(){
        return theSize;
    }
    public boolean isEmpty(){
        return theSize == 0;
    }
    //添加
    public boolean add(AnyType x){
        add(theSize,x);
        return true;
    }
    public void add(int idx,AnyType x){
        addBefore(getNode(idx),x);
    }
    //查找
    public AnyType get(int idx){
        return getNode(idx).data;
    }
    //更新
    public AnyType set(int idx,AnyType newVal){
        AnyType old = getNode(idx).data;
        getNode(idx).data = newVal;
        return old;
    }
    //删除
    public AnyType remove(int idx){
        return remove(getNode(idx));
    }

    private void addBefore(Node<AnyType> p,AnyType x){
        if(p.prev==null){
            throw new IndexOutOfBoundsException();
        }
        Node<AnyType> q = new Node<AnyType>(x,p.prev,p);
        //p.prev.next = q;
        q.prev.next = q;
        p.prev = q;
        theSize++;
        modCount++;//添加操作,更改值
    }
    private AnyType remove(Node<AnyType> p){
        p.next.prev = p.prev;
        p.prev.next = p.next;
        theSize--;
        modCount++;//删除操作,更改值
        return p.data;
    }
    private Node<AnyType> getNode(int idx){
        Node<AnyType> p;
        if(idx<0||idx>theSize){   //not (theSize-1).
            throw new IndexOutOfBoundsException();
        }
        if(idx<size()/2){  //由前向后遍历
            p = beginMarker.next;
            for(int i=0;i<idx;i++){
                p = p.next;
            }
        }
        else{  //由后向前遍历
            p = endMarker;
            for(int i=theSize;i>idx;i--){
                p = p.prev;
            }
        }
        return p;
    }
    //迭代器(non-Javadoc)
    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(expectedModCount != modCount){
                throw new java.util.ConcurrentModificationException();
            }
            if(!hasNext()){
                throw new java.util.NoSuchElementException();
            }
            AnyType d = current.data;
            current = current.next;
            okToRemove = true;
            return d;
        }
        public void remove(){
            if(expectedModCount != modCount){
                throw new java.util.ConcurrentModificationException();
            }
            if(!okToRemove){
                throw new IllegalStateException();
            }
            MyLinkedList.this.remove(current.prev);
            okToRemove = false;
            expectedModCount++;
        }
    }
  }

二、栈
栈的插入和删除只在一个位置操作;
栈是后进先出表;
1.栈的数组实现

 public class MyArrayStack<Type> {

    private static final int DEFAULT_LENGTH = 10;
    private int topOfStack;//栈顶
    private int theSize;
    private Type[] items;

    public MyArrayStack(){
        clear();
    }
    //初始化
    public void clear(){
        theSize = 0;
        topOfStack = -1;
        //items = new Type[DEFAULT_LENGTH];  //error!!
        //items = (Type[]) new Object[DEFAULT_LENGTH];
        ensureArray(DEFAULT_LENGTH);
    }
    //入栈
    public void push(Type t){
        if(theSize>=DEFAULT_LENGTH){
            ensureArray(2*size()-1);
        }
        items[theSize++] = t;
        topOfStack++;
    }
    //出栈
    public Type pop(){
        if(topOfStack<0){
            throw new ArrayIndexOutOfBoundsException();
        }
        theSize--;
        return items[topOfStack--];
    }
    public void ensureArray(int newLength){
        if(newLength<size()){
            return; 
        }
        /*Type[] old = (Type[]) new Object[newLength];
        for(int i=0;i<theSize;i++){
            old[i] = items[i];
        }
        items = old;*/
        Type[] old = items;
        items = (Type[]) new Object[newLength];
        for(int i=0;i<theSize;i++){
            items[i] = old[i];
        }
    }
    public int size(){
        return theSize;
    }
    public boolean isEmpty(){
        return theSize==0;
    }
   }
   //下面是两个应用:进制转换和符号匹配检测
    /**
     * 进制转换
     * num:十进制数 ;n:进制数
     * @param args
     */
    public String conver(int num,int n){
        MyArrayStack<Integer> stack = new MyArrayStack<Integer>();
        while(num!=0){
            stack.push(num%n);
            num = num/n;
        }
        StringBuilder sb = new StringBuilder();
        while(stack.size()>0){
            sb.append(stack.pop());
        }
        return sb.toString();
    }
    /**
     * 检测 符号 是否匹配:([])
     * @param args
     */
    public boolean isMatch(String str){
        MyArrayStack<Character> test = new MyArrayStack<Character>();
        char[] chs = str.toCharArray();
        for(char ch:chs){
            if(test.size()==0 && (ch=='('||ch=='[')){
                test.push(ch);
            }
            else if(test.size()==0){
                    return false;
            }
            else{
                char temp = test.pop();
                if(temp=='(' && ch==')'){

                }
                else if(temp=='[' && ch==']'){

                }
                else{
                    test.push(temp);
                    test.push(ch);
                }
            }
        }
        return test.isEmpty();
    }

2.栈的链表实现(单链表)

public class MyLinkedStack<Type> {
        //私有内部类
    private class Node<Type>{
        public Type data;
        public Node<Type> next;
        public Node(Type data,Node<Type> next){
            this.data = data;
            this.next = next;
        }
        public Node(){
            data = null;
            next = null;
        }
    }
    //数据域
    private int theSize;
    private Node<Type> begin;
    public MyLinkedStack(){
        theSize = 0;
        begin = new Node<Type>(null,null);
    }

    public int size(){
        return theSize;
    }
    public boolean isEmpty(){
        return theSize==0;
    }
    public void push(Type x){
        Node<Type> p = new Node<Type>(x,begin.next);
        begin.next = p;
        theSize++;
    }
    public Type pop(){
        Type old = begin.next.data;
        begin.next = begin.next.next;
        theSize--;
        return old;
    }
   }

三、队列
队列是一种先入先出表;
队列在队头删除元素,在队尾添加元素。
像栈一样,对于每种操作,链表实现和数组实现都给出快速的O(1)运行时间。
1.队列的链表实现

public class MyLinkedQueue<T> {
        //私有内部类
    private class Node{
        public T data;
        public Node next;
        public Node(){
        }
        public Node(T data,Node next){
            this.data = data;
            this.next = next;
        }
    }

    private Node front;//队头
    private Node rear;//队尾
    private int size = 0;

    public MyLinkedQueue(){
        Node p = new Node(null,null);
        front = rear = p;
    }

    /**
     * 队列入队
     * @param data 待入队元素
     * @author yulong
     */
    public void enqueue(T data){
        Node p = new Node(data,null);
        rear.next = p;
        rear = p;
        size++;
    }
    /**
     * 队列出队
     * @return 出队元素
     */
    public T dequeue(){
        if(rear==front){
            return null;
        }
        else{
            Node p = front.next;
            T x = p.data;
            front.next = p.next;
            if(p.next==null)
                rear = front;
            p = null;
            size--;
            return x;
        }
    }
    public int size(){
        return size;
    }
    public boolean isEmpty(){
        return size==0;
    }
   }

2.队列的循环数组实现

public class MyArrayQueue<Type> {

    private final static int FULL = 10;
    private int rear;
    private int front;
    private int size;
    private Type[] theItems;

    public MyArrayQueue(){
        rear = -1;
        front = -1;
        size = 0;
        theItems = (Type[]) new Object[FULL];
    }

    public int size(){
        return size;
    }
    public boolean isEmpty(){
        return size==0;
    }
    public void enqueue(Type x){
        rear++ ;
        theItems[rear%FULL] = x;
        if(size<10){
            size++;
        }else{
            front++;//覆盖
        }
    }
    public Type dequeue(){
        if(rear==front){
            return null;
        }
        else{
            front++;
            front = front%FULL;
            size--;
            return theItems[front];
        }
    }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值