链表的相关操作(3)

来源:互联网 发布:淘宝代销货图片签协议 编辑:程序博客网 时间:2024/06/04 19:22
/*   给定两个数组A1和B1:   1)将A1和B1中的数据导入链表中,形成链表A2和B2,并打印各自链表元素;   2)将链表A2和B2中的元素各自排序(从大到小),形成链表A3和B3,并打印各自链表元素。   3)合并链表A3,B3,合并后的链表C的元素从大到小排列,并打印链表C。*//*11. 导入函数错误;扣2分; 有较小问题,扣1分;12. 排序函数错误;扣2分; 有较小问题,或借用数组,扣1分;13. 合并函数错误,扣2分;效率不高,或借用数组,或其它较小问题,扣1分;14. 主函数中调用排序函数,破坏原有链表,扣1分; 主函数中调用合并函数,破坏原有链表,扣1分;15. 无复制构造函数或赋值函数, 复制构造函数或赋值函数错误; 扣2分; 没有使用复制构造函数或赋值函数,扣1分; 复制构造函数或赋值函数有小问题,扣1分;*///-----------------------LinkedList.h------------------------------#include<iostream>#ifndef LINKED_LIST#define LINKED_LISTtypedef int ElementType;class List//定义一个List类{//--------------------内部定义一个Node类-------------------------private:class Node//定义一个Node类{public:ElementType data;//节点的数据Node *next;//节点的指针域Node(ElementType value=0,Node *link=0)//Node类的构造函数      :data(value),next(link)      {}};typedef Node *NodePointer;//--------------------成员函数以及成员变量-------------------------public:List();//构造函数~List();//析构函数List(const List & origList);//复制构造函数const List & operator=(const List & rightHandSide);//赋值构造函数bool empty() const;//判空函数int size() const;//链表的大小(长度)void insert(const ElementType item,int pos);//插入函数void display(ostream & out) const;//输出函数//-------------------------------------------void import(const ElementType *array,int size);//将数组元素导入链表的函数List sort();//排序函数List merge(const List & aList);//归并链表函数private:NodePointer first;//定义一个头指针int mySize;//链表大小(长度)};ostream & operator<<(ostream & out,const List & aList);//重载输出操作符#endif

