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

来源:互联网 发布:游戏源码吧 编辑:程序博客网 时间:2024/05/29 14:14

这道习题让我纠结了一整天。在写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;
}

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 遇见碰瓷的人怎么办 遇到老人碰瓷的怎么办 打了碰瓷的怎么办 倒车入库打晚了怎么办 上班停车费太贵怎么办 黄疸回家小孩不爱吃母乳怎么办 黄金棒开关坏了怎么办 在一家莆田系医院上班怎么办 被莆田医院骗了怎么办 痘痘红肿有脓包怎么办 换届选举候选人自动退出竞选怎么办 城管暴力执法导致老百姓受伤怎么办 领导制定方案与政策不一致怎么办 第三方支付存在的金融风险怎么办 貔貅鼻子摔坏了怎么办 貔貅鼻子磕破了怎么办 红警2游戏出错怎么办 猛犸牙上油花了怎么办 吃了细菌的食物怎么办 易拉罐罐头拉环断了怎么办 衣服上有火锅味怎么办 衣服沾上火锅味怎么办 做杨梅罐头里面好多小白虫怎么办 一地两检手续怎么办 剩米饭变干硬了怎么办 吃剩的米饭变硬怎么办 误食发热包的水怎么办 玻璃饭盒加热后盖子打不开怎么办 玻璃饭盒盖子被吸住了怎么办 微波炉加热饭盒盖子打不开怎么办 铁饭盒盖子打不开了怎么办 塑料玻璃饭盒打不开了怎么办 方便火锅没有发热包怎么办 加热包的水溢出怎么办 军用黄脸盆坏了怎么办 白瓷洗手盆发黄怎么办 挎包没有拉链东西容易掉怎么办 斜挎包肩带长了怎么办 3个月宝宝不吃奶怎么办 米饭扔厕所堵了怎么办 门过梁搭接不够怎么办