数据结构(Java 实现)之线性表

最近从图书馆借了一本数据结构(Java 语言描述)的书,作者是丁海军老师。上过 C 语言版实现的课程,觉得两者思路大致一样,只是在表达方式有所不同,学完第一章线性表之后,决定写一篇博客为自己总结一下学习情况。

线性表(list)是一种线性结构。线性结构的特点是具有相同数据类型的 n (n >= 0) 个数据元素的有限序列,它们一个接着一个排列,第一个元素没有直接前驱,最后一个元素没有直接后继,中间的元素有一个直接前驱和一个直接后继。当线性表的长度为 0 时,成为空表,表示一个元素都没有。

数据结构的三要素,即数据的逻辑结构、数据的存储结构、数据操作。

数据的逻辑结构是对数据结构的数学抽象,它独立于计算机,是数据元素与数据元素之间存在的一种关系。数据的存储结构也叫物理存储结构,它是数据结构在计算机的实现。主要分为顺序存储结构和链式存储结构,线性表也从这两个结构来实现。数据操作,也就是我们可以在这个数据结构上进行的操作。如最基本的增、删、改、查。

下面我们使用 Java 先实现线性表的顺序存储结构,也叫顺序表。而链式存储结构实现的我们可以称为链表。既然线性表是抽象的,那么就我们可以抽象出来一些顺序表和链表共同的部分,这部分独立于计算机的实现,我们把它定义为一个抽象类 AbsList。下面是这个类的代码部分。

package oldbiwang.ds;
import java.util.Iterator;
public abstract class AbsList<T> implements Iterable<T> {
        //长度
        protected int length;
        //返回第 i (i >= 0)个元素
        abstract public T get(int i);
        //设置第 i 个元素为 x
        abstract public boolean set(int i, T x);
        //查找,返回首次出现的关键字为 key 的元素
        abstract public int indexOf(int begin, int end, T o);
        //插入 x 作为第 i 个元素
        abstract public void add(int i, T x);
        //删除第 i 个位置的数据元素并返回删除对象
        abstract public void remove(int i)
        //返回一个迭代器
        abstract public Iterator<T> iterator();
        //判断线性表是否为空
        public boolean isEmpty() {
            return length == 0;
        }
        //返回线性表长度
        public int length() {
            return length;
        }
        //在线性表最后插入 x 元素
        public void add(T x) {
            add(length, x);
        }
        public void append(T x) {
            add(length, x);
        }
        public int indexOf(T o) {
            return indexOf(0, length, o)
        }
        public int indexOf(int begin, T o) {
            return indexOf(begin, length, o);
        }
        public T remove(T o) {
            return remove(indexOf(o));
        }
}

我们实现顺序表 SeqList 将继承 AbsList 抽象类,它的结构大致如下:
线性表

输入图片说明

下面是 SeqList.java 的代码

