/------------LinkNode.h
//#ifndef _LinkNODE_
//#define _LINKNODE_// 单链表结点类
template <class ElemType>
struct LinkNode
{
ElemType data;
LinkNode<ElemType> *next;
};
//#endif
///---------------------LinkList.h
#ifndef _LinkLIST_
#define _LINKLIST_
#include "LinkNode.h"
// 单链表类
template <class ElemType>
class LinkList
{
public:
LinkList();
LinkList(const LinkList<ElemType>&);
~LinkList();
bool IsEmpty()const {return len <= 0;}
int Length()const {return len;}
void Clear();
bool GetElem (ElemType&,int) const;
bool SetElem( const ElemType&,int);
int LocateElem(const ElemType&) const;
int LocatePrior(const ElemType&) const;
int LocateNext(const ElemType&) const ;
bool OrderInsert(const ElemType&, int);
bool TailInsert(const ElemType&);
bool OrderDelete(ElemType&,int);
void Traverse(void(*visit)(const ElemType&)) const;
void Inverse(LinkList<ElemType> &); //新增方法,实现链表的逆置操作
void LinkDel(LinkList<ElemType> &); //新增方法,删除单链表中值相同的元素
LinkList<ElemType> operator=(const LinkList<ElemType>&);
private:
int len;
void CopyFrom(const LinkList<ElemType>&);
LinkNode<ElemType> *head;
LinkNode<ElemType> *tail;
};
// 构造一个带表头结点、空的单链表
template<class ElemType>
LinkList<ElemType>::LinkList()
{
len = 0;
head = tail = new LinkNode<ElemType> ;
head->next = NULL;
}
// 拷贝构造函数。从现有的单链表拷贝构造出一个单链表
template<class ElemType>
LinkList<ElemType>::LinkList(const LinkList<ElemType> &r)
{
CopyFrom(r); // 从r所引用的链表中复制所有的结点
}
// 析构函数
template <class ElemType>
LinkList<ElemType>::~LinkList( )
{
Clear(); // 释放所有的结点空间
delete head;
}
// 释放单链表中的所有数据结点
template <class ElemType>
void LinkList<ElemType>::Clear()
{
LinkNode<ElemType> *p = head->next, *q;
while (p)
{
q = p->next;
delete p;
p = q;
}
tail = head;
head->next = NULL;
len = 0;
}
// 在单链表中序号为i的位置存入数据元素 (i的合法值为1≤i≤len)
template <class ElemType>
bool LinkList<ElemType>::SetElem(const ElemType &e, int i)
{
if(i<0||i>len+1)
return false;
LinkNode<ElemType> *p=head->next;
int k=1;
while(k<i)
{
p=p->next;
k++;
}
p->data=e;
return true;
}
// 返回单链表中序号为i的数据元素 (i的合法值为1≤i≤len)
template<class ElemType>
bool LinkList<ElemType>::GetElem(ElemType &e, int i) const
{
if (i < 1 || i > len)
return false;
LinkNode<ElemType> *p = head->next;
int k = 1;
while (k < i)
{
p = p->next;
k++;
}
e = p->data;
return true;
}
// 从第一个位置起查找与e匹配的数据元素,若存在则返回该数据元素的位置
// 如果ElemType引用的是一个复杂的数据类型,那么在定义ElemType引用的数据类型时,必须重载!=运算符
template<class ElemType>
int LinkList<ElemType>::LocateElem(const ElemType &e) const
{
LinkNode<ElemType> *p=head->next;
int i=1;
while(p&&p->data!=e)
{
i++;
p=p->next;
}
if(p)
return i;
return 0;
}
//从第一个位置起查找与e匹配的数据元素,若存在且不是第一个则返回该数据元素前驱的位置
// 如果ElemType引用的是一个复杂的数据类型,那么在定义ElemType引用的数据类型时,必须重载!=运算符
template<class ElemType>
int LinkList<ElemType>::LocatePrior(const ElemType &e) const
{
int i = LocateElem(e);
if (i > 1)
return i - 1;
else
return 0;
}
// 函数从第一个位置起查找与e匹配的数据元素,若存在且不是最后一个则返回该数据元素后继的位置
// 如果ElemType引用的是一个复杂的数据类型,那么在定义ElemType引用的数据类型时,必须重载!=运算符
template<class ElemType>
int LinkList<ElemType>::LocateNext(const ElemType &e) const
{
int i = LocateElem (e);
if (i >= 1 && i < len)
return i + 1;
return 0;
}
//在单链表中第i个数据元素之前插入新的数据元素e(i的合法值为1≤i≤len+1)
template<class ElemType>
bool LinkList<ElemType>::OrderInsert(const ElemType &e, int i)
{
if(i<0||i>len+1)
return false;
int k=1;
LinkNode<ElemType> *p=head,*q;
q=new LinkNode<ElemType>;
q->data=e;
while(k<i)
{
p=p->next;
k++;
}
q->next=p->next;
p->next=q;
return true;
if(i==len+1)
{
tail=q;
}
++len;
}
// 在链表linkList的末尾插入新的元素e
template<class ElemType>
bool LinkList<ElemType>::TailInsert(const ElemType &e)
{
LinkNode<ElemType> *p;
p = new LinkNode<ElemType>;
p->data = e;
tail->next=p;
tail=p;
tail->next=NULL;
len++;
return true;
}
// 在单链表中删除第i个数据元素并用数据变量e返回其值(i的合法值为1≤i≤Len)
template<class ElemType>
bool LinkList<ElemType>::OrderDelete(ElemType &e,int i)
{
if(i<0||i>len)
return false;
LinkNode<ElemType> *p=head,*q;
int k=1;
while(k<i)
{
p=p->next;
k++;
}
q=p->next;
p->next=q->next;
if(q==tail) /---------关键 ,附加判断,保证程序的灵活性
tail=p;
e=q->data; //-------用e来返回值
delete q;
--len;
return true;
}
// 依序对单链表中的每个数据元素对行遍历,遍历到每个数据元素时调用函数visit()一次且仅一次
template<class ElemType>
void LinkList<ElemType>::Traverse(void(*visit)(const ElemType &e)) const
{
LinkNode<ElemType> *p = head->next;
while (p)
{
visit(p->data);
p = p->next;
}
}
// 重载=运算符
template<class ElemType>
LinkList<ElemType> LinkList<ElemType>::operator=(const LinkList<ElemType> &r)
{
Clear();
CopyFrom(r);
return *this;
}
// 从现有的一个链表中复制所有的结点
template <class ElemType>
void LinkList<ElemType>::CopyFrom(const LinkList<ElemType> &r)
{
len = 0;
head = tail = new LinkNode<ElemType>;
head->next = NULL;
LinkNode<ElemType> *p = r.head->next;
while (p)
{
TailInsert(p->data);
p = p->next;
}
};
//单链表逆置
template <class ElemType>
void LinkList<ElemType>::Inverse(LinkList<ElemType> &r)
{
LinkNode<ElemType> *p, *q, *s;
p=head->next;
q=p->next;
while(p&&q)
{
s=q->next;
q->next=p;
p=q;
q=s;
}
head->next->next=NULL;
head->next=p;
};
//删除单链表中的相同元素
template <class ElemType>
void LinkList<ElemType>::LinkDel(LinkList<ElemType> &r)
{
LinkNode<ElemType> *p,*q,*s;
p=head->next;
q=p->next;
while(p&&q)
{
if(p->data==q->data)
{
p->next=q->next;
s=q->next;
delete q;
q=s;
--len;
}
else {
p=q;
q=q->next;
}
}
}
#endif
/------------cpp
#include <iostream>
#include "LinkList.h"
using namespace std;
void Print(const char &c)
{
cout<<c<<" ";
}
//使用线性表实现集合运算(A-B)与(B-A),即找出两个集合中所有不同的元素
void Difference(LinkList<char> &la,LinkList<char> &lb)
{
int i,lblen;
lblen=lb.Length();
//逐一读入B表的数据到A表中查找,若存在则从A表中删除,否则,插入到A表
for(i=1;i<=lblen;i++)
{
char e;
lb.GetElem(e,i);
int k=la.LocateElem(e);
if(k)
{
la.OrderDelete(e,k);
}
else
{
la.TailInsert(e);
}
}
}
//建立线性表存储表示的集合
void Create(LinkList<char> &la,int &k)
{
char e;
for(int i=0;i<k;i++)
{
cin>>e;
la.TailInsert(e);
}
}
int main()
{
int n,m;
cout<<"---此程序实现集合运算(A-B)与(B-A)"<<endl<<endl;
cout<<"请输入集合A中元素的个数"<<endl;
cin>>n;
cout<<"请输入集合B中元素的个数"<<endl;
cin>>m;
cout<<"1:解题模板是单链表类,数据元素类型是字符型"<<endl<<endl;
LinkList<char> la1,la2;
cout<<"请输入"<<n<<"个数据元素至集合A"<<endl;
Create(la1,n);
cout<<"请输入"<<m<<"个数据元素至集合B"<<endl;
Create(la2,m);
Difference(la1,la2);
cout<<"运算后的集合A是:"<<endl;
la1.Traverse(Print);
cout<<endl<<endl;
return 0;
}