链表,不能像数组一样,只要知道下标就能访问,而是,一个个的顺着链子访问。
例:单链表的节点类模版(lb1.h)
template<class T>
class Node //节点类
{
Node<T>*next;
public:
T data;
//构造函数,item是数据区,*ptrnext指向Node节点的指针
Node(const T& item,Node<T>*ptrnext=NULL);
void InsertAfter(Node<T>*p);//插入节点
Node<T>*DeleteAfter();//删除节点
Node<T>*NextNode() const;//下一个节点的地址
};
//类的实现部分
template<class T>
//构造函数,初始化数据和指针成员
Node<T>::Node(const T& item,Node<T>*ptrnext):data(item),next(ptrnext)
{}
//返回私有的指针成员
template<class T>
Node<T>*Node<T>::NextNode()const
{return next;}//返回地址,因为*next是私有的。
//在当前节点之后插入一个节点p
template<class T>
void Node<T>::InsertAfter(Node<T>*p)
{
p->next=next;//p节点指针域指向当前节点的后继结点
next=p; //当前节点的指针域指向p
}
//删除当前节点的后继结点,并返回其地址
template<class T>
Node<T>*Node<T>::DeleteAfter(void)
{
Node<T>*tempPtr=next;//将欲删除的节点地址储存到tempPtr中
if(next==NULL)//如果当前节点没有后继结点,则返回NULL
return NULL;
next=tempPtr->next;//使当前节点的指针指向tempPtr的后继结点
return tempPtr;//返回被删除的节点地址
}
例:实现链表操作函数(lb2.h)
#ifndef NODE_LIBRARY
#define NODE_LIBRARY
#include<iostream.h>
#include<stdlib.h>
//头文件实现的是单节点的操作,本函数实现整个链表的操作
#include"单链表的节点类模版.h"
//生成节点
template<class T>
Node<T>*GetNode(const T&item,Node<T>*nextPtr=NULL)
{
Node<T>*newNode;//*newNode为节点类型
newNode=new Node<T>(item,nextPtr);//调用节点的构造函数
if(newNode==NULL)
{//申请失败回执
cerr<<"Memory allocation failure!"<<endl;
exit(1);
}
return newNode;//申请成功返回节点
}
enum AppendNewline{noNewline,addNewline};
//输出链表
template<class T>
void PrintList(Node<T>*head,AppendNewline addnl=noNewline)
{
Node<T>*currPtr=head;//*currPtr初始化地址为head
while(currPtr!=NULL)
{
if(addnl==addNewline)
cout<<currPtr->data<<endl;
else
cout<<currPtr->data<<" ";
//指针指向下一节点,调用成员函数,因为next是私有的
currPtr=currPtr->NextNode();
}
}
//查找节点
template<class T>
int Find(Node<T>*head,T&item,Node<T>*&prevPtr)
{
Node<T>*currPtr=head;//定义了*currPtr地址为head
prevPtr=NULL; //*prevPtr初值为0,作用为查找后删除节点用
while(currPtr!=NULL)
{
if(currPtr->data==item)
return 1;//找到回执1,我觉得这里用exit(1)好
//因为这里,如果不break的话prevPtr指针的值就会继续指向查找到节点的指针了,
//不过未经测试,这个问题放在后面再说
prevPtr=currPtr;
currPtr=currPtr->NextNode();
}
}
//在表头插入节点
template<class T>
void InsertFront(Node<T>*head,T item)
//head指向GetNode,GetNode的next指针指向head的Next指针进行传递。
{head=GetNode(item,head);}
//在表尾添加节点
template<class T>
void InsertRear(Node<T>*&head,const T&item)
{
Node<T>*newNode,*currPtr=head;
//如果在链表尾,则插入节点
if(currPtr==NULL)InsertFront(head,item);
else
{
while(currPtr->NextNode()!=NULL)
currPtr=currPtr->NextNode();
newNode=GetNode(item);
currPtr->InsertAfter(newNode);
}
}
//删除链表的头节点
template<class T>
void DeleteFront(Node<T>*&head)
{
Node<T>*p=head;
if(head!=NULL)
{
head=head->NextNode();
delete p;
}
}
//删除链表中第一个数据域等于key的节点
template<class T>
void Delete(Node<T>*&head,T key)
{
Node<T>*currPtr=head,*prevPtr=NULL;
if(currPtr==NULL)return;
while(currPtr!=NULL&&currPtr->data!=key)
{
prePtr=currPtr;
currPtr=currPtr->NextNode();
}
if(currPtr!=NULL)
{
if(prevPtr==NULL)head=head->NextNode();
else
prevPtr->DeleteAfter();
delete currPtr;
}
}
//在有序链表中插入一个节点
template<class T>
void InsertOrder(Node<T>*&head,T item)
{
Node<T>*currPtr,*prevPtr,*newNode;
prevPtr=NULL;
currPtr=head;
while(currPtr!=NULL)
{
if(item<currPtr->data)break;
prevPtr=currPtr;
currPtr=currPtr->nextNode();
}
if(prevPtr==NULL)
InsertFront(head,item);
else
{
newNode=GetNode(item);
prevPtr->InsertAfter(newNode);
}
}
//清空链表-产出链表中所有节点
template<class T>
void ClearList(Node<T>*&head)
{
Node<T>*currPtr,*nextPtr;
currPtr=head;
while(currPtr!=NULL)
{
nextPtr=currPtr->NextNode();
delete currPtr;
currPtr=nextPtr;
}
head=NULL;
}
#endif //NODE_LIBRARY
例:从键盘输入10个整数,用这些整数值作为节点数据,生成一个链表,按顺序输出链表中节点数值,
然后从键盘输入一个待查找整数,在链表中查找该整数,若找到则删除该整数所在节点,如果出现
多次,全部删除,然后输出删除节点以后的链表。在程序结束之前清空链表。
#include<iostream.h>
#include"lb1.h"
#include"lb2.h"
void main(void)
{
Node<int>*head=NULL,*prevPtr,*delPtr;
int i,key,item;
for(i=0;i<10;i++)
{
cin>>item;
InsertFront(head,item);
}
cout<<"List:";
PrintList(head,noNewline);
cout<<endl;
cout<<"请输入一个要整除的整数:";
cin>>key;
prevPtr=head;
while(Find(head,key,prevPtr)!=NULL)
{
if(prevPtr==NULL)
head=head->NextNode();
else
delPtr=prevPtr->DeleteAfter();
delete delPtr;
}
cout<<"List:";
PrintList(head,noNewline);
cout<<endl;
ClearList(head);
}