public class SeqList extends AbsList<T> implements Iterable<T> {
    //顺序表的增量长度,用于扩容
    private int incrementSize;
    //保存顺序表数据的数组
    protected T[] data;
    //默认构造函数
    public SeqList() {
        //顺序表默认长度设置为 16,后期可自动增加
        this(16);
    }
    //capacity 是顺序表的容量
    @SuppressWarings("unchecked")
    public SeqList(int capacity) {
        if(capacity <= 0)
            capacity = 16;
        //顺序表的长度设置为 0
        length = 0;
        //增量因子为 0
        incrementSize = 0;
        //Java 没有泛型数组,用 Object[] 数组代替,分配 16 个数组元素
        data = (T[])new Object[capacity];
    }
    //用数组 elem 初始化顺序表
    public SeqList(T[] elem) {
        length = elem.length;
        incrementSize = 0;
        data = elem;
    }
    public void setInc(int inc) {
        //设置顺序表每次容量增加时增量大小,默认值为 16
        incrementSize = inc;
    }
    //将顺序表的分配空间重新设置为 newSize
    public void setCapacity(int newSize) {
        data = Arrays.copyOf(data, newSize);
    }
    //设置长度
    public void setLength(int len) {
        if(len > data.length)
            grow();
        else if(len < 0)
            len = 0;
        length = len;
    }
    //获取顺序表的长度,同 size() ,为了方便
    public int size() {
        return length;
    }
    //取得顺序表下标为 i 的元素,也就是 data[i]
    @Override
    public T get(int i) {
        if(i < 0 || i > length - 1)
            return null;
        return data[i];
    }
    //实现两个元素的比较
    private int compare(T a, T b) {
        if(a instanceOf Comparable &&
            b instanceOf Comparable);
            return ((Comparable)a).compareTo((Comparable)b);
        else
            return (a.toString().compareTo(b.toString()));
    }
    //交换下标为 i 的元素值
    public void swap(int i, int j) {
        T temp = data[i];
        data[i] = data[j];
        data[j] = temp;
    }
    //查找值为 o 的数据元素的下标,使用顺序查找算法
    @Override
    public int indexOf(int begin, int end, T o) {
        //判断 o 是否为空
        if(o == null) {
            for(int i = begin; i < end; i++) {
                if(data[i].equals(o))
                    return i;
            }
        }
        else {
            for(int i = begin; i < end; i++) {
                //元素可以自定义 equals 函数
                if(data[i].equals(o))
                    return i;
            }
        }
        return -1;
    }
    //取逻辑下标为 i 的元素,同 get(i)
    public T valueOf(int i) {
        return get(i);
    }
    //内部使用,自动增加顺序表的容量
    private void grow() {
        int newSize;
        if(incrementSize == 0)
            newSize = (int)(1.618 * length);
        else
            newSize = incrementSize + data.length;
        data = Arrays.copyOf(data, newSize);
    }
    //在位置 i 插入数据元素 x
    @Override
    public void add(int i, T x) {
        if(length == data.length)
            grow();
        if(i < 0)
            i = 0;
        if(i > length)
            i = length;
        //从最后一个元素开始到 i 都往后移一个位置
        for(int j = length - 1; j >= i; j--)
            data[j + 1] = data[j];
        data[i] = x;
        length++;
    }
    //以有序的方式向顺序表增加数据元素 x
    public void addSort(T x) {
        insertOrder(length, x);
        length++;
    }
    //对顺序表排序
    public void sort() {
        /*
        利用 insertOrder 函数,它有两个参数,end 为整型,表示下标为 i(包括i) 之前的元素被排序,x 类型为 T,表示下标为 i 的那个元素。先从顺序表第 1、2个元素开始排序,
        然后将1、2个元素排好序后再与第三个元素比较之后排序,依次类推,直到最后一个元素,这样顺序表就是排好序的顺序表,书里说这种方法就插入排序。也就是说以先前排好的顺序再与后一位元素比较排序,直到最后一个元素,得到一个排好序的顺序表。
        */
        Iterator<T> itr = iterator();
        itr.next();
        int i = 1;
        for(; itr.hasNext();) {
            insertOrder(i, itr.next());
            i++;
        }
    }
    //内部使用,以有序方式插入数据元素 x
    protected void insertOrder(int end, T x) {
        //length 是线性表的长度,data.length 代表的是给 data 数组分配空间的长度
        if(length == data.length)
            grow();
        int k;
        for(k = end - 1; k >= 0; k--) {
            if(comapre(x, data[k]) < 0)
                data[k + 1] = data[k];
            else
                break;
        }
        data[k + 1] = x;
    }
    //删除下标为 i 的元素
    @Override
    public T remove(int i) {
        if(i < 0 || i > length - 1)
            throw new IndexOutOfBoundsException("下标越界 i = " + i);
        T olddata = (T)data[i];
        for(int j = i; j < length - 1; j++)
            data[j] = data[j + 1];
        data[--length] = null;
        return olddata;
    }
    //清除整个顺序表
    @Override
    public void clear() {
        // let gc do its work
        for(int i = 0; i < length; i++)
            //让 Java 虚拟机的垃圾收集器自动处理
            data[i] = null;
        length = 0;
    }
    //顺序表的最大容量
    public int getCapacity() {
        return data.length;
    }
    @Override
    public String toString() {
        StringBuilder strb = new StringBuilder("(");
        for(int i = 0; i < length - 1; i++)
            strb = strb.append(data[i].toString() + ",");
        strb = strb.append(data[length - 1].toString() + ")");
        return new String(strb);
    }
    //将顺序表转换为 object 数组
    public Object[] toArray() {
        return Arrays.copyOf(this.data, this.length);
    }
    //将顺序表转换为类型为 E 的数组
    public T[] toArray(T[] a) {
        if(a.length < length)
            //Make a new array of as runtime type,but my contents:
            return (T[])Arrays.copyOf(this.data, this.length);
        System.arraycopy(this.data, 0, a, 0, this.length);
        if(a.length > this.length)
            a[length] = null;
        return a;
    }
    /////////////////////////////
    public Iterator<T> iterator() {
        return new MyIterator();
    }
    //内部类,迭代器
    class MyIterator implements Iterator<T> {
        private int index = 0;
        public boolean hasNext() {
            //只要在调用 next()后,index 自加,确保 index 不等于顺序表的长度
            return index != length;
        }
        @Override
        public T next() {
            //使用索引来获取 SeqList 中下标为 index的项
            return get(index++);
        }
        @Override
        public void remove() {
            //为实现这个方法
        }
    }
    //MyIterator end
    ///////////////////////////////////
    /*
    *   @param args
    */
    public static void main(String[] args) {
        SeqList<Integer> ms = new SeqList<Integer>();
        for(int i = 0; i < 10; i++)
            ms.add((int)(10 * (9 - i + 1)));
        System.out.println(ms);
        System.out.println(ms.get(2));
        System.out.println(ms.getCapacity());
        System.out.println(ms.length());
        System.out.println("indexOf:" + ms.indexOf(60));
        System.out.println("==========================");
        for(integer x: ms) {
            System.out.println(x + ",");
        }
        SeqList myseq = new SeqList(10);
        myseq.add(1);
        myseq.add("oldbiwang");
        myseq.add("王锐鹏");
        myseq.add(25.0);
        System.out.println();
        System.out.println(myseq);
        System.out.println(myseq.get(0).getClass());
        System.out.println(myseq.get(1).getClass());
        System.out.println(myseq.get(2).getClass());
        System.out.println(myseq.get(3).getClass());
        //测试一个简单的 pojo 的类 Person
        SeqList<Person> sp = new SeqList<Person>(10);
        Person p1 = new Person();
        p1.setName("1王锐鹏");
        p1.setSex("男");
        sp.add(p1);
        Person p2 = new Person();
        p2.setName("2张三");
        p2.setSex("男");
        sp.add(p2);
        Person p3 = new Person();
        p3.setName("3貂蝉");
        p3.setSex("女");
        sp.add(p3);
        Person p4 = new Person();
        p4.setName("4阿尔法");
        p4.setSex("男");
        sp.add(p4);
        Person p5 = new Person();
        p5.setName("5阿尔法");
        p5.setSex("男");
        //重写 equals 方法,name 和 sex 都相等才是相等
        System.out.println(sp.indexOf(p5));
        /*System.out.println(p1 instanceof Comparable);
        System.out.println(p2 instanceof Comparable);
        System.out.println(p3 instanceof Comparable);*/
        //注意要这样调用 sp.indexOf(p3); indexOf(p3);会报错
        System.out.println(sp.indexOf(p3));
        System.out.println("排序前:");
        System.out.println(sp);
        /*  Iterator<Person> itr = sp.iterator();
        System.out.print("( ");
        for(;itr.hasNext();){
            System.out.print("[" + itr.next() + "]" + " ");
        }
        System.out.println(" )"); */
        //System.out.println(sp.get(0));
        sp.sort();
        Person p6 = new Person();
        p6.setName("6欧比旺");
        p6.setSex("男");
        System.out.println("排序前:");
        System.out.println(sp);
        System.out.println(sp.length());
        System.out.println("有序添加元素:");
        sp.addSort(p6);
        System.out.println(sp.length());
        System.out.println(sp);
        //在下标i 为 3的地方增加元素
        sp.add(3, p5);
        System.out.println(sp);
        sp.sort();
        System.out.println(sp);
        //在表尾增加元素
        sp.add(p5);
        System.out.println(sp);
        //删除第一个 p5 元素
        sp.remove(p5);
        System.out.println(sp);
        sp.remove(p5);
        System.out.println(sp);
        //得到下标为 3 的元素
        System.out.println("下标为 3 的元素" + sp.get(3));
        //修改下标为 3  的元素
        sp.set(3, p5);
        System.out.println(sp);
        Object[] array = sp.toArray();
        for(int i = 0; i < array.length; i++) {
            System.out.println((Person)array[i]);
        }
        Person[] a = new Person[15];
        a = sp.toArray(a);
        System.out.println(a);
        for(int i = 0; i < a.length; i++) {
            System.out.println(a[i]);
        }
    }
}

