带头结点的单链表
为了方便实现,为每一个链表加上一个“头结点”,如下图所示。它位于链表首元结点之前。头结点的data域可以不存储任何信息,也可以存放一个特殊标志或表长。下图中分别给出了非空表和空表的情形。只要表存在,它必须至少有一个头结点。
由于在链表的首元结点前面还有一个头结点,因此,只要把头结点当作第0个结点,在算法中查找第ai-1个结点时从k=0时开始,如果i不超过表的长度加1,总能找到含ai-1的结点并让指针p指向它。这样,使用带头结点的链表,将有以下两个好处:
- 统一了空表和非空表的操作:在空表或非空表首元结点之前的插入可以不作为特殊情况专门处理;类似地,删除首元结点导致空表与一般情况一样,也可统一处理。
- 简化了链表的插入与删除操作代码的实现。
程序2-18给出单链表部分常用操作的实现。需要明确的是,所有操作的参数表中链表头指针first都是引用型参数,即把它看做实际一个链表头指针的别名。
[程勋 2-18] 单链表部分常用操作的实现
void initList(LinkList&first){
//初始化单链表
first=new LinkNode; //创建头结点
if(!first){
cerr<<2存储分配失败!\n2;exit(1);} //链接stdlib.h和iostream.h
first->link=NULL; //置空
};
void cleatList(LinkList&first){
//清空单链表
LinkNode*q;
while(first->link!=NULL){
//当链表不空是,删去链中的所有结点
q=first->link;
first->link=q->link; //保存被删结点,从链上摘下该结点
delete q; //删除(仅保留一个头结点)
}
};
int Length(LinkList&first){
//计算表的长度
LinkNode*p=first->link;int count=0;
while(p!=NULL) //循链扫描,计算结点数
{
p=p->link;count++;}
return count;
};
int isEmpty(LinkList&first){
//判断单链表是否为空。如果表空,则函数返回1,否则函数返回0
return (first->link==NULL);
};
LinkNode*Search(LinkList&first,DataType x