| 操作 | 陣列 | 鏈表 |
|---|---|---|
| 尾端插入/刪除 | O(1) | O(1) |
| 中間插入/刪除 | O(N) 需搬移 | O(1) 僅改指標 |
| 隨機存取 | O(1) | O(N) 需遍歷 |
結論:頻繁增刪、少量查詢 → 鏈表;頻繁查詢、少量增刪 → 陣列/向量。
template <typename Type>
class Node {
friend class MyList<Type>;
template <typename T> friend ostream& operator<<(ostream&, const MyList<T>&);
private:
Node(const Type& val) : data(val), next(nullptr) {}
Type data;
Node* next;
};
template <typename Type>
class MyList {
template <typename T> friend ostream& operator<<(ostream&, const MyList<T>&);
public:
MyList(); ~MyList();
void insertFront(const Type&);
void insert(const Type&, int index); // 1-based
void remove(const Type&);
bool isEmpty() const;
void invert(); // 反轉
void concatenate(const MyList<Type>&); // 串接另一串表
private:
Node<Type>* first; // 指向哨兵節點
};
MyList() { first = new Node<Type>(Type()); first->next = nullptr; }
~MyList() {
Node<Type>* cur = first;
while (cur) { Node<Type>* nxt = cur->next; delete cur; cur = nxt; }
}
void insertFront(const Type& val) {
Node<Type>* n = new Node<Type>(val);
n->next = first->next;
first->next = n;
}
void insert(const Type& val, int idx) {
Node<Type>* prev = first;
int cnt = 1;
while (cnt < idx && prev->next) { prev = prev->next; ++cnt; }
Node<Type>* n = new Node<Type>(val);
n->next = prev->next;
prev->next = n;
}
void remove(const Type& val) {
if (isEmpty()) return;
Node<Type>* prev = first;
for (Node<Type>* cur = first->next; cur; ) {
if (cur->data == val) {
prev->next = cur->next;
delete cur;
cur = prev->next; // 繼續檢查下一個
} else {
prev = cur;
cur = cur->next;
}
}
}
bool isEmpty() const { return first->next == nullptr; }
void invert() {
if (isEmpty()) return;
Node<Type>* cur = first->next;
Node<Type>* prev = nullptr;
while (cur) {
Node<Type>* nxt = cur->next;
cur->next = prev;
prev = cur;
cur = nxt;
}
first->next = prev; // 新頭
}
void concatenate(const MyList<Type>& other) {
if (isEmpty()) { first = other.first; return; } // 注意:這裡為簡化直接指向,實務應深拷貝
if (other.isEmpty()) return;
Node<Type>* tail = first;
while (tail->next) tail = tail->next;
for (Node<Type>* src = other.first->next; src; src = src->next) {
tail->next = new Node<Type>(src->data);
tail = tail->next;
}
}
template <typename Type>
ostream& operator<<(ostream& os, const MyList<Type>& list) {
for (Node<Type>* p = list.first->next; p; p = p->next) {
os << p->data;
if (p->next) os << " -> ";
}
return os;
}
int main() {
MyList<int> a, b;
for (int i=1;i<=5;++i) a.insert(i,i);
a.remove(5);
for (int i=6;i<=10;++i) b.insert(i,i-5);
b.insertFront(5); b.insert(88,7);
cout << "Before concat:\na: " << a << "\nb: " << b << "\n";
a.concatenate(b);
cout << "After concat:\na: " << a << "\nb: " << b << "\n";
MyList<char> c;
for (char ch='9'; ch>='0'; --ch) c.insertFront(ch);
cout << "\nBefore invert: " << c;
c.invert();
cout << "\nAfter invert: " << c;
c.remove('5');
cout << "\nAfter remove 5:" << c << "\n";
return 0;
}
Before concat: a: 1 -> 2 -> 3 -> 4 b: 5 -> 6 -> 88 -> 7 -> 8 -> 9 -> 10 After concat: a: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 88 -> 7 -> 8 -> 9 -> 10 b: 5 -> 6 -> 88 -> 7 -> 8 -> 9 -> 10 Before invert: 9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0 After invert: 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 After remove 5: 0 -> 1 -> 2 -> 3 -> 4 -> 6 -> 7 -> 8 -> 9
prev 不動、cur 前進,避免漏檢相鄰重複值。next、再改指標、再移動指標」。delete 兩次 → Crash。