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

前言

数组与链表是最常用的数据结构中的两种,也是最简单的数据结构类型,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 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 
List::~List() {
}

template 
int List::size() {
    return len;
}

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

3:ArrayList实现

#ifndef CTEST_ARRAYLIST_HPP
#define CTEST_ARRAYLIST_HPP

#include 
#include 
#include "List.hpp"

template 
class ArrayList : public List {

private:
    /**
     * 初始化数组大小
     */
    int data_size = 0;
    E *datas = NULL;

    void ensureCapacityInternal(int minCapacity);
    //扩充
    void grow(int minCapacity);

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 
ArrayList::ArrayList() {
}

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

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

/**
 * 这里忽略扩充数组后大小超过int最大值
 * @tparam E
 * @param index
 * @param e
 */
template 
void ArrayList::ensureCapacityInternal(int minCapacity) {
    if (this->datas == NULL) {
        minCapacity = 10; //默认10个大小
    }
    if (minCapacity > this->data_size) {
        grow(minCapacity);
    }
}

template 
void ArrayList::grow(int minCapacity) {
    int new_len = data_size + (data_size >> 1);
    if (new_len < minCapacity) {
        new_len = minCapacity;
    }
    E *new_datas = (E*) malloc(sizeof(E) * new_len);
    if (this->datas != NULL) {
        if (List::len > 0) {
            // 拷贝数据
            memcpy(new_datas, this->datas, sizeof(E) * List::len);
        }
        // 释放原来的内存
        free(this->datas);
    }
    this->datas = new_datas;
    this->data_size = new_len;
}

template 
void ArrayList::clear() {
    List::len = 0;
}

template 
bool ArrayList::add(const E &e) {
    ensureCapacityInternal(List::len + 1);
    this->datas[List::len++] = e;
    return true;
}

template 
bool ArrayList::add(int index, const E &e) {
    assert(index >= 0 && index <= List::len);
    ensureCapacityInternal(List::len + 1);
    memmove(this->datas + index + 1, this->datas + index, sizeof(E) * (List::len - index));
    this->datas[index] = e;
    List::len++;
    return true;
}

template 
E ArrayList::remove(int index) {
    assert(index >= 0 && index < List::len);
    E data = datas[index];
    int num_moved = List::len - index - 1;
    if (num_moved > 0) {
        memmove(this->datas + index, this->datas + index + 1, sizeof(E) * num_moved);
    }
    List::len--;
    return data;
}

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

#endif //CTEST_ARRAYLIST_HPP

4:LinkedList实现


#include 
#include "List.hpp"

template 
class LinkedList : public List {

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 
typename LinkedList::Node* LinkedList::node(int index) {
    if (index < List::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::len - 1; i > index; i--) {
            curr = curr->prev;
        }
        return curr;
    }
}

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

template 
void LinkedList::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::len = 0;
    }
}

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

template 
bool LinkedList::add(int index, const E &e) {
    assert(index >= 0 && index <= List::len);
    if (index == 0)
    {
        addFirst(e);
        return true;
    }
    if (index == List::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::len++;
    return true;
}

template 
E LinkedList::remove(int index) {
    assert(index >= 0 && index < List::len);
    if (index == 0)
    {
        return removeFirst();
    }
    if (index == List::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::len--;
    return e;
}

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

template 
void LinkedList::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::len++;
}

template 
void LinkedList::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::len++;
}

template 
E LinkedList::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::len--;
    return e;
}

template 
E LinkedList::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::len--;
    return e;
}

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

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

5:最后测试

  JNIEXPORT void JNICALL
  Java_you_chen_ctest_MainActivity_test0(JNIEnv *env, jobject /* this */) {
        List *list = new ArrayList();
        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 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,LinkedList)