链表的相关操作(3)

/*   给定两个数组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_LIST

typedef 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);//复制参数链表的头指针
		NodePointer	currPtr=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);//复制参数链表的头指针
		NodePointer	currPtr=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;//临时指针置为0
	delete 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链表归并,并将结果返回给新链表C
	cout<<"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;
}

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值