两个链表实现集合的运算

/------------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;


}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值