自己实现顺序表和单链表以及他们的对比

来源:互联网 发布:mac照片和文稿里的图片 编辑:程序博客网 时间:2024/05/22 12:53

线性表包括:顺序表和单链表;顺序表是一串连着的内存空间,因此用数组来实现;单链表是分散的内存空间块,用对象来实现,一个结点是一个对象,对象里面有两个域,一个是data域,一个是nextNode域。

由于顺序表和单链表都涉及到迭代器模式,自己实现迭代器去迭代里面的数据,这里提供一个接口。
迭代器:
MyIterator类:

package cn.test.ArrayList;public interface MyIterator<T> {    //是否有下一个    public boolean hasNext();    public T next();    public T remove();}

顺序表:
MyArray类:

package cn.test.ArrayList;public class MyArray<T> {    private T[] elementDatas;    private int length = 0;    public int getLength() {        return length;    }    //注意length和size是不同的    public int size(){        return elementDatas.length;    }    public MyArray() {         elementDatas = (T[]) new Object[16];    }    public MyArray(int initSize){        elementDatas = (T[]) new Object[initSize];    }    //插入数据    public boolean insert(T data){        //判断elementDatas的长度        if(length >= size()){    //拓展长度            T[] elementDatas_temp = (T[])new Object[size() * 2 + 1];            migrate(elementDatas, elementDatas_temp);            elementDatas = elementDatas_temp;        }               elementDatas[length++] = data;          return true;    }    //指定位置插入数据    public boolean insert(int index, T data){        //判断插入位置的合法性        if(index < 0 || index > length){            return false;        }        if(length >= size()){    //拓展长度            T[] elementDatas_temp = (T[])new Object[size() * 2 + 1];            migrate(elementDatas, elementDatas_temp);            elementDatas = elementDatas_temp;        }           if(index == length){            return insert(data);        }else{            for(int i = length-1; i >= index; i--){                elementDatas[i+1] = elementDatas[i];            }            elementDatas[index] = data;            length++;            return true;        }    }    //在第一个位置插入数据    public boolean insertFirst(T data){        return insert(0, data);    }    //删除指定下标数据    public T delete(int index){        T data = null;        //判断位置合法性        if(index < 0 || index >= length){            return null;        }        data = elementDatas[index];        //删除        for(int i = index; i <= length-1; i++){            elementDatas[i] = elementDatas[i+1];        }        length --;        return data;    }    //删除第一个数据    public T deleteFirst(){        return delete(0);    }    //删除最后一个数据    public T deleteLast(){        return delete(length-1);    }    //删除指定数据    public T delete(T data){        for(int i = 0; i < elementDatas.length; i++){            if(data.equals(elementDatas[i])){                return delete(i);            }        }        return null;    }    //得到指定下面的值    public T get(int index){        return elementDatas[index];    }    //得到第一个值    public T getFirst(){        return get(0);    }    //得到最后一个值    public T getLast(){        return get(length-1);    }    public MyIterator<T> iterator(){        return  new MyArrayIterator();    }    private void migrate(T[] from, T[] to){        for(int i = 0; i < from.length; i++){            to[i] = from[i];        }    }           private class MyArrayIterator implements MyIterator<T>{        private int index = 0;     //未来的下标        @Override        public boolean hasNext() {            if(index <= length-1){                return true;            }            return false;        }        @Override        public T next() {            return get(index++);        }        @Override        public T remove() {            return delete(index);        }    } }

以上代码需要注意private class MyArrayIterator这个内部类,为什么设置为private,目的是不让外部访问。内部类可以访问外部类的方法,但外部类不可以直接访问内部类的方法,需要通过创建内部对象去访问。引申:(参考Thinking in java的内部类部分)

另外,如何创建泛型数组呢?我们知道private T[] ddTs = new T[12]; 是不行的;有一个办法就是先创建Object数组,然后强制转换为T,如:private T[] elementDatas = (T[]) new Object[12];

测试方法如下:
TestMyArray类:

package cn.test.ArrayList;import org.junit.Test;public class TestMyArray {    /**     * 测试size、length     */    @Test    public void test01(){        MyArray<Integer> myArray = new MyArray<Integer>();        myArray.insert(2);        myArray.insert(3);        System.out.println("size:" + myArray.size() + ", length" + myArray.getLength());                MyArray<Integer> myArray2 = new MyArray<Integer>(12);        System.out.println("size:" + myArray2.size());    }    /**     * 测试insert、delete、get     */    @Test    public void test02(){        MyArray<Integer> myArray = new MyArray<Integer>(2);        System.out.println("size:"+myArray.size());        myArray.insert(1);        myArray.insert(2);        myArray.insert(3);        myArray.insert(4);        myArray.insert(2, 100);        myArray.insertFirst(200);        System.out.println("size:"+myArray.size()+" length:"+myArray.getLength());        myArray.delete((Integer)100);        System.out.println(myArray.getLength());        MyIterator<Integer> it = myArray.iterator();        while(it.hasNext()){            System.out.print(it.next()+" ");        }    }}

以上测试方法均能得到正确的输出。

单链表:
MyOneWayLinkedList类:

package cn.test.LinkedList.OneWay;import cn.test.ArrayList.MyIterator;public class MyOneWayLinkedList<T> {    private Node<T> firstNode;    private int length;    public int getLength() {        return length;    }    //在第一个位置插入元素    public boolean insertFirst(T data){        Node<T> tmpNode = new Node<T>();        tmpNode.setData(data);        if(null == firstNode){            firstNode = tmpNode;            length++;        }        tmpNode.setNext(firstNode);        firstNode = tmpNode;        length++;        return true;            }    //在最后的位置添加元素    public boolean insertLast(T data){        //创建一个结点        Node<T> tmp = new Node<T>();        tmp.setData(data);        if(null == firstNode){            firstNode = tmp;            firstNode.setNext(null);        }else{            Node<T> node = firstNode;            for(int i = 0; i < length-1; i++){   //for循环中,要找到哪个位置                                //就要小于哪个值                node = node.getNext();            }            //插入            node.setNext(tmp);        }        length++;        return true;    }    //根据index插入元素    public boolean insert(int index, T data){        //判断index的合法性        if(index < 0 || index > length){            return false;        }        //创建结点        Node<T> node = new Node<T>();        node.setData(data);        if(0 == index){            node.setNext(firstNode);            firstNode = node;            length++;        }else{            int tmp = 0;            Node<T> tmpNode = firstNode;            while(tmp < index - 1){                tmpNode = tmpNode.getNext();                tmp++;            }            node.setNext(tmpNode.getNext());            tmpNode.setNext(node);            length++;        }        return true;    }    //删除指定位置的结点    public T delete(int index){        if(index < 0 || index > length){            return null;        }        Node<T> tmpNode = firstNode;        Node<T> returnNode = null;        if(0 == index){            returnNode = tmpNode;            firstNode = firstNode.getNext();        }else{            int tmp = 0;            while(tmp < index - 1){     //找到删除位置                tmpNode = tmpNode.getNext();                tmp++;            }            returnNode = tmpNode.getNext();            tmpNode.setNext(tmpNode.getNext().getNext());        }        length--;        return returnNode.getData();            }    //删除第一个元素    public T deleteFirst(){        if(0 == length){            return null;        }        Node<T> retNode = firstNode;        firstNode = firstNode.getNext();        length--;        return retNode.getData();    }    //删除最后一个元素    public T deleteLast(){        if(0 == length){            return null;        }        int tmp = 0;        Node<T> tmpNode = firstNode;        while(tmp < length - 2){            tmpNode = tmpNode.getNext();            tmp++;        }        Node<T> retNode = tmpNode.getNext();        tmpNode.setNext(retNode.getNext());        length--;        return retNode.getData();    }    //删除指定元素    public boolean delete(T data){        if(0 == length){            return false;        }        if(1 == length){            if(data.equals(firstNode.getData())){                firstNode = null;                length--;                return true;            }else{                return false;            }        }        int index = 0;        Node<T> tmpNode = firstNode;        while(index < length - 1){            if(data.equals(tmpNode.getNext().getData())){                tmpNode.setNext(tmpNode.getNext().getNext());                length--;                return true;            }        }        return false;    }    //得到指定下标的值    public T get(int index){        //判断下标合法        if(index < 0 || index > length){            return null;        }        int tmp = 0;         Node<T> tmpNode = firstNode;        while(tmp < index){            tmpNode = tmpNode.getNext();            tmp++;        }        return tmpNode.getData();           }    //清空链表    public void clear(){        firstNode = null;        length = 0;    }    //获取迭代器    public MyIterator<T> iterator(){        return new MyOneWayLinkedListIterator();    }    private class MyOneWayLinkedListIterator implements MyIterator<T>{        int index = 0;    //未来的下标        @Override        public boolean hasNext() {            if(index <= length - 1){  //未来的下标在合法的范围内                return true;            }            return false;        }        @Override        public T next() {            return get(index++);        }        @Override        public T remove() {            return delete(index);        }    }}

测试方法:
TestLinkedList类:

package cn.test.LinkedList.OneWay;import org.junit.Test;import cn.test.ArrayList.MyIterator;public class TestLinkedList {    @Test    public void test01(){        MyOneWayLinkedList<String> myList = new MyOneWayLinkedList<String>();        myList.insertLast("1212");        myList.insertFirst("11");        myList.insertFirst("00");        myList.insert(0, "66");        MyIterator<String> it = myList.iterator();        System.out.println(myList.getLength());        while(it.hasNext()){            System.out.print(it.next()+" ");        }    }    @Test    public void test02(){        MyOneWayLinkedList<String> myList = new MyOneWayLinkedList<String>();        System.out.println("---"+myList.getLength());        myList.insertLast("1");        myList.insertLast("2");        myList.insertLast("3");        myList.insertLast("4");        myList.insertLast("5");        myList.delete(4);               myList.clear();        System.out.println("---"+myList.getLength());        MyIterator<String> it = myList.iterator();        while(it.hasNext()){            System.out.print(it.next()+" ");        }    }}

以上测试方法均能得到正确输出

============================

顺序表和单链表的对比:
存储分配方式:
(1)顺序表:采用一段连续的存储单元一次存储数据元素
(2)单链表:采用链式存储结构,用一组任意的存储单元存储数据元素,每个存储单元都存有下一个存储单元的地址

时间性能:
1、查找:
(1)顺序表:时间复杂度为O(1)
(2)单链表:时间复杂度为O(n)
2、插入和删除:
(1)顺序表:时间复杂度为O(n),并且需要移动大量的数据元素
(2)单链表:时间复杂度为O(1),但在找到位置的过程中也需要循环,时间复杂度为O(n)
3、空间性能
(1)顺序表:创建前需要分配好多大的存储空间,这就会导致分配空间少出现内存溢出,分配空间多内存浪费
(2)单链表:创建前不需要分配空间,个数不受限制,空间利用率高

总结:经常插入删除用单链表,经常查询用顺序表

0 0