您的位置:首页 > 理论基础 > 数据结构算法

两个链表实现集合的运算

2016-03-29 23:17 471 查看
/////////////////////////------------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 ElemTy
4000
pe>

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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息