下面给出 Person.java 的代码

package oldbiwang.ds;
public class Person implements Comparable<Person> {
    String name;
    String sex;
    public String getName() {
        return name;
    }
    public void setName(String name)  {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public String toString() {
        return "name: " + name + " sex: " + sex;
    }
    @Override
    //实现 compareTo 方法
    public int compareTo(Person o) {
        if(name.compareTo(o.name) < 0)
            return -1;
        else
            return 1;
    }
    /*
    public boolean equals(Person o) {
        System.out.println("equals in");
        if(name.equals(o.name) && sex.equals(o.sex))
            return true;
        else
            return false;
    }*/
    @Override
    public boolean equals(Object o) {
        //System.out.println("equals in");
        if(name.equals(((Person)o).name) && sex.equals(((Person)o).sex))
            return true;
        else
            return false;
    }
}

至此顺序表的基本功能实现和测试基本完成,要附加功能的话也可以随时增加,比较复杂的是顺序的排序,领会插入排序的实现,还有一个就是迭代器的实现和使用,它可以屏蔽顺序表内部的实现细节,提供一个接口。

我们将实现链表 LinkList 将继承 AbsList 抽象类,它的结构大致如下:
线性表

输入图片说明

我们将用一个类 Lnode 来表示链表的结点
Lnode.java 的实现代码如下:

package oldbiwang.ds;
//链表节点
public class Lnode<T> implements Comparable<Lnode<T>> {
    //数据域
    public T data;
    //指针域,指向下一个元素
    public Lnode<T> next;
    public Lnode(T key) {
        data = key;
        next = null;
    }
    public Lnode(T key, Lnode<T> e) {
        data = key;
        next = e;
    }
    public boolean equals(Object e) {
        Lnode<T> node = (Lnode<T>)e;
        return data.equals(node.data);
    }
    //实现 Comparable 接口的 compareTo 方法
    public int compareTo(Lnode<T> e) {
        Comparable<T> x;
        if(data instanceof Comparable) {
            x = (Comparable)data;
            return (int)x.compareTo(e.data);
        }
        else
            throw new ClassCastException("类型无法比较!");
    }
    public String toString() {
        return data.toString();
    }
}

接下来是链表的 Java 实现,LinkList.java 如下:

package oldbiwang.ds;
import java.util.Iterator;
public class LinkList<T> extends AbsList<T> implements Iterable<T> {
    //指向表头的头指针
    Lnode<T> first;
    //指向表尾的尾指针
    Lnode<T> last;
    //当前指针 写的时候忘了
    Iterator<T> itr = null;
    //默认构造函数
    public LinkList() {
        first = last = null;
        length = 0;
        //写的时候忘记了
        itr = new LinkIterator();
    }
    //写的时候忘了
    //比较两个结点的大小
    private int compare(Lnode<T> a,Lnode<T> b) {
        return a.compareTo(b);
    }
    //清除操作
    public void clear() {
        first = last = null;
        length = 0;
    }
    //写的时候忘了
    public int length() {
        return length;
    }
    //写的时候忘了
    public int size() {
        return length;
    }
    //得到第 i 个元素,从 0 开始计数
    public Lnode<T> getNode(int i) {
        if(i < 0 || i > length - 1)
            return null; //忘记判断
        //忘记判断头结点
        if(i == 0)
            return first;
        Lnode<T> p = first;
        int j = 0;
        while(p != null && j < i) {
            p = p.next;
            j++;
        }
        return p;
    }
    //得到第 i 个元素的值
    public T get(int i) {
        Lnode<T> node = getNode(i);
        if(node != null)
            return node.data;
        else
            return null;
    }
    //修改第 i 个元素的值,从 0 开始计数
    public boolean set(int i, T x) {
        Lnode<T> node = getNode(i);
        if(node != null) {
            node.data = x;
            return true;
        }
        else
            return false;
    }
    //增加结点操作
    public void add(int i, T o) {
        Lnode<T> p;
        Lnode<T> node = new Lnode<T>(o, null);
        int j = i - 1;
        //忘记写 length == 0
        if(first == null || length == 0) {
            //在空链表中插入结点 node
            first = node;
            last = node;
        }
        else if(j < 0) {
            //在头结点之前插入结点 node
            node.next = first;
            first = node;
        }
        else if(j >= length - 1) {
            //在尾结点之后插入 结点node
            last.next = node;
            last = node;
        }
        else{
            //在链表中间插入结点 s
            p = getNode(j);
            node.next = p.next;
            p.next = node;
        }
        length++;
    }
    /*//我写的增加结点操作,有一些错误与冗余
    public void add(int i, T o) {
        Lnode<T> node = new Lnode<T>(o, null);
        int j = i - 1;
        if(first == null) {
            first = node;
            last = node;
            length++;
            return;
        }
        if(i <= 0) {
            node.next = first;
            first = node;
            length++;
            return;
        }
        if(i > 0 && i < length) {
            Lnode<T> p = getNode(j);
            node.next = p.next;
            p.next = node;
            length++;
            return;
        }
        if(i >= length) {
            last.next = node;
            last = node;
            length++;
            return;
        }
    }*/
    //下面三个 add 方法写的时候都忘记写了
    public void add(T key) {
        add(length, key);
    }
    public void addBack(T key) {
        add(length, key);
    }
    public void addFront(T key) {
        add(0, key);
    }
    //这个写的时候没思路
    public void sort() {
        LinkList<T> sl = new LinkList<T>();
        Lnode<T> p;
        p = this.removeNode(0);
        while(p != null) {
            sl.insertOrder(p);
            p = this.removeNode(0);
        }
        this.first = sl.first;
        this.last = sl.last;
        this.length = sl.length;
    }
    //这个方法我已经忘记
    public void addSort(T e) //throws NoComparatorOfType
    {
        Lnode<T> s = new Lnode<T>(e, null);
        insertOrder(s);
    }
    private void insertOrder(Lnode<T> s) //throws NoComparatorOfType
    {
        Lnode<T> p1,p2;
        length = length + 1;
        if(first == null) {
            //空链表
            first = s;
            last = first;
            return;
        }
        if(compare(s, first) < 0) {
            s.next = first;
            first = s;
            return;
        }
        if(compare(s,last) >= 0) {
            last.next = s;
            last = s;
            return;
        }
        //被插结点 p 在 p1 和 p2 之前
        p2 = first;
        p1 = p2;
        while(p2 != null) {
            if(compare(s, p2) > 0) {
                p1 = p2;
                p2 = p2.next;
            }
            else
                break;
        }
        s.next = p2;
        p1.next = s;
        return;
    }
    ///////////////////////////////////
    public void removeAll() {
        clear();
    }
    //写的时候忘记了
    public T remove(int i) {
        Lnode<T> p = removeNode(i);
        if(p != null)
            return p.data;
        else
            return null;
    }
    //删除结点第 i 号结点,从 0 开始计数
    public Lnode<T> removeNode(int i) {;
        Lnode<T> p,q;
        if(first == null)
            return null;
        if(i == 0) {
            p = first;
            first = first.next;
            length = length - 1;
            return p;
        }
        if(i >= 1 && i <= length - 1) {
             p = getNode(i - 1);
             q = p.next;
             p.next = q.next;
             if(q == last) {
                 last = p;
             }
             return q;
        }
        return null;
    }
    //下面三个方法写的时候忘记了
    public T removeFront() {
        return removeNode(0).data;
    }
    public T removeBack() {
        return removeNode(length - 1).data;
    }
    public T remove() {
        return removeNode(0).data;
    }
    public int indexOf(int begin, int end, T key) {
        Lnode<T> p = getNode(begin);
        int i = begin;
        while(p != null && i < end) {
            if(p.data.equals(key))
                return i;
            p = p.next;
            i++;
        }
        return -1;
    }
    //写的时候忘记了
    public T search(T key) {
        Lnode<T> p =  getNode(0);
        while(p != null) {
            if(p.data.equals(key))
                return p.data;
            p = p.next;
        }
        return null;
    }
    //写的时候忘记了
    public boolean contains(T key) {
        if(indexOf(key) == -1)
            return false;
        else
            return true;
    }
    public String toString() {
        Lnode<T> p = first;
        if(p == null)
            return "(  )";
        String str = "(";
        while(p != null)
        {
            if(p == last) {
                    str = str + p.data.toString() + ")";
                    break;
            }
            else
                str = str + p.data.toString() + "->";
            p = p.next;
        }
        return str;
    }
    public Object[] toArray() {
        Object[] a = new Object[length];
        Lnode<T> p = first;
        for(int i=0;i<length;i++) {
            a[i] = p.data;
            p = p.next;
        }
        return a;
    }
    @SuppressWarnings("unchecked")
    public <E> E[] toArray(E[] a) {
        if(a.length < length)
            a = (E[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(),length);
        int i = 0;
        Object[] result = a;
        Lnode<T> x = this.first;
        for(i = 0; i < length; i++) {
            result[i] = x.data;
            x = x.next;
        }
        if(a.length < length)
            a[length] = null;
        return a;
    }
    public Iterator<T> iterator() {
        this.itr = new LinkIterator();
        return this.itr;
    }
    //内部类,迭代器
    private class LinkIterator implements Iterator<T> {
        private int index = 0;
        private Lnode<T> current = first;
        public boolean hasNext() {
            //只要在调用next()后,index自加,确保
            return (index != length() &&
            current != null);
        }
        @Override
        public T next() {
            T temp = current.data;
            current = current.next;
            index++;
            return temp;
        }
        public int nextIndex() {
            return index++;
        }
        @Override
        public void remove() {
            //未实现这个方法
        }
    }
    public static void main(String[] args) {
        LinkList<Person> linkList = new LinkList<Person>();
        Person p1 = new Person();
        p1.setName("Obiwan");
        p1.setSex("male");
        linkList.add(p1);
        Person p2 = new Person();
        p2.setName("Yoda");
        p2.setSex("male");
        linkList.add(p2);
        Person p3 = new Person();
        p3.setName("Vader");
        p3.setSex("male");
        linkList.add(p3);
        Person p4 = new Person();
        p4.setName("Lisa");
        p4.setSex("female");
        linkList.add(p4);
        System.out.println(linkList);       
        //排序
        System.out.println("排序后");
        linkList.sort();
        System.out.println(linkList);
        //方法一:迭代器使用 foreach 输出
        System.out.println("foreach 输出:");
        for(Person p : linkList)
            System.out.println(p);
        //方法二:迭代器使用 while 和 iterator 循环输出
        System.out.println("iterator 输出:");
        Iterator<Person> itr = linkList.iterator();
        while(itr.hasNext()) {
            System.out.println(itr.next() + " ");
        }
        System.out.println("\n===============================");
        System.out.println("length = " + linkList.length());
        System.out.println("size = " + linkList.size());
        Person p5 = new Person();
        p5.setName("Obiwan");
        p5.setSex("male");
        System.out.println("contains p5: " + linkList.contains(p5));
        System.out.println("p5 index of: " + linkList.indexOf(p5));
        System.out.println("search p5: " + linkList.search(p5));
        Person p6 = new Person();
        p6.setName("Oldbiwang");
        p6.setSex("male");
        linkList.addSort(p6);
        System.out.println("addSort: " + linkList);
        System.out.println("===============================\n");
        System.out.println("===============================");
        Person p7 = new Person();
        p7.setName("Luke");
        p7.setSex("male");
        System.out.println("before addFront: " + linkList);
        linkList.addFront(p7);
        System.out.println("after addFront: " + linkList);
        linkList.addBack(p7);
        System.out.println("after addBack: " + linkList);
        Person pGet = linkList.get(3);
        System.out.println("pGet: " + pGet);
        System.out.println("after Get:" + linkList);
        linkList.set(linkList.length() - 1,p1);
        System.out.println("after set:" + linkList);
        linkList.remove(linkList.size() - 1);
        System.out.println("after remove: " + linkList);
        System.out.println("再次排序");
        linkList.sort();
        System.out.println(linkList);
        System.out.println("===============================\n");
        System.out.println("toObjectArray");
        Object[] o = linkList.toArray();
        for(Object person : o) {
            System.out.println("person: " + (Person)person);
        }
        System.out.println("to E Array");
        //Person[] e = new Person[4];输出都为空.所以数组长度要大于链表长度
        Person[] e = new Person[10];
        linkList.toArray(e);
        for(int i = 0; i < e.length; i++) {
            System.out.println("person: " + e[i]);
        }
    }
}

链表的基本实现和测试也基本完成,使用的也是 pojo Person 类,链表的排序比较简单,新创建一个链表,将没排序链表的值插入进去,最后得到一个排好序的链表再返回来。链表是链式存储,也就是在内存里的位置地址不是连续的,而是分散的。

总结:顺序表和链表都是线性表的实现,它们各有优点,各有缺点。如果是经常改变的结构,如插入、删除等操作比较频繁的,使用链表好一点。如果对于不经常改变,查询和修改元素值比较多的结构,就多使用顺序表。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值