一个简易的Set容器

由于临近期末,课都上的差不多了,所以最近多了很多空闲时间来思考和写代码。今天闲的无聊,决定撸一个简易的集合容器练练手。本以为是一件挺简单的事情,可是当完成起来的时候才发现没那么容易。
惯例:先上代码。

//head.h
#ifndef SET_H
#define SET_H_
template<typename T>
class Set {
    struct member {
        T data;
        member * next;
        member() :next(nullptr) {}
    };
    member *head;
    member *current;
public:
    Set() :head(nullptr) {}
    struct iterator {               
        member * ptmember;
        bool operator!=(const iterator & cmp)const
        {
            if (this->ptmember == nullptr&&cmp.ptmember == nullptr)
                return false;
            return (this != &cmp);
        }
        T operator*()
        {
            return this->ptmember->data;
        }
        void operator++()
        {
            this->ptmember = this->ptmember->next;
        }
        void operator--()
        {
            if (ptmember == head)
                return;
            else
            {
                current = head;
                while (current->next != this)
                {
                    current = current->next;
                }
                this->ptmember = current;
            }
        }
    }ptmemtemp;
    typename Set::iterator  begin() { ptmemtemp.ptmember = head; return ptmemtemp; }
    typename Set::iterator  end();
    void push(T x);
    bool find(T x);
    void show();
};
template<typename T>
void Set<T>::push(T x)
{
    if (head == nullptr)
    {
        current = new member;
        current->data = x;
        head = current;
    }
    else if (x < head->data)
    {
        current = new member;
        current->data = x;
        current->next = head;
        head = current;
    }
    else
    {
        current = head;
        while (current->next != nullptr)
        {
            if (current->data == x)
                return;
            if (x < current->next->data)
            {
                member *temp = new member;
                temp->data = x;
                temp->next = current->next;
                current->next = temp;
                return;
            }
            current = current->next;
        }
        if (current->data == x)
            return;
        member *temp=new member;
        temp->data = x;
        current->next= temp;
    }
}
template<typename T>
bool Set<T>::find(T x)
{
    current = head;
    while (current != nullptr)
    {
        if (x == current->data)
        {
            return true;
        }
        current = current->next;
    }
    return false;
}
template<typename T>
void Set<T>::show()
{
    current = head;
    while (current != nullptr)
    {
        cout << current->data << "   ";
        current = current->next;
    }
    cout << endl;
}
template<typename T>
typename Set<T>::iterator Set<T>::end()
{
    current = head;
    while (current != nullptr)
        current = current->next;
    ptmemtemp.ptmember = current;
    return ptmemtemp;
}

#endif
//test.cpp
#include"head.h"
#include<iostream>
#include<cstdlib>
#include<ctime>
using namespace std;
int main()
{
    srand(time(0));
    Set<double> test;
    for (int i = 0; i < 50; ++i)
    {
        double h = rand() % 20;
        test.push(h);
    }
    test.show();
    for (Set<double>::iterator a = test.begin(); a != test.end(); ++a)
    {
        cout << *a << "   ";
    }
    int testnum;
    testnum = rand() % 20;
    cout <<endl<< "testnum is: " << testnum << endl;
    if (test.find(testnum))
        cout << "find it.\n";
    else
        cout << "not find it.\n";

    system("pause");
    return 0;
}

下面就来谈谈我这次写这个容器的艰难的心路历程吧。

一开始准备实现的功能就是插入数字的时候就自动的找到合适的位置插进去(已经有了的数就不插进去了),然后就是通过类似于容器中迭代器一样的东西来遍历Set,最后重载一下!=和++以及– *操作符。(貌似功能也不多(●’◡’●))
到了第二个“迭代器”这个功能的时候就比较麻烦了。一开始想直接通过member实现++和–,所以就写了友元函数来实现这个功能,结果遇到了第一道坎:这里写图片描述
一开始并没有看懂(原谅我见识少(●’◡’●)),请教了一位浙大学长(厚颜无耻的我冒充了浙大学生混进了浙大编程群)。然后加上了typename,因为如果不声明的话编译器并不知道这是什么东西,加上了typename之后编译器才知道这是类型名。
然后准备重载!=。重载!=是为了比较“迭代器”是否相等,关于迭代器我一开始的想法是用member指针来实现。这时候,问题又来了。类中的成员函数和友元函数参数列表不能有指针类型的参数,但是我要传的就是指针啊!于是又厚着脸皮去群里问了问题。大神学长告诉我外包一层iterator,这样一来根本就不用友元函数了,直接在iterator中重载刚才的运算符就行了呀!!!真是excited。
关于上面说的不能传指针,msdn上是这么说的:
***Compiler Error C2803
Visual Studio 2015 Other Versions
‘operator operator’ must have at least one formal parameter of class type
The overloaded operator lacks a parameter of class type.
You need to pass at least one parameter by reference (not using pointers, but references) or by value to be able to write “a < b” (a and b being of type class A).
If both parameters are pointers it will be a pure comparison of pointer addresses and will not use the user-defined conversion.*

然后把++,–,*,!=这些符号全部重载在iterator中,因为本来这些操作符就是对“迭代器”进行的呀。

最后感觉从今天写这个Set容器中学到了不少。

【为什么还需要学习C++?】 你是否接触很多语言,但从来没有了解过编程语言的本质?你是否想成为一名资深开发人员,想开发别人做不了的高性能程序?你是否经常想要窥探大型企业级开发工程的思路,但苦于没有基础只能望洋兴叹? 那么C++就是你个人能力提升,职业之路进阶的不二之选。【课程特色】 1.课程共19大章节,239课时内容,涵盖数据结构、函数、类、指针、标准库全部知识体系。2.带你从知识与思想的层面从0构建C++知识框架,分析大型项目实践思路,为你打下坚实的基础。3.李宁老师结合4大国外顶级C++著作的精华为大家推出的《征服C++11》课程。【学完后我将达到什么水平?】 1.对C++的各个知识能够熟练配置、开发、部署;2.吊打一切关于C++的笔试面试题;3.面向物联网的“嵌入式”和面向大型化的“分布式”开发,掌握职业钥匙,把握行业先机。【面向人群】 1.希望一站式快速入门的C++初学者; 2.希望快速学习 C++、掌握编程要义、修炼内功的开发者; 3.有志于挑战更高级的开发项目,成为资深开发的工程师。 【课程设计】 本课程包含3大模块基础篇本篇主要讲解c++的基础概念,包含数据类型、运算符等基本语法,数组、指针、字符串等基本词法,循环、函数、类等基本句法等。进阶篇本篇主要讲解编程中常用的一些技能,包含类的高级技术、类的继承、编译链接和命名空间等。提升篇:本篇可以帮助学员更加高效的进行c++开发,其中包含类型转换、文件操作、异常处理、代码重用等内容。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值