C++シミュレーションJDKにおけるArrayListとLinkedListの実現
42798 ワード
JavaがArrayListとLinkedListを実現する方式は配列とチェーンテーブルを採用している.以下はC++コードによるシミュレーションです.
Collectionインタフェースの宣言:
Listインタフェースの宣言
インタフェース宣言が完了すると、具体的な実装が行われます.Javaにおける汎用機構をC++のテンプレートでシミュレートし,Iteratorクラスをネストすることでそれぞれの反復器を実現した.JavaでIteratorが最もよく使う方法はhasNext()とnext()です.そこで本稿では,この2つの方法の実装についてのみ行った.
ArrayList.h
明らかに,JavaにおけるArrayListと同様である.挿入を行う代価は高い.
LinkedList.h
LinkedListのすべてのクエリーは反復に依存して完了する必要があります.コストが高いです.しかし、挿入の代価は低い.この点はJDKでの表現と一致している.
まとめ:
(1)C++のメモリモデルはJavaより複雑であるため選択の余地も多い.本ルーチンは完全にポインタを用いて実現されており、基本的にJavaと同等の実現方式を採用している.もちろんビットコピー方式や&リファレンスを用いてもよい.興味のある方は自分で模索することができる.
(2)C++でのゴミ収集は手動で行う必要があり、Javaによる利便性はない.自己呼び出しも可能な構造関数も提供されているが、インスタンスを観察することですべての作業を構造関数に任せることができるわけではないことは明らかである.より典型的な方法は、関数内部で随時整理することである.
使用方法:単純なテストルーチン
Collectionインタフェースの宣言:
#ifndef COLLECTION_H_
#define COLLECTION_H_
template<class T>
class Collection {
public:
virtual ~Collection() {
}
virtual bool add(T* e) = 0;
virtual int contains(T* e) = 0;
virtual bool isEmpty() = 0;
virtual bool remove(T* e) = 0;
virtual int size() = 0;
};
#endif /* COLLECTION_H_ */
Listインタフェースの宣言
#ifndef LIST_H_
#define LIST_H_
#include "Collection.h"
template<class T>
class List: public Collection {
public:
virtual ~List() {
}
virtual void add(int index, T* e) = 0;
virtual T* get(int index) = 0;
virtual T* remove(int index) = 0;
};
#endif /* LIST_H_ */
インタフェース宣言が完了すると、具体的な実装が行われます.Javaにおける汎用機構をC++のテンプレートでシミュレートし,Iteratorクラスをネストすることでそれぞれの反復器を実現した.JavaでIteratorが最もよく使う方法はhasNext()とnext()です.そこで本稿では,この2つの方法の実装についてのみ行った.
ArrayList.h
#ifndef ARRAYLIST_H_
#define ARRAYLIST_H_
#include "List.h"
template<class T, int bsz = 10> // bsz
class ArrayList: public List { // List Collection
int len; //
int max; //
T** items;
void inflate(); //
ArrayList(const ArrayList&); // ,
public:
ArrayList() :
len(0), max(bsz), items(new T*[bsz]) {
}
virtual ~ArrayList();
bool add(T* e); //
int contains(T* e); //
bool isEmpty(); //
bool remove(T* e); //
int size(); //
void add(int index, T* e); //
T* get(int index); //
T* remove(int index); //
class Iterator;
friend class Iterator;
class Iterator { //
ArrayList& al;
int index;
public:
Iterator(ArrayList& list) :
al(list), index(0) {
}
bool hasNext() {
if (index < al.len) {
return true;
}
return false;
}
T* next() {
if (hasNext()) {
return al.items[index++];
}
return 0;
}
};
};
/**
* , 。 inline。
*/
template<class T, int bsz>
ArrayList::~ArrayList() {
for (int i = 0; i < len; i++) {
delete items[i];
items[i] = 0; //
}
delete items; //
}
template<class T, int bsz>
void ArrayList::inflate() {
if (len == max) {
max += bsz; //
T** newItems = new T*[max];
for (int i = 0; i < len; i++)
newItems[i] = items[i];
delete[] items; // : ! 。
items = newItems;
}
}
template<class T, int bsz>
bool ArrayList::add(T* e) {
inflate();
items[len++] = e;
return true;
}
template<class T, int bsz>
int ArrayList::contains(T* e) { // : 。
for (int i = 0; i < len; i++) {
if (get(i) == e) {
return i; //
}
}
return -1;
}
template<class T, int bsz>
int ArrayList::size() { //
return len;
}
template<class T, int bsz>
bool ArrayList::remove(T* e) { //
int index = contains(e);
if (index != -1) {
remove(index);
return true;
}
return false;
}
template<class T, int bsz>
bool ArrayList::isEmpty() { //
if (len == 0) {
return true;
} else {
return false;
}
}
template<class T, int bsz>
void ArrayList::add(int index, T* e) { // :
inflate();
T* newItems[++len];
index--; //
for (int i = 0; i < len; i++) {
if (i < index) {
newItems[i] = items[i];
}
if (i == index) {
newItems[i] = e;
}
if (i > index) {
newItems[i] = items[i - 1];
}
}
items = newItems;
}
template<class T, int bsz>
T* ArrayList::get(int index) { //
if (index < 0 || index >= len) {
return 0;
}
return items[index];
}
template<class T, int bsz>
T* ArrayList::remove(int index) { //
if (index < 0 || index >= len) {
return 0;
}
T* result = get(index);
T* newItems[len - 1];
for (int i = 0; i < len; i++) {
if (i < index) {
newItems[i] = items[i];
}
if (i > index) {
newItems[i - 1] = items[i];
}
}
delete items;
items = newItems;
len--;
return result;
}
#endif /* ARRAYLIST_H_ */
明らかに,JavaにおけるArrayListと同様である.挿入を行う代価は高い.
LinkedList.h
#ifndef LINKEDLIST_H_
#define LINKEDLIST_H_
#include "List.h"
#include
using namespace std;
template<class T>
class LinkedList: public List {
struct Item { //
Item(T* d, Item* nxt = 0, Item* pre = 0) : // d: ,nxt: ,pre: 。
data(d), next(nxt), prev(pre) {
}
T* data;
Item* next;
Item* prev;
};
int len; //
Item* head; //
Item* tail; //
LinkedList(const LinkedList&); //
public:
LinkedList() :
len(0), head(0), tail(0) {
}
virtual ~LinkedList() {
if (len != 0) {
while (head->next != 0) {
Item* item = head;
head = item->next;
delete item;
item = 0;
}
}
}
bool add(T* e); //
int contains(T* e); //
bool isEmpty(); //
bool remove(T* e); //
int size(); //
void add(int index, T* e); //
T* get(int index); //
T* remove(int index); //
class Iterator;
friend class Iterator;
class Iterator {
LinkedList& ll;
int index;
public:
Iterator(LinkedList& list) :
ll(list), index(0) {
}
bool hasNext() {
if (index < ll.len) {
return true;
}
return false;
}
T* next() {
if (hasNext()) {
return ll.get(index++);
}
return 0;
}
};
};
/**
*
*/
template<class T>
bool LinkedList::add(T* e) { //
add(len, e);
return true;
}
template<class T>
int LinkedList::contains(T* e) {
Item* temp = head;
for (int i = 0; i < len; i++) {
if (temp->data == e) {
return i;
}
temp = temp->next;
}
return -1;
}
template<class T>
bool LinkedList::isEmpty() {
if (len == 0) {
return true;
} else {
return false;
}
}
template<class T>
bool LinkedList::remove(T* e) {
int index = contains(e);
if (index != -1) {
remove(index);
return true;
}
return false;
}
template<class T>
int LinkedList::size() {
return len;
}
template<class T>
void LinkedList::add(int index, T* e) { //
if (index > 0 || index <= len) {
if (len == 0) { // ,head tail
Item* first = new Item(e);
head = first;
tail = first;
} else if (index == 0) { // , head
Item* temp = new Item(e, head, 0);
head->prev = temp;
head = temp;
} else if (index == len) { // , tail
Item* temp = new Item(e, 0, tail);
tail->next = temp;
tail = temp;
} else { //
Item* itemPrev = head;
for (int i = 1; i < index; i++) {
itemPrev = itemPrev->next;
}
Item* itemNext = itemPrev->next;
Item* newItem = new Item(e, itemNext, itemPrev);
itemPrev->next = newItem;
itemNext->prev = newItem;
}
len++;
}
}
template<class T>
T* LinkedList::get(int index) { //
if (index >= 0 || index < len) {
Item* result = head;
for (int i = 0; i < index; i++) {
result = result->next;
}
return result->data;
}
return 0;
}
template<class T>
T* LinkedList::remove(int index) {
if (index > 0 || index <= len) {
if (index == 0) { // head
Item* temp = head;
head = temp->next;
head->prev = 0;
T* result = temp->data; // 。
delete item;
item = 0;
return result;
} else if (index == len) { // tail
Item* temp = tail;
tail = temp->prev;
tail->next = 0;
T* result = temp->data;
delete item;
item = 0;
return result;
} else {
Item* item = head;
for (int i = 0; i < index; i++) { //
item = item->next;
}
Item* itemPrev = item->prev;
Item* itemNext = item->next;
itemPrev->next = itemNext;
itemNext->prev = itemPrev;
T* result = item->data;
delete item;
item = 0;
return result;
}
len--;
}
return 0;
}
#endif /* LINKEDLIST_H_ */
LinkedListのすべてのクエリーは反復に依存して完了する必要があります.コストが高いです.しかし、挿入の代価は低い.この点はJDKでの表現と一致している.
まとめ:
(1)C++のメモリモデルはJavaより複雑であるため選択の余地も多い.本ルーチンは完全にポインタを用いて実現されており、基本的にJavaと同等の実現方式を採用している.もちろんビットコピー方式や&リファレンスを用いてもよい.興味のある方は自分で模索することができる.
(2)C++でのゴミ収集は手動で行う必要があり、Javaによる利便性はない.自己呼び出しも可能な構造関数も提供されているが、インスタンスを観察することですべての作業を構造関数に任せることができるわけではないことは明らかである.より典型的な方法は、関数内部で随時整理することである.
使用方法:単純なテストルーチン
#include "ArrayList.h"
#include "LinkedList.h"
#include
#include
using namespace std;
int main() {
// ArrayList
ArrayList<int> ia;
for (int i = 0; i < 15; i++) {
int* v = new int(i);
ia.add(v);
}
cout << ia.size() << endl;
for (int i = 0; i < ia.size(); i++)
cout << *ia.get(i) << endl;
// ArrayList
ArrayList<string> sa;
fstream in;
in.open("Main.cpp");
string line;
while (getline(in, line)) {
sa.add(new string(line));
}
for (int i = 0; i < sa.size(); i++) {
cout << *sa.get(i) << endl;
}
in.close();
// LinkedList
LinkedList<int> il;
for (int i = 0; i < 33; i++) {
il.add(new int(i));
}
for (int i = 0; i < il.size(); i++) {
cout << *il.get(i) << endl;
}
// LinkedList
LinkedList<string> sl;
in.open("Main.cpp");
while (getline(in, line)) {
sl.add(new string(line));
}
for (int i = 0; i < sl.size(); i++) {
cout << *sl.get(i) << endl;
}
in.close();
// ArrayList
ArrayList<int>::Iterator iat(ia);
while (iat.hasNext()) {
cout << *iat.next() << endl;
}
// ArrayList
ArrayList<string>::Iterator ist(sa);
while (ist.hasNext()) {
cout << *ist.next() << endl;
}
// LinkedList
LinkedList<int>::Iterator ilt(il);
while (ilt.hasNext()) {
cout << *ilt.next() << endl;
}
// LinkedList
LinkedList<string>::Iterator slt(sl);
while (slt.hasNext()) {
cout << *slt.next() << endl;
}
}