数据结构与算法之链表(一)顺序表(ArrayList)的实现

开篇

近日由于出了一场意外受伤赋闲在家养伤,由于非科班出身,关于素有程序员的“易筋经”---数据结构与算法这块,都是在闲散的业余时间学习的,没有拿出整块的时间进行系统的研究与总结,也许这次伤病就是老天让我好好学习总结这块的知识,修炼内功吧!网上讲数据结构与算法的博客一堆,我也看了不少,最喜欢这位吴泽坚大神的专栏:https://my.csdn.net/javazejian,这里向大家安利一下,这个系列博客的准备工作也是基于他的数据结构专题的,目的也仅仅在于在拜读大神的文章的基础上,加点自己的理解,进行学习总结,个人建议优先看他的文章吧,写的棒棒哒!今天就从最简单的顺序表开始学习,在实现顺序表的过程中,我参考了JDK的部分源码,不过原理都是一样的。

顺序表的特点

1.它是线性表的一种,原理采用数组实现;
2.存储结构为一片连续的内存;
3.由于是线性存储结构,所以读写效率高,增删效率低。

接口定义

仿照JDK,定义的最顶层的接口是集合接口:

public interface Collection<T> {
    int size();//大小
    boolean isEmpty();//是否为空
    void clear();//清空
    boolean contains(T item);//是否包含元素
    boolean add(T item);//添加
    boolean remove(T item);//删除
}

由于列表有元素索引和迭代器的概念,所以与集合相比,列表接口定义多了一下方法声明:

public interface List<T> extends Collection<T>{
    T get(int index);//读
    T set(int index, T item);//写
    void add(int index, T item);//增
    T remove(int index);//删
    Iterator<T> iterator();//迭代器
}

顺序表实现List接口,下面分别说明其实现

顺序表实现

成员变量:

public class ArrayList<T> implements List<T>{
    private static final int DEFAULT_SIZE = 64;//数组默认大小
    private int mSize;//当前元素
    private T[] mItems;//元素数组空间
    .....
}

1.增加元素逻辑:如果没有超出当前容量,则直接赋值,否则扩容。扩容逻辑分两步:开辟内存和数组内容拷贝。

    /**
     * 扩容操作
     * @param newCapacity 目标容量
     */
    private void ensureCapacity(int newCapacity) {
        if (newCapacity < mSize) {
            return;
        }
        //申请新空间
        mItems = (T[]) new Object[newCapacity];
        T[] oldItems = mItems;
        //迁移数组
        for (int i = 0; i < size(); i++) {
            mItems[i] = oldItems[i];
        }
    }

增加元素:

    @Override
    public boolean add(T item) {
        add(size(), item);
        return true;
    }

    @Override
    public void add(int index, T item) {
        //边界条件判断
        if (item == null) {
            return;
        }
        //插入下标的容错判断,插入在最前面
        if (index < 0) {
            index = 0;
        }

        //插入下标的容错判断,插入在最后面
        if (index > size()) {
            index = size();
        }

        if (mItems.length == size()) {//当前容量已达上限,扩容
            ensureCapacity(size() * 2);
        }

        //index后的元素后移
        for (int i = mSize; i > index; i--) {
            mItems[i] = mItems[i - 1];
        }
        //目标位置设置值
        mItems[index] = item;
        mSize++;//size++
    }

2.删除元素逻辑:和增加逻辑相似,从插入位置往后到结尾,元素前移。

    @Override
    public T remove(int index) {
        //边界条件判断
        if (index < 0 || index >= size()) {
            throw new ArrayIndexOutOfBoundsException();
        }

        T toRemoveItem = mItems[index];
        //删除位置后面的元素前移
        for (int i = index; i < size() - 1; i++) {
            mItems[i] = mItems[i + 1];
        }
        mSize--;
        return toRemoveItem;
    }

3.改动和读取元素

   @Override
    public T set(int index, T item) {
        if (index < 0 || index >= size()) {
            throw new ArrayIndexOutOfBoundsException();
        }
        T oldItem = mItems[index];
        mItems[index] = item;
        return oldItem;
    }

   @Override
    public T get(int index) {
        if (index < 0 || index >= size()) {
            throw new ArrayIndexOutOfBoundsException();
        }
        return mItems[index];
    }

4.迭代器实现。
以上代码实现了顺序表的基本操作,下面说说线性表的迭代器。参照JDK源码,迭代器保存了当前遍历的元素位置,根据这个位置来读取和删除元素,接口定义:

public interface Iterator<T> {
    boolean hasNext();//有无下一元素
    T next();//读元素
    void remove();//删除当前元素
}

实现原理示意图:
迭代器原理.png
    private class ArrayListIterator implements Iterator<T> {
        private int mCurrentPos;

        @Override
        public boolean hasNext() {
            return mCurrentPos < size();
        }

        @Override
        public T next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            //读完当前元素后,位置后移
            return mItems[mCurrentPos++];
        }

        @Override
        public void remove() {
            //位置回退,删除当前元素
            ArrayList.this.remove(--mCurrentPos);
        }
    }

5.其他方法实现:

@Override
    public boolean contains(T item) {
        Iterator<T> iterator = iterator();
        while (iterator.hasNext()) {
            T obj = iterator.next();
            if (obj.equals(item)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean remove(T item) {
        Iterator<T> iterator = iterator();
        while (iterator.hasNext()) {
            T obj = iterator.next();
            if (obj.equals(item)) {
                iterator.remove();
            }
        }
        return false;
    }

6.完整代码地址:数据结构与算法学习JAVA描述GayHub地址

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容