#include<iostream>
using namespace std;
struct Node{
Node(const int&d):data(d),next(0){}//或者为next(null)
int data;//数据域
Node*next; //指针域
};
class LinkList{
private: Node *pHead,*last;
unsigned listsize;
public :
LinkList():pHead(0),last(0),listsize(0){};//构造函数 ,pHead初始化为0(当前链表中不包含任何元素)
LinkList(int *arr,int n); //构造函数
LinkList(const LinkList &a);//复制构造函数
~LinkList(); //析构函数
unsigned size()const{return listsize;}//用于返回链表节点个数
int date(Node*pos){return pos->data;} //用于返回pos节点的数据
Node *begin()const {return pHead;} //用于返回头节点,
bool empty()const{if(!listsize)return true;return false;}//判断当前链表是否有元素 ,老师的要求是int IsEmpty(),这是按自己的习惯写的。
void push_front(const int&d); //插入一个头节点。老师的要求为void insert(int value),这是按自己的习惯写的。
void push_back(const int&d); //插入一个末节点。
void insert(int n,const int &d); //在第n的节点的位置后插入一个储存d数据的节点。
void pop_front();//删除头结点
void pop_back();//删除末节点
Node*find(const int&d)const; //在原链表中找到储存d数据节点的位置
bool deletenode(const int&c); //删除第一个储存的是数据c 的节点(会判断是否存在数据c,存在则删除并返回true,不存在则返回false
LinkList &operator=(const LinkList &a);
LinkList &operator+=(const LinkList&a);
friend LinkList operator+(const LinkList&a,const LinkList&b);
void clear(); //清空链表
void print()const;};//遍历(输出每个节点的数据)
LinkList::LinkList(int*arr,int n){
if(n==0) LinkList();//列表长度为0,则直接调用构造函数
listsize=n;
Node*p;
pHead=last=new Node(arr[0]);
for(int i=1;i<n;i++){//把节点位置储存的数据一个一个赋值
p=new Node(arr[i]);
last->next=p;
last=p;}}
LinkList::LinkList(const LinkList &a){
if(a.pHead==0){ //若a中没有元素 ,则该链表也为空链表
pHead=last=0;
listsize=0;
return; }
Node*p2=new Node((a.pHead)->data);
last=pHead=p2; //先使开始时pHead和last相等
listsize=a.listsize;
for(Node*p=(a.pHead)->next;p;p=p->next){//把a中的每一个节点的数据都复制到this中
Node*p2=new Node(p->data);
last->next=p2; //先使last的位置为当前已拷贝的数据的位置,随后不断更新
last=p2;}}
void LinkList::push_back(const int&d){
Node*p=new Node(d);
if(last)last->next=p;//列表不为空
else pHead=p; //列表为空 ,则firs和last都赋为p;
last=p;
listsize++;}
void LinkList::push_front(const int&d){
Node*p=new Node(d); //先给该数据分配地址
p->next=pHead;pHead=p;//原链表pHead接到p的后面,p位置变为pHead ,即把插入的数据变为头结点
if(!last){last=p;} //若原链表为空,则插入的数据既是头结点,也是尾节点。
listsize++;}
void LinkList::insert(int n,const int&d){
Node*pos=(*this).pHead;
for(int i=0;i<n-1;i++)//先找到该地址
pos=pos->next;
Node*p=new Node(d);
p->next=pos->next;pos->next=p;//把该数插到pos位置后
if(pos==last) last=p; //若pos位置为末位置,则直接接上去
listsize++;}
void LinkList::pop_front(){
if(pHead){ //若原链表不为空,
Node*p=pHead;//使p变为头结点
pHead=pHead->next;//将pHead位置给第二数的位置
listsize--;
delete p; } //删除链表原先头结点的数据
if(!pHead)last=0;} //若原链表为空,或者只存在一个节点,则删除后链表中不会存在节点
void LinkList::pop_back(){
Node*p=pHead;
if(last==0)return;//若链表为空时,没有尾节点可以删除,直接跳出该函数
if(pHead==last){ //若链表中只有一个数时,直接删这个数
pHead=last=0; //删除后,链表变为空
listsize=0;
delete p;
return;
}
while(p->next!=last)p=p->next;//链表不止存在一个节点使,先用循环结构找到倒数第二个数的位置
last=p;p=p->next; //使倒数第二个节点变为链表末节点,使P指向原链表的末节点,方便删掉P
last->next=0;
listsize--;
delete p;
return;}
Node*LinkList::find(const int&d)const{//查找节点,找到第一个符合的节点
for(Node*p=pHead;p;p=p->next)
if(p->data==d)return p;
return 0;
}
bool LinkList::deletenode(const int&d){
if(!pHead)return false;//当原链表为空时,直接返回false,既不可能会存在d;
Node*p=pHead;
if(pHead->data==d){ //若头结点就是d所在位置,则删除头结点
pHead=pHead->next; //删除头结点后,原第二节点变为头结点
listsize--;
delete p;
return true;
}
Node*p0=p;p=p->next;//若头结点不是d所在位置,则从第二个节点一个一个往下找 ,p0为p节点前面的节点
while(p!=0) //在未找到该数据的节点且链表数据还未全部比对情况下,一直找
if(p->data==d){ //找到后,删除该节点并返回true
p0->next=p->next;
if(p==last)last=p0;//若该数据在末节点,则将末节点的前面一个节点置为末节点
listsize--;
delete p; //原末节点数据删除
return true;
}
else{p0=p;p=p->next;}//在还没找到的情况下,一一往下找,p0是p前面一个的位置 ,并不断更新它们的位置
return false;} //不存在储存d数据的节点则返回false
void LinkList::print()const{ //遍历
for(Node*p=pHead;p!=last;p=p->next)//从第一个位置开始一个个打印
cout<<p->data<<" ";
cout<<last->data<<endl; //打印最后一个位置对应的数据
}
LinkList operator+(const LinkList&a,const LinkList&b){
LinkList t=a; //先在创建一个链表对象t,使用拷贝构造使其和a链表相同
for(Node*p=b.pHead;p;p=p->next)//从pHead位置每个数据都放到t的末尾,不断更新链表t
t.push_back(p->data);
return t;} //返回链表对象t
LinkList&LinkList::operator=(const LinkList&a){
clear(); //先把原链表中的数据清空,变为空链表,后续操作参考拷贝构造函数
Node*p0=a.pHead;
if(p0==0){
last=pHead=0;
listsize=0;
return *this;}
Node*p2=new Node(p0->data);
last=pHead=p2; //先使开始时pHead和last相等 ,头结点和末节点相同
listsize=a.listsize;
for(Node*p=p0->next;p;p=p->next){//把a中的每一个节点的数据都复制到this中
Node*p2=new Node(p->data);
last->next=p2;
last=p2;} // 先使last的位置为当前已拷贝的数据的位置,随后不断更新
return *this;
}
LinkList&LinkList::operator+=(const LinkList&a){
if(this==&a){ //若自身相加 ,则需先复制该链表,在把数据以一一放在后面 ,避免因本身改变导致一直加下去
LinkList b=a;
for(Node*p=b.pHead;p;p=p->next)
push_back(p->data);
return *this; }
for(Node*p=a.pHead;p;p=p->next)
push_back(p->data);
return*this;
}
void LinkList::clear()
{ (*this).~LinkList(); //调用析构函数清除数据
pHead=last=0;
listsize=0;}
LinkList::~LinkList(){
for(Node*p=pHead;pHead!=0;p=pHead){//把数据一个一个析构掉
pHead=pHead->next;
delete p;
}
}
int main(){
int arr[10]={1,2,3,4,5,6,7,8,9,10};
LinkList a(arr,10),b(arr,9),c;
a.print(); //测试构造函数
a.insert(5,55); //下一段代码来测试插入节点的准确性
a.print();
b=a; //测试操作符(=)的准确性 (同时可以测试clear()函数(用于清空链表)的准确性 )
b.print();
b.push_front(333); //测试在头结点插入节点的准确性
b.push_back(999); //测试在末节点插入节点的准确性
b.print();
b.pop_front(); //测试删除头结点的准确性
b.pop_back(); //测试删除头结点的准确性
b.print();
cout<<"b是否为空"<<b.empty()<<endl; //以下代码测试empty函数(链表是否为空)的准确性
cout<<"c是否为空"<<c.empty()<<endl;
b.deletenode(1); //测试删除第一个储存数据为1的节点
b.print();
c=a+b; //测试操作符(+)(把两个链表连接在一起,a在前)的准确性
c.print();
b+=a; //测试操作符(+=)的准确性
b.print();
}
基本的链表建立C++
猜你喜欢
转载自blog.csdn.net/cangzhexingxing/article/details/125793094
今日推荐
周排行