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