链表分为带头节点和不带头节点,单链表和双向循环链表。
带头节点的链表虽然有头结点,但是并不存储数据,双向循环链有指向前一个数的指针和指向后一个数的指针。
如下图:
先来实现一些主要的函数:
List的构造函数和析构函数:
List()
{
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
}
~List()
{
clear();
delete _head;
_head = NULL;
}
List在任意一个位置插入一个数和删除一个数
//任意一个位置插入一个数,在pos的前面插入一个数据
void Insert(Node* pos, const T& x)
{
assert(pos);
Node* tmp = new Node(x);
Node* cur = pos;
Node* prev = cur->_prev;
prev->_next = tmp;
tmp->_prev = prev;
tmp->_next = cur;
cur->_prev = tmp;
}
//删除任意一个位置的数
void Erase(Node* pos)
{
assert(pos && pos != _head);
Node* prev = pos->_prev;
Node* next = pos->_next;
prev->_next = next;
next->_prev = prev;
delete pos;
}
有了插入和删除函数之后,其他的函数都可以用Erase和Insert来复用:
尾部插入和删除函数:
//尾部插入一个数
void PushBack(const T& x)
{
Insert(_head, x);
}
//尾部删除一个数
void PopBack(const T& x)
{
Erase(_head->_prev);
}
头部插入和删除数据:
//头部插入一个数
void PushFront(const T& x)
{
Insert(_head->_next,x);
}
//头部删除一个数
void PopFront(const T& x)
{
Erase(_head->_next);
}
构造函数和赋值运算符重载:
//拷贝构造函数
List(const List<T> & l)
{
_head = new Node();
_head->_next = _head;
_head->_prev = _head;
Node* cur = (l._head)->_next;
while (cur != l._head)
{
this->PushBack(cur->_data);
cur = cur->_next;
}
}
//赋值运算符重载
List<T>& operator=(const List<T>& l)
{
if (this != &l)
{
this->clear();
Node* cur = l._head->_next;
while (cur != l._head)
{
this->PushBack(cur->_data);
cur = cur->_next;
}
}
return *this;
}
在插入和删除数据的时候要考虑双向链表里面会出现的各种情况!
以下是完整的代码:
ListNode.h
#pragma once
#include<assert.h>
template<class T>
struct ListNode
{
T _data;
ListNode<T>* _next;
ListNode<T>* _prev;
ListNode(const T& x = T())
:_data(x)
, _next(NULL)
, _prev(NULL)
{}
};
template<class T>
class List
{
typedef ListNode<T> Node;
public:
List()
{
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
}
~List()
{
clear();
delete _head;
_head = NULL;
}
//删除任意一个位置的数
void Erase(Node* pos)
{
assert(pos && pos != _head);
Node* prev = pos->_prev;
Node* next = pos->_next;
prev->_next = next;
next->_prev = prev;
delete pos;
}
//任意一个位置插入一个数,在pos的前面插入一个数据
void Insert(Node* pos, const T& x)
{
assert(pos);
Node* tmp = new Node(x);
Node* cur = pos;
Node* prev = cur->_prev;
prev->_next = tmp;
tmp->_prev = prev;
tmp->_next = cur;
cur->_prev = tmp;
}
//尾部插入一个数
void PushBack(const T& x)
{
Insert(_head, x);
}
//尾部删除一个数
void PopBack(const T& x)
{
Erase(_head->_prev);
}
//头部插入一个数
void PushFront(const T& x)
{
Insert(_head->_next,x);
}
//头部删除一个数
void PopFront(const T& x)
{
Erase(_head->_next);
}
//查找一个数
void Find(const T& x)
{
Node* cur = _head->_next;
while (cur != _head)
{
if (cur->_data == x)
{
return cur;
}
return NULL;
}
}
//清除
void clear()
{
Node* cur = _head->_next;
while (cur != _head)
{
Node* next = cur->_next;
delete cur;
cur = next;
}
_head->_next = _head;
_head->_prev = _head;
}
//打印
void Print()
{
Node* cur = _head->_next;
while (cur!=_head)
{
cout << cur->_data << "";
cur = cur->_next;
}
cout << endl;
}
//拷贝构造函数
List(const List<T> & l)
{
_head = new Node();
_head->_next = _head;
_head->_prev = _head;
Node* cur = (l._head)->_next;
while (cur != l._head)
{
this->PushBack(cur->_data);
cur = cur->_next;
}
}
//赋值运算符重载
List<T>& operator=(const List<T>& l)
{
if (this != &l)
{
this->clear();
Node* cur = l._head->_next;
while (cur != l._head)
{
this->PushBack(cur->_data);
cur = cur->_next;
}
}
return *this;
}
protected:
Node* _head;
};
void Test1()//尾部插入和删除
{
//插入
List<int> l;
l.PushBack(1);
l.Print();
l.PushBack(2);
l.Print();
l.PushBack(3);
l.Print();
l.PushBack(4);
l.Print();
//删除
l.PopBack(1);
l.Print();
l.PopBack(1);
l.Print();
l.PopBack(1);
l.Print();
}
void Test2()//头部插入和删除
{
//插入
List<int> l;
l.PushFront(1);
l.Print();
l.PushFront(2);
l.Print();
l.PushFront(3);
l.Print();
//删除
l.PopFront(1);
l.Print();
l.PopFront(1);
l.Print();
l.PopFront(1);
l.Print();
}
测试函数
Test.cpp
#include<iostream>
using namespace std;
#include"ListNode.h"
int main()
{
Test1();
Test2();
system("pause");
return 0;
}