美文网首页
C++实现jdk中的List,ArrayList,LinkedL

C++实现jdk中的List,ArrayList,LinkedL

作者: youxiaochen | 来源:发表于2020-06-14 17:10 被阅读0次

前言

数组与链表是最常用的数据结构中的两种,也是最简单的数据结构类型,jdk中最常用的就是ArrayList与LinkedList, 都是List的子类,LinkedList是双向链表同时也具备双向队列的功能,C++的STL库是有自带与JAVA类似的容器,自己动手写就是加深数据结构的印象,同时在使用时也能最佳的选择哪个容器

1:直接上图介绍,看ArrayList与LinkedList中的添加与删除操作

Group 6.png

从上图中可以看出ArrayList与LinkedList的主要区别
ArrayList是连续的数组,查找元素的时候非常快,LinkedList双向链表虽然有二分查找也还是只能顺着链表一个个查询,速度比较慢
ArrayList需要预开辟一定的内存空间,而LinkedList不需要
ArrayList在插入中间元素或删除中间元素(插入末尾部还是很快)时需要挪动数组中的元素,而且在数组长度不够的时候需要重新开辟数组并拷贝内存, 因此效率会比较慢, 而LinkedList相比会快速
LinkedList还实现了Dequeue双向队列功能
因此在操作随机访问较多情况的时候优先选择ArrayList,而在操作增加与删除比较多的时候选择LinkedList

2:直接上代码吧,基类List

template <class E>
class List {
protected:
    int len = 0;
public:
    virtual ~List();
    virtual int size();
    virtual bool isEmpty();
    //清空
    virtual void clear() = 0;
    //添加
    virtual bool add(const E &e) = 0;
    virtual bool add(int index, const E &e) = 0;
    //移除
    virtual E remove(int index) = 0;
    virtual E get(int index) = 0;
};

template <class E>
List<E>::~List() {
}

template <class E>
int List<E>::size() {
    return len;
}

template <class E>
bool List<E>::isEmpty() {
    return len <= 0;
}

3:ArrayList实现

#include <assert.h>
#include <malloc.h>
#include "List.hpp"

template <class E>
class ArrayList : public List<E> {

private:
    /**
     * 初始化数组大小
     */
    int initialCapacity;
    E *datas = NULL;
    //扩充
    void grow(int index, const E &e);

public:

    ArrayList();
    ArrayList(int initialCapacity);
    ~ArrayList();

    void clear();
    bool add(const E &e);
    bool add(int index, const E &e);
    E remove(int index);
    E get(int index);
};

//默认大小10
template <class E>
ArrayList<E>::ArrayList() : ArrayList(10) {
}

template <class E>
ArrayList<E>::ArrayList(int initialCapacity) {
    assert(initialCapacity > 1);
    this->initialCapacity = initialCapacity;
    this->datas = (E*) malloc(sizeof(E) * initialCapacity);
}

template <class E>
ArrayList<E>::~ArrayList() {
    if (this->datas) {
        free(this->datas);
        this->datas = NULL;
    }
}

/**
 * 这里忽略扩充数组后大小超过int最大值
 * @tparam E
 * @param index
 * @param e
 */
template <class E>
void ArrayList<E>::grow(int index, const E &e) {
    initialCapacity += initialCapacity >> 1;//扩充成原先的1.5倍
    E *newDatas = (E*) malloc(sizeof(E) * initialCapacity);
    for (int i = 0; i < index; i++)
    {
        newDatas[i] = this->datas[i];
    }
    newDatas[index] = e;
    for (int i = index + 1; i <= List<E>::len; i++)
    {
        newDatas[i] = datas[i - 1];
    }
    free(this->datas);
    this->datas = newDatas;
    List<E>::len++;
}

template <class E>
void ArrayList<E>::clear() {
    List<E>::len = 0;
}

template <class E>
bool ArrayList<E>::add(const E &e) {
    return add(ArrayList<E>::size(), e);
}

template <class E>
bool ArrayList<E>::add(int index, const E &e) {
    assert(index >= 0 && index <= List<E>::len);
    if (List<E>::len == initialCapacity)
    {//需要扩充
        grow(index, e);
        return true;
    }
    for (int i = List<E>::len - 1; i >= index; i--) {
        datas[i + 1] = datas[i];
    }
    datas[index] = e;
    List<E>::len++;
    return true;
}

template <class E>
E ArrayList<E>::remove(int index) {
    assert(index >= 0 && index < List<E>::len);
    E data = datas[index];
    for (int i = index; i < List<E>::len - 1; i++)
    {
        datas[i] = datas[i + 1];
    }
    List<E>::len--;
    return data;
}

template <class E>
E ArrayList<E>::get(int index) {
    assert(index >= 0 && index < List<E>::len);
    return datas[index];
}

4:LinkedList实现


#include <assert.h>
#include "List.hpp"

template <class E>
class LinkedList : public List<E> {

private:

    struct Node {
        E data;
        Node *prev = NULL;
        Node *next = NULL;
        Node(const E &data, Node *prev, Node *next) : data(data) {
            this->prev = prev;
            this->next = next;
        }
    };

    /**
     * 头结点
     */
    Node *head = NULL;
    /**
     * 尾结点
     */
    Node *last = NULL;
    /**
     * 位置点节
     */
    Node* node(int index);

public:
    /**
     * 实现父类方法
     */
    ~LinkedList();
    void clear();

    bool add(const E &e);
    bool add(int index, const E &e);

    E remove(int index);
    E get(int index);

    /**
     * 新增方法
     */
    void addFirst(const E &e);
    void addLast(const E &e);
    //移除
    E removeFirst();
    E removeLast();
    E getFirst();
    E getLast();
};

/**
 * 注意此处的写法要加上typename
 * @tparam E
 * @param index
 * @return
 */
