链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。
#include<iostream>
using namespace std;
template <class T>
class Chain;
template <class T>
class ChainNode
{
friend class Chain<T>;
private:
T data;
ChainNode<T> *next;
};
template <class T>
class Chain
{
public:
Chain()
{
first = 0;
last = 0;
}
~Chain();
void Add(T& x);
bool IsEmpty()const{return first==0;}
int Length()const;
bool Find(int k, T& x)const;
int Search(const T& x)const;
void DeleteOfk(int k);//删除第k个元素
void DeleteOfx(T& x);//删除链表中值为x的几点,如果存在
void Insert(int k,const T& x);
void OutPut()const;
private:
ChainNode<T> *first;
ChainNode<T> *last;
};
template <class T>
Chain<T>::~Chain()
{//析构函数,删除表中的所有节点
ChainNode<T> *next;
while(first)
{
next = first->next;
delete(first);
first = next;
}
}
template <class T>
void Chain<T>::Add(T& x)
{
ChainNode<T> *node = new ChainNode<T>;
node->data = x;
node->next = NULL;
if(first)
{//每次在链表的尾部插入一个节点
last->next = node;
last = node;
}
else
{//如果是空表 这新加入的节点既是头结点也是尾节点
first = node;
last = node;
}
}
template <class T>
int Chain<T>::Length()const
{//返回链表的长度
ChainNode<T> *current = first;
int len = 0;
while(current)
{
len++;
current = current->next;
}
return len;
}
template<class T>
bool Chain<T>::Find(int k, T& x)const
{//查找第k个元素,如果纯在将其保存在x中。
//如纯在返回true,不存在返回false
if (k<1)
return false;
ChainNode<T> *current = first;
int index = 1;
while(index<k&¤t)
{
current = current->next;
index++;
}
if (current)
{
x = current->data;
return true;
}
else
{
return false;
}
}
template<class T>
int Chain<T>::Search(const T& x)const
{//寻找x,如果发现x,返回x的地址
//如果x不存在链表中则返回0
ChainNode<T> *current = first;
int index = 1;
while(current&¤t->data!=x)
{
index++;
current = current->next;
}
if(current)
return index;
return 0;
}
template <class T>
void Chain<T>::DeleteOfk(int k)//删除第k个元素
{
T x;
if(Find(k,x))
{
int index = 1;
ChainNode<T> *current = first;
ChainNode<T> *temp=0;
if(k==1)
{//删除头结点
first = first->next;
delete (current);
}
else
{
while(k!=index)
{
index++;
temp = current;//temp始终指向current的上一个节点
current = current->next;
}
if(current)
{
temp->next = current->next;
if(!current->next)
{//如果删除的是最后一个节点,则最后的一个节点应该变成temp。
last = temp;
}
delete (current);
}
}
}
}
template <class T>
void Chain<T>::DeleteOfx(T& x)//删除链表中值为x的几点,如果存在
{
int k;
k = Search(x);
if(k!=0)
{
DeleteOfk(k);
}
else
{
cout<<"删除的数据在链表中不存在"<<endl;
}
}
template <class T>
void Chain<T>::Insert(int k,const T& x)
{
ChainNode<T> *temp = new ChainNode<T>;
temp->data = x;
temp->next = NULL;
if(k==0)
{ //插入在头结点的位置
temp->next = first;
first = temp;
}
else if(k>0&&k<=Length())
{
ChainNode<T> *current = first;
int index = 1;
while(index!=k)
{
index++;
current = current->next;
}
if(current)
{
temp->next = current->next;
current->next = temp;
}
else
{//插入在尾节点的位置
last = temp;
current->next = temp;
}
}
else
{
cout<<"插入数据不正确"<<endl;
}
}
template <class T>
void Chain<T>::OutPut()const
{
ChainNode<T> *current = first;
while(current)
{
cout<<current->data<<" ";
current = current->next;
}
cout<<endl;
}
int main()
{
Chain<int> list;
int x;
for(int i=0; i<5; i++)
{
cin>>x;
list.Add(x);
}
list.OutPut();
cout<<"length: "<<list.Length()<<endl;
x = 0;
if(list.Find(5,x))
{
cout<<"OK!! "<<x<<endl;
}
int y = list.Search(x);
cout << "y="<<y<<endl;
list.DeleteOfk(1);
list.OutPut();
list.DeleteOfx(x);
list.OutPut();
list.Insert(0,x);
list.OutPut();
}