该单向链表类名字为Linked_list。
1.Linked_list类的基本数据成员:
单向链表类Linked_list的基本数据成员包括:指向链表头节点的指针head,以及链表的节点数目size,如下所示:
Node *head; //当前链表的头节点
int size; //当前链表的节点数目
其中链表节点Node类的实现如下:
struct Node
{
int data;
Node *next=NULL;
Node(int nums):data(nums),next(NULL)
{
}
};
2.Linked_list类的成员函数:
Linked_list类的成员函数如下:
//构造函数
Linked_list(); //单向链表构造函数:构造空链表
Linked_list(int nums[],int size); //单向链表构造函数:由数组构造链表
Linked_list(const Linked_list &other); //拷贝构造函数
//运算符
Linked_list operator= (const Linked_list &other); //拷贝构造运算符
Linked_list operator+ (const Linked_list &other); //加法运算符:将两个单向链表相连接
//链表节点查找
Node *search_by_content(int target); //根据内容查找节点的第一次出现的地址
int search_by_position(int pos); //根据下标位置查找节点的内容
//链表节点插入
bool insert_by_position(int nums,int pos); //根据位置进行插入节点
void insert_back(int nums); //将指定的内容插入到链表的末尾
//链表节点删除
bool delete_by_content(int nums); //根据内容进行删除节点
bool delete_by_position(int pos); //根据位置进行删除节点
//单向链表特殊操作
void reverse(); //将当前的链表反转
void clean(); //将当前链表清空
int count(); //返回当前链表的节点数目
void print(); //输出链表的值
3.Linked_list类成员函数的实现:
Linked_list类成员函数的实现,实现的细节和需要注意的要点可以参见注释:
Linked_list::Linked_list() //单向链表构造函数:构造空链表
{
size=0;
head=NULL;
}
Linked_list::Linked_list(int nums[],int isize) //单向链表构造函数:由数组构造链表
{
//该函数既可以通过调用insert_back进行实现,也可以不调用
//若决定调用insert_back成员函数进行实现,则必须先初始化head=NULL,size=0,因为insert_back函数需要链表的相关信息
head=NULL;
size=0;
for(int i=0;idata); //该函数已经计算了链表节点数目
now=now->next;
}
}
Linked_list Linked_list::operator= (const Linked_list &other) //拷贝构造运算符
{
//链表的拷贝构造运算符需要考虑原链表是否为空,原链表非空的时候需要清空链表
if(size) //当原链表非空的时候,这时需要将原链表清空,否则会导致内存泄漏
(*this).clean();
Node *now=other.head;
while(now!=NULL)
{
(*this).insert_back(now->data);
now=now->next;
}
size=other.size;
return (*this);
}
Linked_list Linked_list::operator+ (const Linked_list &other) //加法运算符:将两个单向链表相连接
{
Node *now=other.head;
while(now!=NULL)
{
(*this).insert_back(now->data);
now=now->next;
}
size+=other.size;
return (*this);
}
Node *Linked_list::search_by_content(int target) //给定内容查找该内容所在的节点
{
Node *now=head;
while(now!=NULL)
{
if(now->data==target)
return now;
now=now->next;
}
return NULL;
}
int Linked_list::search_by_position(int pos) //根据下标位置查找节点的内容
{
if(pos>=size)
return INT_MAX; //下标超出上限返回错误标志INT_MAX
if(pos<0)
return INT_MIN; //下标超出下限返回错误标志INT_MAX
Node *now=head;
for(int i=0;inext;
}
return now->data;
}
bool Linked_list::insert_by_position(int nums,int pos) //根据位置进行插入节点
{
//先判断插入位置是否合法
if(pos>size||pos<0)
return false;
//特判:当pos=0,即插入的节点位置为链表头时,这里已经特别考虑了链表为空时在链表头插入的情况
else if(!pos)
{
Node *temp=head;
head=new Node(nums);
head->next=temp;
}
//特判:当pos=size,即插入的节点位置为链表尾时
else if(pos==size)
{
Node *now=head;
while(now->next)
{
now=now->next;
}
now->next=new Node(nums);
}
else
{
Node *back=head;
for(int i=0;inext;
}
Node *now=new Node(nums);
Node *next=back->next;
back->next=now;
now->next=next;
}
size++;
return true;
}
void Linked_list::insert_back(int nums) //将指定的内容插入到链表的末尾
{
//特判:当链表为空的时候,需要特别进行处理
if(head==NULL)
{
head=new Node(nums);
}
else
{
Node *now=head;
while(now->next)
{
now=now->next;
}
now->next=new Node(nums);
}
size++;
}
bool Linked_list::delete_by_content(int nums) //根据内容进行删除节点
{
bool flag=false;
Node *now=head;
while(now)
{
if(now->data==nums)
{
flag=1;
//下面开始删除节点
if(now==head) //特判情况:当待删除的节点是链表的第一个节点
{
Node *pre_del=head;
head=now;
size--;
delete pre_del;
}
else //其他情况:当待删除的节点不是链表的第一个节点
{
//先查找待删除节点的前驱元
Node *back=head;
while(back->next!=now)
{
back=back->next;
}
//开始正式删除待删除节点
back->next=now->next;
Node *pre_del=now;
size--;
delete pre_del;
}
}
now=now->next; //推荐将游标移动语句now=now->next写在链表的
}
return flag;
}
bool Linked_list::delete_by_position(int pos) //根据位置进行删除节点
{
//这里使用双游标法减少运行时间,思路:空间换时间
if(pos<0||pos>=size)
return false;
else if(pos==0) //特判:删除头节点情况
{
if(size==1) //特判:当链表中只剩下一个节点的情况
{
delete head;
head=NULL;
size=0;
}
else
{
Node *pre_del=head;
head=head->next;
size--;
delete pre_del;
}
}
else
{
Node *back=head;
Node *now=head->next;
for(int i=0;inext;
now=now->next;
}
back->next=now->next;
size--;
delete now;
}
return true;
}
void Linked_list::reverse() //将当前的链表反转
{
//常用的一种链表反转方式:使用双指针将各个节点的连接处进行反转
if(head==NULL) //特判:空链表不需要进行反转
return;
Node *back=head;
Node *now=head->next;
while(now)
{
Node *temp=now->next; //记录指针移动的下一个节点
//反转连接处
now->next=back;
//移动双指针
back=now;
now=temp;
}
//在每个连接处都进行反转之后,这时双指针中的back即为新的链表头节点
//这时先将链表尾节点(即原链表头)的next指针置为空
head->next=NULL;
head=back;
return;
}
void Linked_list::clean() //将当前链表清空
{
Node *now=head;
while(now)
{
Node *temp=now;
now=now->next;
delete temp;
}
size=0;
head=NULL;
}
int Linked_list::count() //返回当前链表的节点数目
{
return size;
}
void Linked_list::print() //输出链表各节点的值
{
Node *now=head;
while(now)
{
cout<data<<" ";
now=now->next;
}
cout<
4.ADT源代码:
#include
#include
using namespace std;
struct Node
{
int data;
Node *next=NULL;
Node(int nums):data(nums),next(NULL)
{
}
};
class Linked_list
{
public:
//构造函数
Linked_list(); //单向链表构造函数:构造空链表
Linked_list(int nums[],int size); //单向链表构造函数:由数组构造链表
Linked_list(const Linked_list &other); //拷贝构造函数
//运算符
Linked_list operator= (const Linked_list &other); //拷贝构造运算符
Linked_list operator+ (const Linked_list &other); //加法运算符:将两个单向链表相连接
//链表节点查找
Node *search_by_content(int target); //根据内容查找节点的第一次出现的地址
int search_by_position(int pos); //根据下标位置查找节点的内容
//链表节点插入
bool insert_by_position(int nums,int pos); //根据位置进行插入节点
void insert_back(int nums); //将指定的内容插入到链表的末尾
//链表节点删除
bool delete_by_content(int nums); //根据内容进行删除节点
bool delete_by_position(int pos); //根据位置进行删除节点
//单向链表特殊操作
void reverse(); //将当前的链表反转
void clean(); //将当前链表清空
int count(); //返回当前链表的节点数目
void print(); //输出链表的值
private:
Node *head; //当前链表的头节点
int size; //当前链表的节点数目
};
Linked_list::Linked_list() //单向链表构造函数:构造空链表
{
size=0;
head=NULL;
}
Linked_list::Linked_list(int nums[],int isize) //单向链表构造函数:由数组构造链表
{
//该函数既可以通过调用insert_back进行实现,也可以不调用
//若决定调用insert_back成员函数进行实现,则必须先初始化head=NULL,size=0,因为insert_back函数需要链表的相关信息
head=NULL;
size=0;
for(int i=0;idata); //该函数已经计算了链表节点数目
now=now->next;
}
}
Linked_list Linked_list::operator= (const Linked_list &other) //拷贝构造运算符
{
//链表的拷贝构造运算符需要考虑原链表是否为空,原链表非空的时候需要清空链表
if(size) //当原链表非空的时候,这时需要将原链表清空,否则会导致内存泄漏
(*this).clean();
Node *now=other.head;
while(now!=NULL)
{
(*this).insert_back(now->data);
now=now->next;
}
size=other.size;
return (*this);
}
Linked_list Linked_list::operator+ (const Linked_list &other) //加法运算符:将两个单向链表相连接
{
Node *now=other.head;
while(now!=NULL)
{
(*this).insert_back(now->data);
now=now->next;
}
size+=other.size;
return (*this);
}
Node *Linked_list::search_by_content(int target) //给定内容查找该内容所在的节点
{
Node *now=head;
while(now!=NULL)
{
if(now->data==target)
return now;
now=now->next;
}
return NULL;
}
int Linked_list::search_by_position(int pos) //根据下标位置查找节点的内容
{
if(pos>=size)
return INT_MAX; //下标超出上限返回错误标志INT_MAX
if(pos<0)
return INT_MIN; //下标超出下限返回错误标志INT_MAX
Node *now=head;
for(int i=0;inext;
}
return now->data;
}
bool Linked_list::insert_by_position(int nums,int pos) //根据位置进行插入节点
{
//先判断插入位置是否合法
if(pos>size||pos<0)
return false;
//特判:当pos=0,即插入的节点位置为链表头时,这里已经特别考虑了链表为空时在链表头插入的情况
else if(!pos)
{
Node *temp=head;
head=new Node(nums);
head->next=temp;
}
//特判:当pos=size,即插入的节点位置为链表尾时
else if(pos==size)
{
Node *now=head;
while(now->next)
{
now=now->next;
}
now->next=new Node(nums);
}
else
{
Node *back=head;
for(int i=0;inext;
}
Node *now=new Node(nums);
Node *next=back->next;
back->next=now;
now->next=next;
}
size++;
return true;
}
void Linked_list::insert_back(int nums) //将指定的内容插入到链表的末尾
{
//特判:当链表为空的时候,需要特别进行处理
if(head==NULL)
{
head=new Node(nums);
}
else
{
Node *now=head;
while(now->next)
{
now=now->next;
}
now->next=new Node(nums);
}
size++;
}
bool Linked_list::delete_by_content(int nums) //根据内容进行删除节点
{
bool flag=false;
Node *now=head;
while(now)
{
if(now->data==nums)
{
flag=1;
//下面开始删除节点
if(now==head) //特判情况:当待删除的节点是链表的第一个节点
{
Node *pre_del=head;
head=now;
size--;
delete pre_del;
}
else //其他情况:当待删除的节点不是链表的第一个节点
{
//先查找待删除节点的前驱元
Node *back=head;
while(back->next!=now)
{
back=back->next;
}
//开始正式删除待删除节点
back->next=now->next;
Node *pre_del=now;
size--;
delete pre_del;
}
}
now=now->next; //推荐将游标移动语句now=now->next写在链表的
}
return flag;
}
bool Linked_list::delete_by_position(int pos) //根据位置进行删除节点
{
//这里使用双游标法减少运行时间,思路:空间换时间
if(pos<0||pos>=size)
return false;
else if(pos==0) //特判:删除头节点情况
{
if(size==1) //特判:当链表中只剩下一个节点的情况
{
delete head;
head=NULL;
size=0;
}
else
{
Node *pre_del=head;
head=head->next;
size--;
delete pre_del;
}
}
else
{
Node *back=head;
Node *now=head->next;
for(int i=0;inext;
now=now->next;
}
back->next=now->next;
size--;
delete now;
}
return true;
}
void Linked_list::reverse() //将当前的链表反转
{
//常用的一种链表反转方式:使用双指针将各个节点的连接处进行反转
if(head==NULL) //特判:空链表不需要进行反转
return;
Node *back=head;
Node *now=head->next;
while(now)
{
Node *temp=now->next; //记录指针移动的下一个节点
//反转连接处
now->next=back;
//移动双指针
back=now;
now=temp;
}
//在每个连接处都进行反转之后,这时双指针中的back即为新的链表头节点
//这时先将链表尾节点(即原链表头)的next指针置为空
head->next=NULL;
head=back;
return;
}
void Linked_list::clean() //将当前链表清空
{
Node *now=head;
while(now)
{
Node *temp=now;
now=now->next;
delete temp;
}
size=0;
head=NULL;
}
int Linked_list::count() //返回当前链表的节点数目
{
return size;
}
void Linked_list::print() //输出链表各节点的值
{
Node *now=head;
while(now)
{
cout<data<<" ";
now=now->next;
}
cout<data<data<