template <class E>
typename LinkedList<E>::Node* LinkedList<E>::node(int index) {
    if (index < List<E>::len >> 1)
    {//小于一半的长度,从头部开始查找
        Node *curr = this->head;
        for (int i = 0; i < index; i++)
        {
            curr = curr->next;
        }
        return curr;
    }
    else {
        Node *curr = this->last;
        for (int i = List<E>::len - 1; i > index; i--) {
            curr = curr->prev;
        }
        return curr;
    }
}

template <class E>
LinkedList<E>::~LinkedList() {
    this->clear();
}

template <class E>
void LinkedList<E>::clear() {
    if (this->head)
    {
        Node *curr = this->head;
        while (curr) {
            Node *next = curr->next;
            delete curr;
            curr = next;
        }
        this->head = NULL;
        this->last = NULL;
        List<E>::len = 0;
    }
}

template <class E>
bool LinkedList<E>::add(const E &e) {
    addLast(e);
    return true;
}

template <class E>
bool LinkedList<E>::add(int index, const E &e) {
    assert(index >= 0 && index <= List<E>::len);
    if (index == 0)
    {
        addFirst(e);
        return true;
    }
    if (index == List<E>::len)
    {
        addLast(e);
        return true;
    }
    Node *addPreNode = node(index - 1);
    Node *addNextNode = addPreNode->next;
    Node *new_node = new Node(e, addPreNode, addNextNode);
    addPreNode->next = new_node;
    addNextNode->prev = new_node;
    List<E>::len++;
    return true;
}

template <class E>
E LinkedList<E>::remove(int index) {
    assert(index >= 0 && index < List<E>::len);
    if (index == 0)
    {
        return removeFirst();
    }
    if (index == List<E>::len - 1)
    {
        return removeLast();
    }
    Node *removeNode = node(index);
    Node *removePreNode = removeNode->prev;
    Node *removeNextNode = removeNode->next;
    removePreNode->next = removeNextNode;
    removeNextNode->prev = removePreNode;
    E e = removeNode->data;
    delete removeNode;
    List<E>::len--;
    return e;
}

template <class E>
E LinkedList<E>::get(int index) {
    assert(index >= 0 && index < List<E>::len);
    Node *getNode = node(index);
    return getNode->data;
}

template <class E>
void LinkedList<E>::addFirst(const E &e) {
    Node *newNode = new Node(e, NULL, head);
    if (this->head)
    {
        this->head->prev = newNode;
        this->head = newNode;
    }
    else {
        this->last = newNode;
        this->head = newNode;
    }
    List<E>::len++;
}

template <class E>
void LinkedList<E>::addLast(const E &e) {
    Node *newNode = new Node(e, last, NULL);
    if (this->head)
    {
        this->last->next = newNode;
        this->last = newNode;
    }
    else {
        this->last = newNode;
        this->head = newNode;
    }
    List<E>::len++;
}

template <class E>
E LinkedList<E>::removeFirst() {
    assert(this->head);
    Node *removeNode = this->head;
    Node *headNextNode = removeNode->next;
    if (headNextNode)
    {//有多个结点
        headNextNode->prev = NULL;
        this->head = headNextNode;
    }
    else {//只有一个结点
        this->head = NULL;
        this->last = NULL;
    }
    E e = removeNode->data;
    delete removeNode;
    List<E>::len--;
    return e;
}

template <class E>
E LinkedList<E>::removeLast() {
    assert(this->last);
    Node *removeNode = this->last;
    Node *lastPreNode = removeNode->prev;
    if (lastPreNode)
    {//有多个结点
        lastPreNode->next = NULL;
        this->last = lastPreNode;
    }
    else {//只有一个结点
        this->head = NULL;
        this->last = NULL;
    }
    E e = removeNode->data;
    delete removeNode;
    List<E>::len--;
    return e;
}

template <class E>
E LinkedList<E>::getFirst() {
    assert(List<E>::len > 0);
    return this->head->data;
}

template <class E>
E LinkedList<E>::getLast() {
    assert(List<E>::len > 0);
    return this->last->data;
}

5:最后测试

  JNIEXPORT void JNICALL
  Java_you_chen_ctest_MainActivity_test0(JNIEnv *env, jobject /* this */) {
        List<Dog*> *list = new ArrayList<Dog*>();
        Dog *dog1 = new Dog("dog1*", 11);
        Dog *dog2 = new Dog("dog2*", 22);
        Dog *dog3 = new Dog("dog3*", 33);
        list->add(dog1);
        list->add(dog3);
        list->add(1, dog2);
        list->remove(2);
        for (int i = 0; i < list->size(); ++i) {
            Dog *dog = list->get(i);
            LOGD("Dog %s, %d", dog->name, dog->age);
        }
        delete list; delete dog1; delete dog2; delete dog3;

        LOGD("------divider--------- \n\n\n");

        ArrayList<Dog> dogs1;
        dogs1.add(Dog{"dog1",  13 });
        dogs1.add(Dog{"dog2",  25 });
        Dog d1 = {"dog3", 38};
        dogs1.add(d1);
        dogs1.remove(1);

        for (int i = 0; i < dogs1.size(); ++i) {
            Dog dog = dogs1.get(i);
            LOGD("Dog %s, %d", dog.name, dog.age);
        }
        dogs1.clear();
    }
最后附上源码https://github.com/youxiaochen/DataStructArrayLink
数据结构看10次都不如自己动手敲一次印象深,代码中如有错误欢迎指教

更多文章请关注:http://www.jianshu.com/u/b1cff340957c

相关文章

网友评论

      本文标题:C++实现jdk中的List,ArrayList,LinkedL

      本文链接:https://www.haomeiwen.com/subject/ykoxxktx.html