基于C++封装性的双向链表

来源:互联网 发布:1024为熟知端口 编辑:程序博客网 时间:2024/06/03 17:21

基于C++封装性的双向链表

双向链表即有指向前一个节点的指针和指向后一个节点的指针,就像这样:

struct Node
{
Node
(const DataType& data)
: _pNext(NULL)
, _pPre(NULL)
, _data(data)
{}

Node* _pNext;
Node* _pPre;
DataType _data;
};

在C++中struct的默认属性为public,每当调用节点Node时会执行一次构造函数将一前一后指针初始化为空,数据初始化为给定的值。

以下是基于C++封装性的双向链表的类以及功能函数的声明:

class List
{
public:
List()// 创建一个空链表时构造函数会调用这个
: _pHead(NULL),_size(1)
{}
List(size_t n, DataType data)// 创建一个非空链表
:_size(n)
{
_pHead = BuyNode(data);
Node* tail = _pHead;
for (size_t idx = 0; idx < _size-1; idx++)
{
Node* newNode = BuyNode(data);
tail->_pNext = newNode;
newNode->_pPre = tail;
tail = tail->_pNext;
}
}
~List()// 析构函数
{
Clear();
}
List(const List& l)
{
if (l._pHead == NULL)
{
_pHead = NULL;
}
else
{
Node* temp = l._pHead;
Node* newHead = BuyNode(temp->_data);
_pHead = newHead;
temp = temp->_pNext;

while (NULL != temp)
{
Node* newNode = BuyNode(temp->_data);
newHead->_pNext = newNode;
newNode->_pPre = newHead;
temp = temp->_pNext;
newHead = newNode;
}
}
}
List& operator=(const List& l)// 赋值运算符的重载
{
if (this != &l)// 判断不是自己给自己赋值
{
if (l._pHead == NULL)// 两种情况
{
_pHead = NULL;
}
else
{
Clear();
Node* temp = l._pHead;
Node* newHead = BuyNode(temp->_data);
_pHead = newHead;
temp = temp->_pNext;

while (NULL != temp)
{
Node* newNode = BuyNode(temp->_data);
newHead->_pNext = newNode;
newNode->_pPre = newHead;
temp = temp->_pNext;
newHead = newNode;
}
}
}
_size = l._size;
return *this;
}
void Display();
void PushBack(const DataType& data);
void PopBack();
void PushFront(const DataType& data);
void PopFront();
Node* Find(const DataType& data);
void Insert(Node* pos, const DataType& data);
void Erase(Node* pos);
//size_t Size();
//bool Empty()const;
private:
Node* BuyNode(const DataType& data)
{
return new Node(data);
}
void Clear()
{
while (_pHead)
{
Node* temp = _pHead->_pNext;
delete[] _pHead;
_pHead = temp;
}
_size=0;
}
private:
Node* _pHead;
size_t _size;
};

下面是一些对链表操作的功能函数:

void List::Display()// 从头到尾打印链表
{
Node*temp = _pHead;
while (NULL != temp)
{
cout << temp->_data << "->";
temp = temp->_pNext;
}
cout << "NULL" << endl;
}
void List::PushBack(const DataType& data)
{
Node* temp = _pHead;
Node* NewNode = BuyNode(data);
if (NULL == _pHead)// 两种情况:1,空链表 2,非空链表
{
_pHead = NewNode;
}
else
{
while (NULL != temp->_pNext)
{
temp = temp->_pNext;
}
temp->_pNext = NewNode;
NewNode->_pPre = temp;
}
_size += 1;// 记录链表中一共有多少节点
}

void List::PopBack()
{
if (_pHead == NULL)
return;
else// 删非空链表的尾
{
Node* temp = _pHead;
while (NULL != temp->_pNext)
{
temp = temp->_pNext;
}
temp->_pPre->_pNext = NULL;
temp->_pPre = NULL;
delete[] temp;
temp = NULL;
}
_size -= 1;
}

void List::PushFront(const DataType& data)
{
Node* temp = _pHead;
if (_pHead == NULL)
{
_pHead = BuyNode(data);
}
else
{
Node* newHead = BuyNode(data);
newHead->_pNext = temp;
temp->_pPre = newHead;
_pHead = newHead;
}
_size += 1;
}
void List::PopFront()
{
if (_pHead == NULL)// 三种情况 1,空链表 2,一个节点 3,一般情况
return;
else if (_pHead->_pNext == NULL)
{
delete _pHead;
_pHead = NULL;
}
else
{
Node* temp = _pHead;
_pHead = _pHead->_pNext;
delete[] temp;
temp = NULL;
}
_size -= 1;
}

Node* List::Find(const DataType& data)
{
Node* temp = _pHead;
while (temp)
{
if (temp->_data == data)
return temp;
temp = temp->_pNext;
}
return NULL;
}

插入一个节点时是在原链表这个位置的前方插入的,因为在前方插入的节点刚好就是新链表pos的这个位置 。一定要注意增加一个节点或者删除一个节点时前后指针都得连接好,否则会出错。

void List::Insert(Node* pos, const DataType& data)
{
assert(pos); if (_pHead == pos)
PushFront(data);
else
{
Node* temp = _pHead;
Node* newNode = BuyNode(data);
while (temp->_pNext == _pHead)
{
temp = temp->_pNext;
}
newNode->_pNext = temp->_pNext;
temp->_pNext->_pPre = newNode;
temp->_pNext = newNode;
newNode->_pPre = temp;
_size += 1;
}
}

void List::Erase(Node* pos)
{
assert(pos);
if (pos == _pHead)
{
PopFront();
}
else if (pos->_pNext == NULL)
{
PopBack();
}
else
{
pos->_pPre->_pNext = pos->_pNext;
pos->_pNext->_pPre = pos->_pPre;
delete[] pos;
pos = NULL;
}
}