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

线性表包括:顺序表和单链表;顺序表是一串连着的内存空间,因此用数组来实现;单链表是分散的内存空间块,用对象来实现,一个结点是一个对象,对象里面有两个域,一个是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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值