//------------------------LinkedList.cpp-------------------------------#include<iostream>#include<cassert>using namespace std;#include"LinkedList.h"List::List()//构造函数------------------------:first(0),mySize(0){}List::~List()//析构函数------------------------{NodePointer currPtr=first,//定义指向节点的指针        nextPtr;while(currPtr!=0)//当前指针非0{nextPtr=currPtr->next;delete currPtr;  //删除当前指针currPtr=nextPtr;}mySize=0;//链表大小置为0}List::List(const List & origList)//复制构造函数-----------------------:mySize(origList.mySize){if(!origList.empty())//传进来的链表非空{NodePointer ptr=origList.first;//ptr指向参数链表的头部,以便后续进行复制操作        first=new Node(ptr->data);//复制参数链表的头指针NodePointercurrPtr=first,//当前指针,这两个指针将完成对新链表的复制与连接nextPtr;//下一个指针for(int i=0;i<mySize-1;i++)//循环mySize-1次操作{ptr=ptr->next;//ptr指向参数链表的下一个指针nextPtr=new Node(ptr->data);//nextPtr指向新节点并且复制ptr(参数链表)的数据currPtr->next=nextPtr;//currPtr指针的指针域存放nextPtr指向的节点的地址,完成节点的连接currPtr=nextPtr;//currPtr指针指向nextPtr指向的节点}}else//链表为空,提示并退出{cerr<<"***List is empty, exit this program***\n";exit(1);//退出程序}}const List & List::operator=(const List & rightHandSide)//赋值构造函数--------------------------{if(this!=&rightHandSide)//确认不是自我赋值{if(rightHandSide.empty())//参数链表非空{cerr<<"***List is empty, exit this program***\n";    exit(1);}NodePointer ptr=rightHandSide.first;//ptr指向参数链表的第一个节点first=new Node(ptr->data);//复制参数链表的头指针NodePointercurrPtr=first,//当前指针,这两个指针将完成对新链表的复制与连接nextPtr;//下一个指针if(mySize!=rightHandSide.mySize)//如果需要,分配一个新链表{ this->~List();//调用析构函数,销毁原链表               for(int i=0;i<mySize-1;i++)//循环mySize-1次操作     { ptr=ptr->next;//ptr指向参数链表的下一个指针     nextPtr=new Node(ptr->data);//nextPtr指向新节点并且复制ptr(参数链表)的数据     currPtr->next=nextPtr;//currPtr指针的指针域存放nextPtr指向的节点的地址,完成节点的连接     currPtr=nextPtr;//currPtr指针指向nextPtr指向的节点           }   }       else//此时,不需要重新创建链表,将在原链表上操作   {for(int i=0;i<mySize-1;i++)//循环mySize-1次操作{currPtr=currPtr->next;//currPtr指针指向下一个节点ptr=ptr->next;//ptr指针指向参数链表的下一个节点currPtr->data=ptr->data;//将参数链表的节点数据复制到currPtr指针的数据域}   }   }     return *this;//返回新链表对象  }bool List::empty() const//判空函数-----------------------{return first==0;}int List::size() const//链表的大小(长度)------------------------{return mySize;}void List::insert(ElementType item,int pos)//插入到第pos个节点之后的位置----------{assert(pos>=0);//保证插入位置非负NodePointer ptr=first,            newPtr=new Node(item);//定义一个带数据的节点if(pos==0)//表示插入到第一个节点位置{newPtr->next=first;          first=newPtr;}else if(pos<=mySize)//表示插入到第1到mySize节点之后位置{for(int i=1;i<pos;i++)    ptr=ptr->next;//循环结束时,ptr指向第pos个节点        newPtr->next=ptr->next;//插入新节点操作    ptr->next=newPtr;//插入新节点操作}else//pos位置越界报错{delete newPtr;//将未使用的新节点返还给堆cerr<<"***The position out of range***\n";return;}    mySize++;//链表长度加一  }  void List::import(const ElementType *array,int size)//将数组元素导入链表的函数-----------------{if(size>0)//保证数组元素个数大于0{NodePointer currPtr,newNode;//这两个指针将完成对数组数据的导入first=new Node(*array);//头指针指向第一个节点,同时将数组元素初始化在节点的数据域currPtr=first;for(int i=1;i<size;i++)//将数组剩余数据导入链表中    {    newNode=new Node(*(array+i));//数组数据从前往后导入链表currPtr->next=newNode;//连接操作currPtr=newNode;//后移操作    }}else//数组元素小于等于0进行异常报错{cerr<<"The size of the array should be greater than 0"<<endl;return;}mySize=size;//更新链表长度}List List::sort()//排序函数-------------------------{List newList(*this);//调用复制构造函数,将原链表对象复制于新链表,防止破坏原链表if(mySize<=0)//链表非空{cerr<<"***The linked list has no node,exit this program***"<<endl;exit(1);}ElementType tem;//交换变量NodePointer currPtr,nextPtr;//这两个指针将完成链表数据的排序for(int i=0;i<mySize-1;++i) //冒泡排序 {for(int j=0;j<mySize-i-1;j++)//内层循环{ currPtr=newList.first;//当前指针指向第一个节点for(int k=0;k<j;k++)//循环结束后,当前指针指向第j+1个节点currPtr=currPtr->next;nextPtr=currPtr->next;//nextPtr指向第j+2个节点if(currPtr->data<nextPtr->data)//若第j+1个节点的数据小于第j+2个节点的数据,则交换数据        {       tem=currPtr->data;       currPtr->data=nextPtr->data;//交换语句       nextPtr->data=tem;        }}   } return newList;//返回新链表,此时原链表并未被破坏}List List::merge(const List & aList)//归并链表函数------------------------{List newList1=*this,//调用复制构造函数,将第一个链表(*this)复制于新链表,防止破坏原链表 newList2=aList;//调用复制构造函数,将第一个链表(aList)复制于新链表,防止破坏原链表List mergeList;//定义归并链表mergeList.mySize=(*this).mySize+aList.mySize;//归并链表的大小进行更新mergeList.first=new Node(0);//归并链表的头指针指向一个数据域为0节点(此节点不是真正的头节点)NodePointer ptr1=newList1.first,//ptr1指向第一个链表的头节点            ptr2=newList2.first,//ptr2指向第二个链表的头节点            currPtr=mergeList.first,//currPtr指向归并链表的头节点            nextPtr,//nextPtr与currPtr将完成归并链表各个节点的生成与连接tempPtr=mergeList.first;//指向归并链表的(伪)头指针,最后进行删除while(ptr1!=0&&ptr2!=0)//ptr1与ptr2均不为0{if(ptr1->data>ptr2->data)//ptr1指向的数据大于ptr2指向的数据{nextPtr=new Node(ptr1->data);//生成一个数据等于ptr1->data的节点currPtr->next=nextPtr;//currPtr指针的指针域存放新节点地址,完成前后节点的连接currPtr=nextPtr;//currPtr指针指向新节点ptr1=ptr1->next;//ptr1指向第一个链表原节点的后一个节点}else{nextPtr=new Node(ptr2->data);//生成一个数据等于ptr2->data的节点currPtr->next=nextPtr;//currPtr指针的指针域存放新节点地址,完成前后节点的连接currPtr=nextPtr;//currPtr指针指向新节点ptr2=ptr2->next;//ptr2指向第一个链表原节点的后一个节点}}if(ptr1==0)//第一个链表的所有数据都已导入归并链表中{if(ptr2!=0)//第二个链表有部分数据未导入归并链表中{while(ptr2!=0)//ptr2未读取完第二个链表的所有数据{nextPtr=new Node(ptr2->data);//生成一个数据等于ptr2->data的节点    currPtr->next=nextPtr;//currPtr指针的指针域存放新节点地址,完成前后节点的连接currPtr=nextPtr;//currPtr指针指向新节点    ptr2=ptr2->next;//ptr2指向第一个链表原节点的后一个节点}}}else//否则,第二个链表的所有数据都已导入归并链表中,而第一个链表仍有数据未导入{while(ptr1!=0)//ptr1未读取完第一个链表的所有数据{nextPtr=new Node(ptr1->data);//生成一个数据等于ptr1->data的节点    currPtr->next=nextPtr;//currPtr指针的指针域存放新节点地址,完成前后节点的连接currPtr=nextPtr;//currPtr指针指向新节点    ptr1=ptr1->next;//ptr1指向第一个链表原节点的后一个节点}}mergeList.first=tempPtr->next;//归并链表的头节点指向下一个节点(真正的头节点)tempPtr=0;//临时指针置为0delete tempPtr;//删除(伪)头节点    return mergeList;//返回归并链表}void List::display(ostream & out) const//输出函数-----------------------{NodePointer ptr;for(ptr=first;ptr!=0;ptr=ptr->next)//从头到尾遍历并输出链表数据out<<ptr->data<<" ";out<<endl;}ostream & operator<<(ostream & out,const List & aList)//重载输出操作符------------------{aList.display(out);//调用display()成员函数return out;}

