最近复习到链表(LinkedList),一般来说共有大概有两种实现方式:1. 数组实现 和 2. 链式实现。
其中,链式实现又可分为两种:1. 依托数组的链式实现---静态链表(请参考[2]) 2. 直接链式实现
我仅使用了直接链式实现,代码如下。其他的实现方式,大家不妨自己尝试下吧。
(注:代码头文件中的函数原型参考自[1],然函数的实现是我本人写的,没有参考书,如有雷同,纯属巧合)
/**************************************
*
* copyright: ace_yom (Peizhen Zhang)
* author: ace_yom (Peizhen Zhang)
* date: 2015-8-17
* description: 链表实现
*
**************************************/
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <stdexcept>
#include <iostream>
using namespace std;
template <typename T>
struct Node
{
T element;
Node<T> *next;
Node() {
next = nullptr;
}
Node(T element) {
this->element = element;
next = nullptr;
}
};
template <typename T>
class LinkedList
{
private:
Node<T>*head, *tail;
int size;
private:
void addLast(T element) {
Node<T>* tmp = new Node<T> (element);
if(tail == nullptr)
head = tail = tmp;
else
{
tail->next = tmp;
tail = tail->next;
}
size ++;
}
void addFirst(T element) {
if(size == 0)
{
addLast(element);
return;
}
Node<T>* tmp = new Node<T>(element);
tmp->next = head;
head = tmp;
size ++;
}
Node<T>* preNodeOfIndex(int index) {
if(index == 1)
return nullptr;
Node<T>* p = head;
for(int i = 0 ;i < index-2 ; i ++)
p = p->next;
return p;
}
public:
LinkedList();
bool checkIndex(int index,int first,int last); //检查越界
T getFirst(); //获取第一个节点的值
T getLast(); //获取最后一个节点的值
T removeFirst(); //删除第一个节点, 并返回值
T removeLast(); //删除最后一个节点, 并返回值
void remove(T element); //删除所有值为element的节点
T removeAt(int index); //删除在index处的节点, 并返回值
void add(T element); //增加节点
void add(int index , T element); //在index处增加节点
void clear(); //清空链表
bool contains(T element); //查询是否包含值为element的节点
int indexOf(T element); //返回第一个其值为element的节点的索引
bool isEmpty(); //表是否空
int lastIndexOf(T element); //最后一个值为element的节点的索引
int getSize(); //获取表长
T get(int index); //获取在index处的节点的值
void set(int index, T element); //重新设置在index处的节点的值
void print(); //打印链表
};
template <typename T>
LinkedList<T>::LinkedList() {
head = tail = nullptr;
size = 0;
}
template <typename T>
bool LinkedList<T>::checkIndex(int index, int first, int last) {
if (index >= first && index <= last)
return true;
else
return false;
}
template <typename T>
T LinkedList<T>::getFirst() {
if(head == nullptr)
throw runtime_error("Index out of range");
return head->element;
}
template <typename T>
T LinkedList<T>::getLast() {
if(tail == nullptr)
throw runtime_error("Index out of range");
return tail->element;
}
template <typename T>
T LinkedList<T>::removeFirst() {
if(head == nullptr)
throw runtime_error("Index out of range");
Node<T> *tmp = head;
head = head->next;
T temp = tmp->element;
delete tmp;
size --;
if(size == 0)
tail = nullptr;
return temp;
}
template <typename T>
T LinkedList<T>::removeLast() {
if(tail == nullptr)
throw runtime_error("Index out of range");
if(size == 1)
return removeFirst();
Node<T>* p = preNodeOfIndex(size);
Node<T> *tmp = p->next;
T temp = tmp->element;
delete tmp;
size --;
tail = p;
tail->next = nullptr;
return temp;
}
template <typename T>
void LinkedList<T>::add(T element) {
addLast(element);
}
template <typename T>
void LinkedList<T>::add(int index, T element) {
if(!checkIndex(index,1,size+1))
return;
Node<T>* pre = preNodeOfIndex(index);
if(pre == nullptr)
{
addFirst(element);
return;
}
else
{
Node<T> *lat = pre->next;
Node<T> *tmp = new Node<T>(element);
pre->next = tmp;
tmp->next = lat;
size += 1;
}
}
template <typename T>
void LinkedList<T>::clear() {
while(head != nullptr)
{
Node<T>* tmp = head->next;
delete head;
head = tmp;
}
tail = head;
size = 0;
}
template <typename T>
bool LinkedList<T>::contains(T element) {
if(size == 0)
return false;
Node<T> *p = head;
while(p != nullptr)
{
if(p->element == element)
return true;
p = p->next;
}
return false;
}
template <typename T>
T LinkedList<T>::get(int index) {
if(!checkIndex(index,1,size))
{
throw runtime_error("Index out of range");
}
Node<T>* p = head;
for(int i = 0 ; i < index-1 ; i ++)
p = p->next;
return p->element;
}
template <typename T>
int LinkedList<T>::indexOf(T element) {
//output -1 if not found
Node<T>* p = head;
int inde = 1;
while( p != nullptr)
{
if(p->element == element)
return inde;
inde ++;
p = p->next;
}
return -1;
}
template <typename T>
bool LinkedList<T>::isEmpty() {
return size==0;
}
template <typename T>
int LinkedList<T>::lastIndexOf(T element) {
//output -1 if not found
int inde = -1, cnt = 1;
Node<T> *p = head;
while(p != nullptr)
{
if(p->element == element)
inde = cnt;
cnt ++;
p = p->next;
}
return inde;
}
//Implemented mainly via two pointers
template <typename T>
void LinkedList<T>::remove(T element) {
while(head != nullptr && head->element == element)
removeFirst();
if(size == 0)
return;
/*
使用front, rear两个指针
front初始化指向原链表中的第一个"非element"节点
初始化tail=front, tail在算法运行中会逐渐后退直到最后一个非element节点
*/
Node<T>* front = head;
head = tail = front;
Node<T> *rear = front->next;
while(rear != nullptr)
{
//rear->element = element, 删除rear指向的节点
if (rear->element == element)
{
Node<T> *tmp = rear;
rear = rear->next;
front->next = rear;
delete tmp;
size --;
}
//rear->element != element, tail后移; front,rear后移
else
{
tail = rear;
front = front->next;
rear = rear->next;
}
}
}
template <typename T>
int LinkedList<T>::getSize() {
return size;
}
template <typename T>
T LinkedList<T>::removeAt(int index) {
if(!checkIndex(index,1,size))
{
throw runtime_error("Index out of range");
}
if(index == 1)
return removeFirst();
else if(index == size)
return removeLast();
else
{
Node<T>* p = preNodeOfIndex(index);
Node<T>* tmp = p->next;
p->next = (p->next)->next;
T temp = tmp->element;
delete tmp;
size --;
return temp;
}
}
template <typename T>
void LinkedList<T>::set(int index , T element) {
if(!checkIndex(index,1,size))
return;
Node<T>* p = head;
for(int i = 0 ; i < index-1 ; i ++)
p = p->next;
p->element = element;
}
template <typename T>
void LinkedList<T>::print() {
if(size == 0)
{
cout << "Empty LinkedList.\n";
return;
}
cout << head->element;
Node<T>* p = head->next;
while(p)
{
cout << " " << p->element;
p = p->next;
}
cout << endl;
}
#endif
[1] Introduction to Programming with C++ (Comprehensive Version) Y.Daniel Liang
[2] 数据结构(C 语言版) 严蔚敏 吴伟民 编著