基本的链表建立C++

#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();
}  
  
  
  

猜你喜欢

转载自blog.csdn.net/cangzhexingxing/article/details/125793094
今日推荐