//---------------------LinkedList_main.cpp--------------------------#include<iostream>using namespace std;#include"LinkedList.h"int main(){cout<<"----------------------The program test is begin---------------------"<<endl;cout<<endl;cout<<"Constructing intList1 and intList2\n";List intList1,intList2;//定义两个链表cout<<"List1 is empty? "<<boolalpha<<intList1.empty()<<endl;//测试判空函数cout<<"Display the intList1's size:"<<intList1.size()<<endl;//测试size函数cout<<"List2 is empty? "<<boolalpha<<intList2.empty()<<endl;//测试判空函数cout<<"Display the intList2's size:"<<intList2.size()<<endl;//测试size函数cout<<"---------------------------------------------------------------------"<<endl;int a[10]={1,2,3,4,5,6,7,8,9,10};//初始化两个数组int b[10]={11,12,13,14,15,16,17,18,19,20};//初始化两个数组cout<<"There are two arrays now:";cout<<"a[10]={1,2,3,4,5,6,7,8,9,10};b[10]={11,12,13,14,15,16,17,18,19,20};"<<endl;intList1.import(a,10);//测试导入函数intList2.import(b,10);//测试导入函数cout<<"After importing the data of the array into the linked list"<<endl;cout<<"List1 is empty? "<<boolalpha<<intList1.empty()<<endl;//再次测试判空函数cout<<"Display the intList1's size:"<<intList1.size()<<endl;//再次测试size函数cout<<"List2 is empty? "<<boolalpha<<intList2.empty()<<endl;//再次测试判空函数cout<<"Display the intList2's size:"<<intList2.size()<<endl;//再次测试size函数cout<<"---------------------------------------------------------------------"<<endl;cout<<"Display the data in the linked list:"<<endl;cout<<"intList1 :"<<endl; intList1.display(cout);//显示导入数组数据后的结果cout<<"intList2 :"<<endl; intList2.display(cout);//显示导入数组数据后的结果cout<<"---------------------------------------------------------------------"<<endl;cout<<"After sorting the data in the list from large to small"<<endl;cout<<"intList1 :"<<endl; List A3=intList1.sort();//排序后的结果返回给A3链表 A3.display(cout);//显示将第一个链表排序后的结果cout<<"intList2 :"<<endl; List B3=intList2.sort();//排序后的结果返回给B3链表 B3.display(cout);//显示将第二个链表排序后的结果cout<<endl;cout<<"The data in the original list"<<endl;cout<<"The original intList1 :"<<endl;intList1.display(cout);//显示将第一个链表排序前的结果,观察是否数据被破坏cout<<"The original intList2 :"<<endl;intList2.display(cout);//显示将第二个链表排序前的结果,观察是否数据被破坏cout<<"---------------------------------------------------------------------"<<endl;cout<<"After merging two linked lists"<<endl;List C=A3.merge(B3);//将排序已完成的A3链表与B3链表归并,并将结果返回给新链表Ccout<<"intList C :"<<endl; C.display(cout);//输出归并链表后的结果cout<<endl;cout<<"The data in the original list"<<endl;cout<<"The original A3 :"<<endl;A3.display(cout);//显示将第一个链表归并前的数据,观察是否数据被破坏cout<<"The original B3 :"<<endl;B3.display(cout);//显示将第二个链表排序前的数据,观察是否数据被破坏cout<<"Insert a node into the linked list"<<endl;//检验插入函数是否正确C.insert(2017,10);//将2017插入到第十个节点之后C.display(cout);//输出结果/*排序函数中已经使用复制构造函数,归并函数中已经使用赋值构造函数,  主要作用是生成新链表,相关操作在新链表上进行,以防止原有链表数据被破坏,  在此,不再进行验证*/cout<<"----------------------The program test is end--------------------------"<<endl;system("pause");return 0;}

原创粉丝点击