链表
功能
公有函数 | 功能 |
---|---|
List(const List<T>&) | 拷贝构造函数 |
List(const T*, std::size_t) | 由数组构造 |
List(const std::vector<T>&) | 由 vector 构造 |
List(const std::list<T>&) | 由 list 构造 |
List(const std::deque<T>&) | 由 deque 构造 |
inline void push_back(const T& item) | 最后插入 |
inline void push_front(const T& item) | 最前插入 |
inline void pop_back() | 删除最后一个 |
inline void pop_front() | 删除第一个 |
inline void insert(const T& item, std::size_t index = node_number) | 在特定位置前插入 |
inline void removeAt(std::size_t index) | 删除特定位置的一个数 |
inline void clear() | 清空 List |
inline void append(const List<T>&) | 在 List 后附加一个 List |
inline bool isEmpty() const | 判断是都为空 |
inline T at(std::size_t index) const | 只读访问特定位置内容 |
inline T& at(std::size_t index) | 可写访问特定位置内容 |
std::size_t size() const | List 大小 |
void print(std::ostream& out = std::cout, std::string str = " ", bool null_info = false) const | 打印List (第一个参数:输出形式;第二个参数:间隔符;第三个参数:List 为空是否提醒) |
void operator=(const List<T>&); | 赋值 |
inline T operator[](std::size_t index) const; | 只读访问特定位置内容 |
inline T& operator[](std::size_t index); | 可写访问特定位置内容 |
输出:默认是print(out, " ");
。
代码
List.h
#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <deque>
#include <Windows.h>
#define _LIST_H_
template<typename T0>
struct Node
{
T0 value = 0; // the value the node holds
Node<T0>* next = nullptr; // the pointer that points to the next node
Node() = default; // the default constuctor
Node(T0 value_, Node<T0>* next_ = nullptr) : value(value_), next(next_) {} // constructor
};
template<typename T>
class List
{
public:
List() = default;
List(const List<T>&);
List(const T*, std::size_t);
List(const std::vector<T>&);
List(const std::list<T>&);
List(const std::deque<T>&);
inline void push_back(const T& item);
inline void push_front(const T& item);
inline void pop_back();
inline void pop_front();
inline void insert(const T& item, std::size_t index = node_number);
inline void removeAt(std::size_t index);
inline void clear();
inline void append(const List<T>&);
inline bool isEmpty() const;
inline T at(std::size_t index) const;
inline T& at(std::size_t index);
std::size_t size() const;
void print(std::ostream& out = std::cout, std::string str = " ", bool null_info = false) const;
void operator=(const List<T>&);
inline T operator[](std::size_t index) const;
inline T& operator[](std::size_t index);
private:
Node<T>* head = nullptr;
Node<T>* tail = head;
std::size_t node_number = 0;
inline Node<T>* find(std::size_t index);
};
template<typename T>
std::ostream& operator<<(std::ostream&, const List<T>& list);
template<typename T>
List<T>::List(const List<T>& new_list)
{
for (Node<T>* p = new_list.head; p; p = p->next)
{
this->push_back(p->value);
}
}
template<typename T>
List<T>::List(const T* new_elements, std::size_t new_size)
{
for (std::size_t i = 0; i != new_size; i++)
{
this->push_back(*(new_elements++));
}
}
template<typename T>
List<T>::List(const std::vector<T>& vec)
{
for (T item : vec)
{
this->push_back(item);
}
}
template<typename T>
List<T>::List(const std::list<T>& new_list)
{
for (auto item : new_list)
{
this->push_back(item);
}
}
template<typename T>
List<T>::List(const std::deque<T>& vec)
{
for (T item : vec)
{
this->push_back(item);
}
}
template<typename T>
void List<T>::push_back(const T& item)
{
Node<T>* new_tail = new Node<T>(item);
if (this->isEmpty())
{
tail = head = new_tail;
node_number++;
}
else
{
tail->next = new_tail;
tail = new_tail;
node_number++;
}
}
template<typename T>
void List<T>::push_front(const T& item)
{
Node<T>* new_head = new Node<T>(item, head);
this->head = new_head;
node_number++;
}
template<typename T>
void List<T>::pop_back()
{
if (!this->isEmpty())
{
if (node_number == 1)
{
node_number = 0;
head = tail = nullptr;
}
else
{
find(node_number - 2)->next = nullptr;
this->tail = find(node_number - 2);
node_number--;
}
}
else
{
MessageBox(NULL, L"Can not pop back an empty list.\nThis action has been omitted", L"ERROR", MB_ICONERROR);
}
}
template<typename T>
void List<T>::pop_front()
{
if (!this->isEmpty())
{
head = head->next;
node_number--;
}
else
{
MessageBox(NULL, L"Can not pop front an empty list.\nThis action has been omitted", L"ERROR", MB_ICONERROR);
}
}
template<typename T>
void List<T>::insert(const T& item, std::size_t index)
{
if (index > node_number)
{
MessageBox(NULL, L"Can not insert out of range.\nThis action has been omitted", L"ERROR", MB_ICONERROR);
}
else
{
if (index)
{
Node<T>* new_node = new Node<T>(item, find(index));
find(index - 1)->next = new_node;
node_number++;
}
else
{
this->push_front(item);
}
}
}
template<typename T>
void List<T>::removeAt(std::size_t index)
{
if (index >= node_number)
{
MessageBox(NULL, L"Can not remove out of range.\nThis action has been omitted", L"ERROR", MB_ICONERROR);
}
else if (index)
{
find(index - 1)->next = find(index + 1);
node_number--;
}
else
{
pop_front();
}
}
template<typename T>
void List<T>::clear()
{
tail = head = nullptr;
node_number = 0;
}
template<typename T>
bool List<T>::isEmpty() const
{
if (node_number) return false;
else return true;
}
template<typename T>
void List<T>::append(const List<T>& new_list)
{
for (Node<T>* p = new_list.head; p; p = p->next)
{
this->push_back(p->value);
}
}
template<typename T>
T List<T>::at(std::size_t index) const
{
Node<T>* ret = find(index);
if (ret)
{
return ret->value;
}
else
{
MessageBox(NULL, L"Subscript out of range.", L"ERROR", MB_ICONERROR);
exit(-1);
}
}
template<typename T>
T& List<T>::at(std::size_t index)
{
Node<T>* ret = find(index);
if (ret)
{
return ret->value;
}
else
{
MessageBox(NULL, L"Subscript out of range.", L"ERROR", MB_ICONERROR);
exit(-1);
}
}
template<typename T>
std::size_t List<T>::size() const
{
return node_number;
}
template<typename T>
Node<T>* List<T>::find(std::size_t index)
{
if (index > node_number)
{
return nullptr; // indecate can not find (i.e. not within range)
}
else
{
Node<T>* target = this->head;
for (int i = 0; i != index; i++)
{
target = target->next;
}
return target;
}
}
template<typename T>
void List<T>::print(std::ostream& out, std::string fill_str, bool null_info) const
{
if (null_info && this->isEmpty())
{
MessageBox(NULL, L"Empty List", L"Information", MB_ICONINFORMATION);
return;
}
Node<T>* p = this->head;
for (; p && p->next; p = p->next)
{
out << p->value << fill_str;
}
if (p) out << p->value;
}
template<typename T>
void List<T>::operator=(const List<T>& new_list)
{
this->clear();
for (Node<T>* p = new_list.head; p; p = p->next)
{
this->push_back(p->value);
}
}
template<typename T>
T List<T>::operator[](std::size_t index) const
{
return this->at(index);
}
template<typename T>
T& List<T>::operator[](std::size_t index)
{
return this->at(index);
}
template<typename T>
std::ostream& operator<<(std::ostream& out, const List<T>& list)
{
list.print(out, " ");
return out;
}
测试
测试代码:
#include "List.h"
using namespace std;
int main(int argc, char** argv)
{
double a[5] = { 0, 2, 3.4,-2, 0.8 };
vector<double> b = { 0.1, -0.5, 0.3 };
List<double> test(a, 4);
List<double> test2(b);
cout << test << endl;
test.push_back(1);
cout << test << endl;
test.push_front(-6.2);
cout << test << endl;
test.removeAt(2);
cout << test << endl;
test.append(test2);
cout << test << endl;
test.pop_back();
cout << test << endl;
test[1] = -100;
cout << test << endl;
test.clear();
cout << test << endl;
for (size_t i = 0; i != 10; i++)
{
test.push_back(i);
}
cout << test << endl;
test.insert(0, 3);
cout << test << endl;
for (size_t j = 0; j != 5; j++)
{
test.pop_front();
}
cout << test << endl;
test = test2;
test.print(cout, " -> ");
cout << endl;
return 0;
}
输出效果:
分析
- 本程序对于错误的操作进行了判断,并会用
MessageBox
弹窗提示。 - 有一些奇怪的事情,如果将
.h
和.cpp
分离,编译器汇报奇怪的错误(MSVC 和 MinGW 都会):
ALL RIGHTS RESERVED © 2021 Teddy van Jerry
欢迎转载,转载请注明出处。