数据结构中的链表的特点是元素都是FIFO(First In First Out),其中链表又分单向链表与双向链表。
单向链表中每个元素都有一个指向下一元素的指针,而双向链表在单向链表的基础上,增加了一个指向前一个元素的指针。
这几天休假,我继续造轮子,重新实现了一下双向链表。
首先是链表节点数据的定义,见如下代码:
template <class T>
class Node
{
public:
Node<T>* next;
Node<T>* prior;
T data;
public:
Node(){};
~Node(){};
Node<T>* GetNext();
Node<T>* GetPrior();
void GetData(T& data);
void ChangeData(T data);
};
template<class T>
void Node<T>::GetData(T& _data)
{
_data = data;
}
template<class T>
Node<T>* Node<T>::GetNext()
{
return next;
}
template<class T>
Node<T>* Node<T>::GetPrior()
{
return prior;
}
template<class T>
void Node<T>::ChangeData(T _data)
{
data = _data;
}
class Node
{
public:
Node<T>* next;
Node<T>* prior;
T data;
public:
Node(){};
~Node(){};
Node<T>* GetNext();
Node<T>* GetPrior();
void GetData(T& data);
void ChangeData(T data);
};
template<class T>
void Node<T>::GetData(T& _data)
{
_data = data;
}
template<class T>
Node<T>* Node<T>::GetNext()
{
return next;
}
template<class T>
Node<T>* Node<T>::GetPrior()
{
return prior;
}
template<class T>
void Node<T>::ChangeData(T _data)
{
data = _data;
}
Node结点类是一个模板类,具体最基本链表访问的方法。
接下来,才是最重要链表类:
链表声明
template <class T>
class DoubleLinkedList:public Node<T>
{
public:
Node<T>* start;
Node<T>* end;
public:
DoubleLinkedList();
~DoubleLinkedList();
void ForwardList();
void BackwardList();
bool Remove(Node<T>* node);
void Add(T data);
Node<T>* Search(T data);
Node<T>* GetStart();
};
class DoubleLinkedList:public Node<T>
{
public:
Node<T>* start;
Node<T>* end;
public:
DoubleLinkedList();
~DoubleLinkedList();
void ForwardList();
void BackwardList();
bool Remove(Node<T>* node);
void Add(T data);
Node<T>* Search(T data);
Node<T>* GetStart();
};
链表声明类中有一个start 和 end结点,便于遍历链表, 我先写上增加链表结点的方法,
添加结点
template<class T>
void DoubleLinkedList<T>::Add(T data)
{
Node<T>* node = new Node<T>();
if(!node)
{
cout << "assign memeory failure!"<<endl;
exit(0);
}
node->data = data;
if(!start) //add first node
{
start = end = node;
start->prior = NULL;
}
else
{
node->prior= end;
end->next = node;
node->next = NULL;
end = node;
}
}
void DoubleLinkedList<T>::Add(T data)
{
Node<T>* node = new Node<T>();
if(!node)
{
cout << "assign memeory failure!"<<endl;
exit(0);
}
node->data = data;
if(!start) //add first node
{
start = end = node;
start->prior = NULL;
}
else
{
node->prior= end;
end->next = node;
node->next = NULL;
end = node;
}
}
起始结点的上一个结果指针为NULL,同理最后一个结点的下一个结点的指针也为NULL。
遍历链表
template<class T>
void DoubleLinkedList<T>::ForwardList()
{
Node<T>* p = start;
if(!p)
{
cout << "the double linked list is empty" << endl;
return;
}
cout << "forward double linked list:";
while(p)
{
cout << p->data << " ";
p = p->GetNext();
}
cout << endl;
}
template<class T>
void DoubleLinkedList<T>::BackwardList()
{
Node<T>* p = end;
if(!p)
{
cout << "the double linked list is empty" << endl;
return;
}
cout << "backward double linked list:";
while(p)
{
cout << p->data << " ";
p = p->prior;
}
cout << endl;
}
void DoubleLinkedList<T>::ForwardList()
{
Node<T>* p = start;
if(!p)
{
cout << "the double linked list is empty" << endl;
return;
}
cout << "forward double linked list:";
while(p)
{
cout << p->data << " ";
p = p->GetNext();
}
cout << endl;
}
template<class T>
void DoubleLinkedList<T>::BackwardList()
{
Node<T>* p = end;
if(!p)
{
cout << "the double linked list is empty" << endl;
return;
}
cout << "backward double linked list:";
while(p)
{
cout << p->data << " ";
p = p->prior;
}
cout << endl;
}
我分别实现了从起始结点向后遍历以及从尾结点向前遍历的二种方法。其中就利用到链表中的start结点指针与end结点指针。
移除结点
template<class T>
bool DoubleLinkedList<T>::Remove(Node<T>* node)
{
if(!node)
{
cout << "the node wanted to deleted is null" << endl;
return 0;
}
if(node->next)
{
if(node->prior) //remove the middle node
{
node->next->prior = node->prior;
node->prior->next = node->next;
}
else //remove first node;
{
node->next->prior = NULL;
start = node->next;
}
}
else
{
if(node->prior) //remove the last node
{
node->prior->next = NULL;
end = node;
}
else //remove the only node
{
start = end = NULL;
}
}
}
bool DoubleLinkedList<T>::Remove(Node<T>* node)
{
if(!node)
{
cout << "the node wanted to deleted is null" << endl;
return 0;
}
if(node->next)
{
if(node->prior) //remove the middle node
{
node->next->prior = node->prior;
node->prior->next = node->next;
}
else //remove first node;
{
node->next->prior = NULL;
start = node->next;
}
}
else
{
if(node->prior) //remove the last node
{
node->prior->next = NULL;
end = node;
}
else //remove the only node
{
start = end = NULL;
}
}
}
移除结点稍微要麻烦点,要考虑要删除的结果是否为起始结点。
到此差不多就完成了链表所功能,包括查询、添加、修改以及移除功能。
最后只剩下测试程序了。
测试程序
#include "stdafx.h"
#include <iostream>
#include <string>
#include "DoubleLinkedList.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
//test double linked list
//Node<int> a;
DoubleLinkedList<int> list;
for(int i=0;i<10;i++)
{
list.Add(i+1);
}
list.ForwardList();
list.BackwardList();
//add new node
list.Add(12);
list.ForwardList();
//find the first node
cout << "search node 3:" <<endl;
Node<int>* midNode = list.Search(3);
if(midNode)
{
//remove middle node
cout << "remove middle node:"<<endl;
list.Remove(midNode);
list.ForwardList();
}
else
{
cout << "can not find"<<endl;
}
Node<int>* firstNode = list.Search(1);
if(midNode)
{
//remove middle node
cout << "remove fist node:"<<endl;
list.Remove(firstNode);
list.ForwardList();
}
else
{
cout << "can not find"<<endl;
}
Node<int>* lastNode = list.Search(12);
if(midNode)
{
//remove middle node
cout << "remove last node:"<<endl;
list.Remove(lastNode);
list.ForwardList();
}
else
{
cout << "can not find"<<endl;
}
cout << "chaged node data from 10 to 11:" <<endl;
Node<int>* changedNode = list.Search(10);
if(changedNode)
{
changedNode->ChangeData(11);
list.ForwardList();
}
int wait;
cin >> wait;
return 0;
}
#include <iostream>
#include <string>
#include "DoubleLinkedList.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
//test double linked list
//Node<int> a;
DoubleLinkedList<int> list;
for(int i=0;i<10;i++)
{
list.Add(i+1);
}
list.ForwardList();
list.BackwardList();
//add new node
list.Add(12);
list.ForwardList();
//find the first node
cout << "search node 3:" <<endl;
Node<int>* midNode = list.Search(3);
if(midNode)
{
//remove middle node
cout << "remove middle node:"<<endl;
list.Remove(midNode);
list.ForwardList();
}
else
{
cout << "can not find"<<endl;
}
Node<int>* firstNode = list.Search(1);
if(midNode)
{
//remove middle node
cout << "remove fist node:"<<endl;
list.Remove(firstNode);
list.ForwardList();
}
else
{
cout << "can not find"<<endl;
}
Node<int>* lastNode = list.Search(12);
if(midNode)
{
//remove middle node
cout << "remove last node:"<<endl;
list.Remove(lastNode);
list.ForwardList();
}
else
{
cout << "can not find"<<endl;
}
cout << "chaged node data from 10 to 11:" <<endl;
Node<int>* changedNode = list.Search(10);
if(changedNode)
{
changedNode->ChangeData(11);
list.ForwardList();
}
int wait;
cin >> wait;
return 0;
}
在我本机上测试通过!
顺便附上下载地址:下载