Intset实现:真正理解并掌握链表

这道习题让我纠结了一整天。在写Intset的添加元素的push成员函数时,我一下走进了思维误区。直到晚上无意间看到了C++Primer 16章的Queue类之后才犹如醍醐灌顶。问题在于我把empty()函数写砸了。我原先是这样写的:

bool Intset::empty() const

{

    return beg==end;

}

然而,这样的一个empty函数将导致在添加第一个元素时陷入困境。在添加第一个元素时

if(empty())

    beg=end=newElement;

empty显示容器仍然为空。而事实上,容器已经有一个元素了。

这样以后我绞尽脑汁写了一个更别扭的:

if(empty())

{

    beg=newElement;

    beg->next=end;

}

这样,容器“不再为空”了。但是在添加第二个元素时,你会发现一个惊人的事实:你无法写出添加第二个元素的代码。

if(!empty())

    .....//这里竟然会无法实现。

这是很正常的。因为,end指针此时为0,而不是指向尾元素。这导致end指向了“尾元素的下一位置”,而beg却指向了尾元素。这显然是链表出现了结构错误。

正确的empty()应该是:

bool Intset::empty() const

{

    return beg==0;

}

还有,del函数也相当关键。我也思考了不少时间。


//9.(*3)定义、实现并测试一个整数集合的类Intset,提供并、交和对称差等操作。

//10.(*1.5)将类Intset修改为一个结点Node的集合。其中Node是你定义的一种struct。
#include <iostream>
#include <stdexcept>
using namespace std;
struct Node{
Node(int ival):i(ival),next(0){}
Node* next;
int i;
};
class Intset{
public:    
    Intset():beg(0),end(0){}
    ~Intset();
    
    bool push(int);
    void del(Node*);
    Node* find(int) const;
    
    Intset setUnion(const Intset&) const;
    Intset intersect(const Intset&) const;
    Intset symmetricDifference(const Intset&) const;
    
    bool empty() const{return beg==0;}    
    void print() const;
private:
    Node *beg,*end;
};
Intset::~Intset()
{
Node* p=beg;
while(p){
Node* victim=p;
p=p->next;
delete victim;
}
}
bool Intset::push(int ival)
{
Node* pfind=find(ival);
if(pfind) return false;

Node* pn=new Node(ival);
    if(empty())
        beg=end=pn;
    else{
    end->next=pn;//核心语句:把pn链入Intset 
    end=pn;      //让旧尾元素的next指针指向新尾元素,同时使end指向新尾元素。 
    }
}
void Intset::del(Node* ptr)
{
    Node* p=beg;
    while(p!=ptr&&p&&p->next!=ptr)
        p=p->next;
    if(p){
    if(p==ptr){//要删除的是第一个元素 
    beg=beg->next;
    }else if(ptr==end){
            end=p;
            end->next=0;
   }else{
    p->next=ptr->next;
    }
    delete ptr;
    }else throw std::out_of_range("no such element");
}
Node* Intset::find(int ival) const
{
Node* p=beg;
while(p&&p->i!=ival) p=p->next;
return p;
}
Intset Intset::setUnion(const Intset& rhs) const
{
Intset ret;
    for(Node* p=beg;p;p=p->next)
        ret.push(p->i);
    for(Node* p=rhs.beg;p;p=p->next)
        ret.push(p->i);
    return ret;
}
Intset Intset::intersect(const Intset& rhs) const
{
Intset ret;
for(Node* p=beg;p;p=p->next)
   if(rhs.find(p->i))
       ret.push(p->i);
    return ret;
}
Intset Intset::symmetricDifference(const Intset& rhs) const
{
Intset ret;
for(Node* p=beg;p;p=p->next)
   if(!rhs.find(p->i))
       ret.push(p->i);
    for(Node* p=rhs.beg;p;p=p->next)
   if(!find(p->i))
       ret.push(p->i);//不会导致重复:push()会检查重复性 
    return ret;
}
void Intset::print() const
{
for(Node* p=beg;p;p=p->next)
   std::cout<<p->i<<'\t';
    std::cout<<std::endl;
}
int main()
{
Intset a,b;
    a.push(1);
    a.push(2);
    a.push(3);
    a.print();
    if(Node* p2=a.find(2))
        a.del(p2);
    a.print();
    b.push(3);
    b.print();
    a.setUnion(b).print();
    a.intersect(b).print();
    a.symmetricDifference(b).print();
return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值