zoukankan      html  css  js  c++  java
  • 列表的实现与应用

    列表分为三种类型:a.有序列表(其元素按照元素的某种内在特性进行排序) b.无序列表(元素不存在内在顺序,按照它们在列表中的位置进行排序) c.索引列表(其元素可以用数字索引来引用)

    这里主要实现有序和无序两种列表:

    两种列表的共有操作:

    package xidian.sl.list;
    
    import java.util.Iterator;
    
    import xidian.sl.stack.EmptyCollectionException;
    import xidian.sl.tree.ElementNotFoundException;
    
    /**
     * 有序列表与无序列表的公共接口
     * */
    public interface ListADT<T> {
        /*从列表中删除第一个元素*/
        public T removeFirst() throws ElementNotFoundException;
        
        /*从列表中删除最后一个元素*/
        public T removeLast() throws ElementNotFoundException;
        
        /*从列表中删除一个特定元素*/
        public T remove(T element) throws ElementNotFoundException, EmptyCollectionException;
        
        /*检查列表的第一个元素*/
        public T first() throws ElementNotFoundException;
        
        /*检查列表的最后一个元素*/
        public T last() throws ElementNotFoundException;
        
        /*确定列表中是否包含某个特殊元素*/
        public boolean contains(T element);
        
        /*确定列表是否为空*/
        public boolean isEmpty();
        
        /*确定列表中元素的个数*/
        public int size();
        
        /*返回该列表的迭代*/
        public Iterator<T> iterator();
        
        /*重写toString方法*/
        public String toString();
    }

    有序列表的特有操作:

    package xidian.sl.list;
    
    /**
     * 有序列表特有的操作接口
     * */
    public interface OrderedListADT<T> extends ListADT<T>{
        /*向列表中添加一个元素*/
        public void add(T element);
    }

    无序列表的特有操作:

    package xidian.sl.list;
    
    import xidian.sl.tree.ElementNotFoundException;
    
    /**
     * 无序列表特有的操作接口
     * */
    public interface UnorderedListADT<T> extends ListADT<T>{
        /*添加一个元素到列表头*/
        public void addToFront(T element);
        
        /*添加一个元素到列表尾*/
        public void addToRear(T element);
        
        /*添加一个元素到列表中某个特定元素之后*/
        public void addAfter(T element, T target) throws ElementNotFoundException;
    }

    以下我们还是使用两种方式来实现列表(数组与链表)
    1.使用数组实现列表:

    共有操作的实现:

    package xidian.sl.list;
    
    import java.util.Iterator;
    
    import xidian.sl.tree.ElementNotFoundException;
    
    /**
     * 利用数组来实现
     * */
    public class ArrayList<T> implements ListADT<T>{
        //默认初始数组大小
        private final int DEFAULT_CAPACITY = 100;
        //未找个指定元素的返回常量
        private final int NOT_FOUNND = -1;
        //表示了列表中的元素数目,以及把元素添加到列表末端时的下一个可用位置
        protected int rear;
        protected T[] list;
        
        @SuppressWarnings("unchecked")
        public ArrayList(){
            rear = 0;
            list = (T[]) new Object[DEFAULT_CAPACITY];
        }
        
        @SuppressWarnings("unchecked")
        public ArrayList(int initialCapacity){
            rear = 0;
            list = (T[]) new Object[initialCapacity];
        }
    
        @Override
        public boolean contains(T element) {
            int index = find(element);
            return index != NOT_FOUNND;
        }
    
        @Override
        public T first() throws ElementNotFoundException {
            if(isEmpty()){
                throw new ElementNotFoundException("list");
            }
            return list[0];
        }
    
        @Override
        public boolean isEmpty() {
            return rear == 0? true : false;
        }
        
        /**
         * 这里为了重用代码,我们专门为列表的数组实现创建一个iterator方法。但是,我们创建了一个通用的ArrayIterator类,
         * 它可以与任何集合的数组实现一起工作
         * */
        @SuppressWarnings("unchecked")
        public Iterator<T> iterator() {
            return new ArrayIterator<T>(list, rear);
        }
    
        @Override
        public T last() throws ElementNotFoundException {
            if(isEmpty()){
                throw new ElementNotFoundException("list");
            }
            return list[rear-1];
        }
    
        /**
         * remove操作要求我们查找作为参数传递的元素,如果找到就从列表中进行删除,
         * 然后将数组中更高索引位的元素向下平移以填补空隙
         * @throws ElementNotFoundException 
         * 
         * */
        public T remove(T element) throws ElementNotFoundException {
            T result;
            int index = find(element);
            
            if(index == NOT_FOUNND){
                throw new ElementNotFoundException("list");
            }
            
            result = list[index];
            rear--;
            
            for(int scan = index; scan < rear; scan++){
                list[scan] = list[scan+1];
            }
            list[rear] = null;
            
            return result;
        }
        /**
         * find方法用于查找指定元素,如果在列表中则返回该元素的索引,如果列表中不存在该元素,则返回一个名为NOT_FOUNND的常量
         * */
        private int find(T target){
            int scan = 0, result = NOT_FOUNND;
            boolean found = false;
            
            if(!isEmpty()){
                while(!found && scan < rear){
                    if(target.equals(list[scan])){
                        found = true;
                    }else{
                        scan++;
                    }
                }
            }
            //如果存在则返回该元素的索引
            if(found){
                result = scan;
            }
            
            return result;
        }
        @Override
        public T removeFirst() throws ElementNotFoundException {
            T result;
            if(isEmpty()){
                throw new ElementNotFoundException("list");
            }
            result = list[0];
            rear--;
            
            for(int scan = 0; scan < rear; scan++){
                list[scan] = list[scan+1];
            }
            list[rear] = null;
            return result;
        }
    
        @Override
        public T removeLast() throws ElementNotFoundException {
            T result;
            if(isEmpty()){
                throw new ElementNotFoundException("list");
            }
            result = list[rear-1];
            rear--;
            
            list[rear] = null;
            return result;
        }
    
        @Override
        public int size() {
            return rear;
        }
        
        /*扩容是将数组的大小进行加倍*/
        @SuppressWarnings("unchecked")
        protected void expandCapacity(){
            T[] larger = (T[])(new Object[list.length*2]);
            for(int index = 0; index< list.length; index++){
                larger[index] = list[index];        //把原数组的内容复制到新数组中
            }
            list = larger;
        }
    }

    以上涉及到的ArrayIterator类:

    package xidian.sl.list;
    
    import java.util.Iterator;
    import java.util.NoSuchElementException;
    
    @SuppressWarnings("unchecked")
    public class ArrayIterator<T> implements Iterator{
        //记录集合中的元素数目
        private int count;
        //记录迭代的位置
        private int current;
        //需要迭代的集合
        private T[] items;
        
        public ArrayIterator(T[] collection, int size){
            items = collection;
            count = size;
            current = 0;
        }
        @Override
        public boolean hasNext() {
            return (current < count);
        }
    
        @Override
        public Object next() {
            if(!hasNext()){
                throw new NoSuchElementException();
            }
            current++;
            return items[current-1];
        }
    
        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }
        
    }

    有序列表实现:

    package xidian.sl.list;
    
    /**
     * 有序列表的实现
     * */
    public class ArrayOrderedList<T> extends ArrayList<T> implements OrderedListADT<T>{
        /**
         * add操作时将一个元素添加到有序列表的唯一方式。调用中没有指定添加到的位置,因为元素本身就决定了它们的次序。
         * 与remove操作类似,add操作也需要比较和平移操作:进行比较以找到元素在列表中的正确位置,然后平移元素以便为
         * 新元素腾出一个位置。并且每次add操作时需要进行n次比较和平移操作(如果操作时第一个元素,则需1次比较,n-1次
         * 平移,如果是最后一个元素,则需n次比较0次平移)
         * */
        @SuppressWarnings("unchecked")
        @Override
        public void add(T element) {
            //首先查看列表大小,必须时进行扩容
            if(size() == list.length){
                expandCapacity();
            }
            //将元素转化为Comparable对象
            Comparable<T> temp = (Comparable<T>)element;
            //该元素与列表中的其他元素比较大小,选出插入位置
            int scan = 0;
            while(scan < rear && temp.compareTo(list[scan]) > 0){
                scan++;
            }
            //比插入位置索引值大的元素进行平移
            for(int scan2 = rear; scan2 > scan; scan2--){
                list[scan2] = list[scan2-1];
            }
            //将该元素插入到列表
            list[scan] = element;
            rear++;
        }
    }

    无序列表实现:

    package xidian.sl.list;
    
    import xidian.sl.tree.ElementNotFoundException;
    
    public class ArrayUnorderedList<T> extends ArrayList<T> implements UnorderedListADT<T>{
        
        @Override
        public void addAfter(T element, T target) throws ElementNotFoundException {
            //首先查看列表大小,必须时进行扩容
            if(size() == list.length){
                expandCapacity();
            }
            //查找应该插入的位置
            int scan = 0;
            while(scan < rear && !target.equals(list[scan])){
                scan++;
            }
            if(scan == rear){
                throw new ElementNotFoundException("list");
            }
            scan++;
            //平移
            for(int scan2 = rear; scan2 > scan; scan2--){
                list[scan2] = list[scan2-1];
            }
            //将该元素插入到列表
            list[scan] = element;
            rear++;
        }
    
        @Override
        public void addToFront(T element) {
            //首先查看列表大小,必须时进行扩容
            if(size() == list.length){
                expandCapacity();
            }
            //对所有元素进行一次平移
            for(int scan = rear; scan > 0; scan--){
                list[scan] = list[scan-1];
            }
            //将该元素插入到列表
            list[0] = element;
            rear++;
        }
    
        @Override
        public void addToRear(T element) {
            //首先查看列表大小,必须时进行扩容
            if(size() == list.length){
                expandCapacity();
            }
            //将该元素插入到列表
            list[rear] = element;
            rear++;
        }
    
    }


    2.使用链表实现列表(主要实现了remove方法)

    package xidian.sl.list;
    
    import java.util.Iterator;
    
    import xidian.sl.stack.EmptyCollectionException;
    import xidian.sl.stack.LinearNode;
    import xidian.sl.tree.ElementNotFoundException;
    
    /**
     * 使用链表实现列表
     * */
    public class LinkedList<T> implements ListADT<T>{
        protected int count;
        protected LinearNode<T> head, tail;
        
        public LinkedList(){
            count = 0;
            head = tail = null;
        }
        
        @Override
        public boolean contains(T element) {
            return false;
        }
    
        @Override
        public T first() throws ElementNotFoundException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public boolean isEmpty() {
            return (count == 0);
        }
    
        @Override
        public Iterator<T> iterator() {
            return new LinkedIterator<T>(head, count);
        }
    
        @Override
        public T last() throws ElementNotFoundException {
            // TODO Auto-generated method stub
            return null;
        }
    
        /**
         * 利用单向链表来实现remove方法
         * */
        public T remove(T element) throws ElementNotFoundException, EmptyCollectionException {
            if(isEmpty()){
                throw new EmptyCollectionException("list");
            }
            
            boolean found = false;
            LinearNode<T> previous = null;
            LinearNode<T> current = head;
            
            while(current != null && !found){
                if(element.equals(current.getElement())){
                    found = true;
                }else{
                    previous = current;
                    current = current.getNext();
                }
            }
            if(!found){
                throw new ElementNotFoundException("list");
            }
            if(size() == 1){
                head = tail = null;
            }else if(current.equals(head)){
                head = current.getNext();
            }else if(current.equals(tail)){
                tail = previous;
                tail.setNext(null);
            }else{
                previous.setNext(current.getNext());
            }
            count--;
            
            return current.getElement();
        }
    
        @Override
        public T removeFirst() throws ElementNotFoundException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public T removeLast() throws ElementNotFoundException {
            // TODO Auto-generated method stub
            return null;
        }
    
        @Override
        public int size() {
            return count;
        }
        
    }

    涉及到的LinkedIterator类:

    package xidian.sl.list;
    
    import java.util.Iterator;
    import java.util.NoSuchElementException;
    
    import xidian.sl.stack.LinearNode;
    
    public class LinkedIterator<T> implements Iterator<T>{
        private int count;
        private LinearNode<T> current;
        
        public LinkedIterator(LinearNode<T> collection, int size){
            current = collection;
            count = size;
        }
        
        @Override
        public boolean hasNext() {
            return (current != null);
        }
    
        @Override
        public T next() {
            if(! hasNext()){
                throw new NoSuchElementException();
            }
            T result = current.getElement();
            current = current.getNext();
            
            return result;
        }
    
        @Override
        public void remove() {
            // TODO Auto-generated method stub
            throw new UnsupportedOperationException();
        }
        
    }

    下面我来介绍一下那个双向链表(存储着上一节点的引用和下一节点的引用),以前我们实现集合都是使用的是单向列表(只存储下一个节点的引用,)

    package xidian.sl.list;
    
    /**
     * 双向链表:存储着上一节点的引用和下一节点的引用
     * */
    public class DoubleNode<T> {
        private DoubleNode<T> next;
        private T element;
        private DoubleNode<T> previous;
        
        public DoubleNode(){
            next = null;
            element = null;
            previous = null;
        }
        
        public DoubleNode(T ele){
            next = null;
            element = ele;
            previous = null;
        }
    
        public DoubleNode<T> getNext() {
            return next;
        }
    
        public void setNext(DoubleNode<T> next) {
            this.next = next;
        }
    
        public T getElement() {
            return element;
        }
    
        public void setElement(T element) {
            this.element = element;
        }
    
        public DoubleNode<T> getPrevious() {
            return previous;
        }
    
        public void setPrevious(DoubleNode<T> previous) {
            this.previous = previous;
        }
        
        
    }


    列表的应用:组织赛程:

  • 相关阅读:
    android 访问SD卡的方法
    android 用Achartengine 作图
    hello
    IIS 7.0 "确认文件是否存在"功能
    test
    收藏:如何在Web页面上直接打开、编辑、创建Office文档
    JavaScript面向对象技术
    正则表达式30分钟入门教程
    JWT有状态登陆与无状态登陆
    20条JavaScript代码简洁的写法
  • 原文地址:https://www.cnblogs.com/shenliang123/p/2916158.html
Copyright © 2011-2022 走看看