项目源代码
本文项目源代码可在此处下载(Visual Studio 2013项目文件):https://github.com/Voyager2718/Blog/tree/master/linked_list
简介
数组 (Array) 是一种很常用的顺序储存数据结构,理论上说,当我们新建一个数组的时候就是在内存中开辟了一段连续的内存空间,并返回一个指向这段内存空间第一个元素地址的指针。因此在初始化以后,因为内存管理的原因,数组不能增加或减少他的长度。所以当我们需要一段长度可变的数据结构的时候,我们就发明了链表。
链表 (Linked list) 是一种非顺序、非连续的数据结构。链表可以通过一个包含数据和指向其他节点指针的结构体(struct)或类(class)来实现。
这篇文章主要讨论的是单向链表的实现。
下面的表格对比了数组和单向链表的优劣势:
单向链表 数组
实现复杂度 复杂 简单
查找复杂度 O(n) O(1)
插入复杂度 O(1) O(n)
单向链表的类定义
template<typename T>
class slist {
private:
struct _node{
T element;
_node *next;
};
_node *_pnode;
int _size;
public:
slist() :_size(0), _pnode(nullptr) {}
~slist(){ empty(); }
void push_front(T);
void push_back(T);
T pop_front(void);
T pop_back(void);
T get(int);
int size(void);
T remove(int);
void empty(void);
bool isEmpty(void);
};
这里我定义了一个模板类,令我的单向链表可以处理各种数据类型。
往表头插入数据
template <typename T>
void slist<T>::push_front(T element){
_node *node = new _node();
node->element = element;
if (_size == 0)
node->next = nullptr;
else
node->next = _pnode;
_pnode = node;
_size++;
}
往表尾插入数据
template <typename T>
void slist<T>::push_back(T element){
_node *node = new _node();
node->element = element;
if (_size == 0)
_pnode = node;
else{
_node *tmp_node = _pnode;
while (tmp_node->next != nullptr)
tmp_node = tmp_node->next;
tmp_node->next = node;
}
_size++;
}
删除第一个元素
template<typename T>
T slist<T>::pop_front(void){
if (_size == 0)
throw new IndexOutOfRangeException();
T t = _pnode->element;
_node *tmp_node = _pnode;
_pnode = _pnode->next;
delete (tmp_node);
_size--;
return t;
}
删除最后一个元素
template<typename T>
T slist<T>::pop_back(void){
if (_size == 0)
throw new IndexOutOfRangeException();
T e;
if (_size == 1){
e = _pnode->element;
delete(_pnode);
_pnode = nullptr;
_size--;
return e;
}
_node *tmp_node = _pnode;
while (tmp_node->next->next != nullptr)
tmp_node = tmp_node->next;
e = tmp_node->next->element;
delete(tmp_node->next);
tmp_node->next = nullptr;
_size--;
return e;
}
获得第n个元素(n∈[0,∞))
template <typename T>
T slist<T>::get(int index){
if (index >= _size)
throw new IndexOutOfRangeException();
_node *tmp_node = _pnode;
for (int i = 0; i < index; i++){
tmp_node = tmp_node->next;
}
return tmp_node->element;
}
获得单向链表长度
template <typename T>
int slist<T>::size(){
return _size;
}
删除第n个元素(n∈[0,∞))
template <typename T>
T slist<T>::remove(int index){
if (index >= _size)
throw new IndexOutOfRangeException();
_node *tmp_node0 = _pnode, *tmp_node1 = nullptr;
for (int i = 0; i < index - 1; i++){
tmp_node0 = tmp_node0->next;
}
tmp_node1 = tmp_node0->next;
tmp_node0->next = tmp_node0->next->next;
T e = tmp_node1->element;
delete(tmp_node1);
_size--;
return e;
}
清空链表
template <typename T>
void slist<T>::empty(){
if (_size == 0)
return;
_node *tmp_node = _pnode;
while (tmp_node->next != nullptr)
{
tmp_node = tmp_node->next;
delete(_pnode);
_pnode = tmp_node;
}
delete(_pnode);
_pnode = nullptr;
_size = 0;
}
确定链表是否为空
template <typename T>
bool slist<T>::isEmpty(){
return _size == 0;
}
Exception 的定义
class Exception{
private:
string message;
public:
Exception(string message){
this->message = string(message);
}
Exception(){}
string getMessage(){
return message;
}
};
class IndexOutOfRangeException :public Exception{};
调用例子
int main(int argc, char *argv[]){
slist<int> *list = new slist <int>();
list->push_front(3);
list->push_front(2);
list->push_front(1);
list->push_back(4);
list->push_back(5);
list->remove(2);
for (int i = 0; i < list->size(); i++)
cout << list->get(i) << endl;
}