(C++)vector & list 的使用和模拟实现_用vector实现list-程序员宅基地

技术标签: C++  c++  迭代器  vector  list  

顺序容器(sequential container)

  • 顺序容器为程序员提供了控制元素储存和访问顺序的能力。
  • 这种顺序不依赖于元素的值,而是与元素加入容器时的位置相对应。

迭代器

  • 提供对对象的间接访问。
  • 使用迭代器可以访问某个元素,迭代器也能从一个元素移动到另外一个元素。
  • 迭代器有 有效和无效之分,
  • 有效的迭代器或指向某个元素,或指向容器中尾元素的下一位置。
  • 其他情况都属于无效。

使用

  • begin(): 负责返回指向第一个元素
  • end():负责返回只想最后一个元素的下一个位置。也就是说,该迭代器指向的是容器一个本不存在的“尾后”(off the end)元素。
  • 特殊情况下,如果容器为空,则begin和end返回的是同一个迭代器。都是尾后迭代器。

vector

特点

  • 可变大小数组。
  • 支持快速随机访问。
  • 在尾部之外的位置插入或删除元素可能很慢。

函数接口

这里写图片描述

使用

代码:

int main()
{
    vector<int>::iterator it;
    vector<int> v1;

    v1.push_back(1);
    v1.push_back(2);
    v1.push_back(3);
    v1.push_back(4);

    for (auto it = v1.begin(); it != v1.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;

    v1.pop_back();
    v1.pop_back();
    v1.pop_back();

    for (auto it = v1.begin(); it != v1.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;

    it = v1.begin();
    it = v1.insert(it, 100);

    for (it = v1.begin(); it != v1.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;

    v1.push_back(12);
    v1.push_back(13);
    v1.push_back(14);
    v1.push_back(15);

    for (it = v1.begin(); it != v1.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;

    it = v1.begin();
    v1.erase(it + 3);

    for (it = v1.begin(); it != v1.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;

    vector<int> v2(3, 30);
    vector<int> v3(6, 60);

    for (it = v2.begin(); it != v2.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;

    for (it = v3.begin(); it != v3.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;

    v2.swap(v3);
    for (it = v2.begin(); it != v2.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;

    for (it = v3.begin(); it != v3.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;

    getchar();
    return 0;
}

运行结果:

这里写图片描述

实现

代码:

#include<iostream>
#include<vector>
#include<list>
#include<assert.h>

using namespace std;

template<class T>
class MyVector
{
public:
    MyVector()
        :_data(NULL)
        , _size(0)
        , _capacity(0)
    {}

    MyVector(const MyVector<T> &s)
    {
        _data = new T[s._size];
        for (size_t i = 0; i < _size; ++i)
        {
            _data[i] = s._data[i];
        }
        _size = s._size;
        _capacity = s._capacity;
    }

    ~MyVector()
    {
        if (_data)
        {
            delete[] _data;
            _data = NULL;
            _size = 0;
            _capacity = 0;
        }
    }

    void PushBack(const T& data)
    {
        CheckCapacity();
        _data[_size++] = data;
    }

    void PopBack()
    {
        assert(_size);
        --_size;
    }

    void Insert(size_t n, const T& data)
    {
        assert(n < _size);
        CheckCapacity();
        T cur = _size - 1;
        for (size_t i = n; i <_size; ++i)
        {
            _data[cur+1] = _data[cur];
            cur--;
        }
        _data[n] = data;
        ++_size;
    }

    void Erase(size_t n)
    {
        assert(n < _size);
        for (size_t i = n-1; i < _size; ++i)
        {
            _data[i] = _data[i + 1];
        }
        --_size;
    }

    void CheckCapacity()
    {
        if (_size == _capacity)
        {
            size_t NewCapacity =_capacity * 2 + 3;
            T* pData = new T[NewCapacity];

            for (size_t i = 0; i < _size; ++i)
            {
                pData[i] = _data[i];
            }

            delete[] _data;
            _data = pData;
            _capacity = NewCapacity;
        }
    }

    void Print()
    {
        assert(_size);
        for (size_t i = 0; i < _size; ++i)
        {
            cout << _data[i] << " ";
        }
        cout << endl;
    }

    void clear()
    {
        _size = 0;
    }

    void Swap(MyVector<T> v)
    {
        swap(_data, v._data);
        swap(_size, v._size);
        swap(_capacity, v._capacity);
    }

    T& operator[](size_t pos)
    {
        assert(pos<_size);
        return _data[pos];
    }

    size_t Size()
    {
        return _size;
    }

    size_t Capacity()
    {
        return _capacity;
    }

    bool Empty()
    {
        return (_size == 0);
    }
private:
    T* _data;
    size_t _size;
    size_t _capacity;
};

测试代码:

int main()
{
    MyVector<int> v1;
    v1.PushBack(1);
    v1.PushBack(2);
    v1.PushBack(3);
    v1.PushBack(4);
    v1.Print();

    v1.PopBack();
    v1.PopBack();
    v1.Print();

    v1.Insert(1, 2);
    v1.Insert(1, 2);
    v1.Insert(1, 2);
    v1.Print();

    v1.Erase(1);
    v1.Erase(1);
    v1.Erase(1);

    v1.Print();


    getchar();
    return 0;
}

运行结果:

这里写图片描述

list

特点

  • 双向链表。
  • 只支持双向顺序访问。
  • 在list中任何位置进行插入/删除操作速度都很快。

函数接口

这里写图片描述

使用

代码

int main()
{
    list<int> l1;
    list<int>::iterator it;

    l1.push_back(1);
    l1.push_back(2);
    l1.push_back(3);
    l1.push_back(4);

    for (auto it = l1.begin(); it != l1.end();++it)
    {
        cout << *it << " ";
    }
    cout << endl;

    l1.pop_front();
    l1.pop_front();


    for (auto it = l1.begin(); it != l1.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;

    it = l1.begin();
    ++it;

    l1.insert(it, 10);
    l1.insert(it, 3, 30);

    for (auto it = l1.begin(); it != l1.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;

    it = l1.begin();
    advance(it,3);
    l1.erase(it);

    for (auto it = l1.begin(); it != l1.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;

    list<int> l2(3, 12);
    list<int> l3(5, 16);

    for (auto it = l2.begin(); it != l2.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;
    for (auto it = l3.begin(); it != l3.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;

    l2.swap(l3);
    for (auto it = l2.begin(); it != l2.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;
    for (auto it = l3.begin(); it != l3.end(); ++it)
    {
        cout << *it << " ";
    }
    cout << endl;

    getchar();
    return 0;
}

运行结果:

这里写图片描述

实现

代码:

#include<iostream>
#include<vector>
#include<list>
#include<assert.h>

using namespace std;

template<class T>
struct ListNode
{
    ListNode(const T& data = T())
    :_pre(NULL)
    , _next(NULL)
    , _data(data)
    {}

    ListNode<T>* _pre;
    ListNode<T>* _next;
    T _data;
};

//迭代器
template<class T, class Ref>
class ListIterator
{
    template<class T>//声明友元函数类
    friend class MyList;

    typedef ListIterator<T, Ref> self;
public:
    ListIterator()
        :_pNode(NULL)
    {}

    ListIterator(ListNode<T>* pNode)
        :_pNode(pNode)
    {}

    Ref operator*()
    {
        return _pNode->_data;
    }

    self& operator++()
    {
        _pNode = _pNode->_next;
        return *this;
    }

    self operator++(int)//后置
    {
        self tmp(*this);
        _pNode = _pNode->_next;
        return tmp;
    }

    self operator--()
    {
        _pNode = _pNode->_pre;
        return *this;
    }

    self& operator--(int)//后置
    {
        self tmp(*this);
        _pNode = _pNode->_pre;
        return tmp;
    }

    bool operator == (const self& s)
    {
        return _pNode == s._pNode;
    }

    bool operator != (const self& s)
    {
        return _pNode != s._pNode;
    }

private:
    ListNode<T>* _pNode;

};

template<class T>
class MyList
{
public:
    typedef ListIterator<T, T&> Iterator;

public:
    Iterator begin()
    {
        return Iterator(_pHead->_next);
    }

    Iterator end()
    {
        return Iterator(_pHead);
    }

    /*Iterator Find(const T& data)
    {
        ListNode<T>* pCur = _pHead->_next;
        while (pCur != _pHead)
        {
            if (data == pCur->_data)
                return Iterator(pCur);
            pCur = pCur->_next;
        }
    }*/

    MyList()
    {
        CreateHead();
    }

    MyList(size_t n, const T& data)
    {
        CreateHead();
        for (size_t = i; i < n; ++i)
        {
            PushBack(data);
        }
    }

    ~MyList()
    {
        Clear();
        delete _pHead;
        _pHead = NULL;
    }

    void Clear()
    {
        ListNode<T>* pCur = _pHead->_next;
        ListNode<T>* pPre = NULL;

        while (pCur != _pHead)
        {
            pPre = pCur;
            pCur = pCur->_next;
            delete pPre;
        }

        _pHead->_next = _pHead;
        _pHead->_pre = _pHead;

    }

    void PushBack(const T& data)
    {
        ListNode<T>* pTail = _pHead->_pre;
        ListNode<T>* pTmp = new ListNode<T>(data);
        pTail->_next = pTmp;
        pTmp->_next = _pHead;
        pTmp->_pre = pTail;
        _pHead->_pre = pTmp;
    }

    void PopBack()
    {
        if (_pHead == _pHead->_next)
        {
            assert(false);
            return;
        }

        ListNode<T>* pTmp = _pHead->_pre;
        pTmp->_pre->_next = _pHead;
        _pHead->_pre = pTmp->_pre;
        delete pTmp;
    }

    void PushFront(const T& data)
    {
        ListNode<T>* pTmp = _pHead->_next;
        ListNode<T>* pNew = new ListNode<T>(data);

        _pHead->_next = pNew;
        pNew->_next = pTmp;
        pTmp->_pre = pNew;
        pNew->_pre = _pHead;
    }

    void PopFront()
    {
        ListNode<T>* pTmp = _pHead->_next;
        _pHead->_next = pTmp->_next;
        pTmp->_next->_pre = _pHead;
        delete pTmp;
    }

    void Insert(const Iterator position, const T& data)
    {
        ListNode<T>* pTmp = _pHead->_next;

        while (pTmp != _pHead)
        {
            if (pTmp->_data == data)
                break;
            pTmp = pTmp->_next;
        }

        ListNode<T>* pNew = new ListNode<T>(data);
        pNew->_next = pTmp->_next;
        pNew->_pre = pTmp;
        pTmp->_next = pNew;
    }

    void Erase(const Iterator position)
    {
        ListNode<T>* pCur = _pHead->_next;

        while (pCur != _pHead)
        {
            if (pCur == position._pNode)
            {
                break;
            }
            pCur = pCur->_next;
        }

        pCur->_pre->_next = pCur->_next;
        pCur->_next->_pre = pCur->_pre;
        delete pCur;
    }

    bool Empty()
    {
        return _pNext->next == _pHead;
    }

    size_t Size() const
    {
        size_t count = 0;
        ListNode<T>* pCur = _pHead->_next;
        while (pCur != _pHead)
        {
            pCur = pCur->_next;
            count++;
        }
        return count;
    }

    void Print()
    {
        ListNode<T>* pTmp = _pHead->_next;
        while (pTmp != _pHead)
        {
            cout <<pTmp->_data<<" ";
            pTmp = pTmp->_next;
        }
        cout << endl;
    }

protected:
    void CreateHead()
    {
        _pHead = new ListNode<T>;
        _pHead->_next = _pHead;
        _pHead->_pre = _pHead;
    }
private:
    ListNode<T>* _pHead;
};

测试代码:

int main()
{
    MyList<int> l1;
    l1.PushBack(1);
    l1.PushBack(2);
    l1.PushBack(3);
    l1.PushBack(4);
    l1.Print();



    l1.PopBack();
    l1.PopBack();
    l1.Print();

    l1.PushFront(10);
    l1.PushFront(20);
    l1.PushFront(30);
    l1.Print();

    l1.PopFront();
    l1.PopFront();
    l1.PopFront();
    l1.PopBack();
    l1.PopBack();

    l1.Print();

    l1.PushBack(10);
    l1.PushBack(20);
    l1.PushBack(30);

    MyList<int>::Iterator it;
    //for (auto it = l1.begin(); it != l1.end(); ++it)
    //{
    //cout << *it << " ";
    //}
    //cout << endl;

    it = l1.begin();
    it++;

    l1.Insert(it, 2);
    l1.Print();

    it = l1.begin();

    l1.Erase(it);
    l1.Print();

    getchar();
    return 0;
}

运行结果:

这里写图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/JS_Evey/article/details/78106910

智能推荐

Spring Batch 之 Sample(XML文件操作)(五)_spring sample xml-程序员宅基地

文章浏览阅读532次。转自:http://www.cnblogs.com/gulvzhe/archive/2011/12/03/2274908.html前篇关于Spring Batch的文章,讲述了Spring Batch 对CSV文件的读写操作。 本文将通过一个完整的实例,与大家一起讨论运用Spring Batch对XML文件的读写操作。实例流程是从一个XML文件中读取商品信息,经过简单的处理,写入另外一_spring sample xml

C# 重写WndProc 拦截 发送 系统消息_c# 父窗体拦截事件-程序员宅基地

文章浏览阅读650次。转自:https://blog.csdn.net/shmily0923/article/details/47291909C# 重写WndProc 拦截 发送 系统消息 + windows消息常量值(1) #region 截获消息 /// 截获消息 处理XP不能关机问题 protected override void WndProc(ref Message messa..._c# 父窗体拦截事件

写入文件D:上课软件\glib-2.0.dll时出错。请确认您有访问该自录的权限。 直接删除vm,内存不用删_写入glib-2.0.dll时出错-程序员宅基地

文章浏览阅读1.1w次,点赞6次,收藏22次。写入文件D:上课软件\glib-2.0.dll时出错。请确认您有访问该自录的权限。 直接删除vm,内存不用删直接点修改,然后然后打开安装包,重新安装就ok啦!这个是我的VM安装包:(内附注册码器)链接:https://pan.baidu.com/s/18WgJTXAu_-5SrXMJqoEeOg提取码:ub2c第一篇博客..._写入glib-2.0.dll时出错

【Java】spring mvc简单项目示例_javaspring,mvc项目案例-程序员宅基地

文章浏览阅读3.1k次。但凡进行java网站开发的人,都有学过spring mvc的开发。下面用一个获取当前时间和时区的简单示例,展现一下怎么用myeclipse 10,来创建一个spring mvc项目。 1.打开MyEclipse-->File-->New-->Web Project,在打开的对话框里面输入Project Name为GetTimeDemo,点击Finis..._javaspring,mvc项目案例

SpringBoot - @Import注解使用详解_springboot import-程序员宅基地

文章浏览阅读3.4k次。通过导入的方式,来实现把实例加入Spring容器中的功能,相当于Spring xml配置文件中的 标签。_springboot import

[tensorflow+pycharm]Skipping registering GPU devices...-程序员宅基地

文章浏览阅读1w次,点赞7次,收藏55次。用Pycharm跑VGG16报了上面的警告,还提示“Skipping registering GPU devices…”,意思是你的代码可以运行,但不使用GPU跑的,而是CPU!心痛啊!明明已经配置了tensorflow、cuda等等,看来还是没有配置好,那就继续配置吧!发现问题还是自己的tensorflow版本和cuda版本不对应导致的,查看电脑的显卡驱动版本,和cuda版本解决问题1 打开控制面板,点击“硬件和声音”2 点击“DVIDIA控制面板”3 点击“系统信息”4 在这里可以._skipping registering gpu devices...

随便推点

.repo/repo/main.py“, line 79 file=sys.stderr) SyntaxError: invalid syntax_file=sys.stderr) ^ syntaxerror: invalid syntax-程序员宅基地

文章浏览阅读7.4k次。.repo/repo/main.py", line 79 file=sys.stderr) SyntaxError: invalid syntax_file=sys.stderr) ^ syntaxerror: invalid syntax

【数据结构与算法】内部排序之三:堆排序(含完整源码)_堆排序原码-程序员宅基地

文章浏览阅读320次。转载请注明出处:http://blog.csdn.net/ns_code/article/details/20227303前言 堆排序、快速排序、归并排序(下篇会写这两种排序算法)的平均时间复杂度都为O(n*logn)。要弄清楚堆排序,就要先了解下二叉堆这种数据结构。本文不打算完全讲述二叉堆的所有操作,而是着重讲述堆排序中要用到的操作。比如我们建堆的时候可以采用堆_堆排序原码

0x00007FFEB5D49149 处(位于 Project1.exe 中)有未经处理的异常: Microsoft C++ 异常: cv::Exception,位于内存位置 0x00000060CB_0x00007ff6c1afb01f 处有未经处理的异常(在 project1.exe 中): 0x-程序员宅基地

文章浏览阅读3.6w次,点赞2次,收藏15次。程序编译通过,跑程序时,跑到读图模块突然不正常了,昨天还好好的。程序debug原因如上截图,真心请教有调试经验的大神!感谢!_0x00007ff6c1afb01f 处有未经处理的异常(在 project1.exe 中): 0xc000001d: illeg

错误解决ModuleNotFoundError: No module named ‘imutils‘_modulenotfounderror: no module named 'imutils-程序员宅基地

文章浏览阅读5.4k次,点赞3次,收藏7次。ModuleNotFoundError: No module named 'imutils’解决办法:打开cmd激活你的环境:activate tensorflow安装: pip install imutils安装完成!_modulenotfounderror: no module named 'imutils

插件系列 => 时间格式化 DayJs 多少时间之前_vant4 dayjs-程序员宅基地

文章浏览阅读693次,点赞2次,收藏3次。1.创建timeFilter.js文件import Vue from 'vue';import dayjs from 'dayjs';import 'dayjs/locale/zh-cn';import relativeTime from 'dayjs/plugin/relativeTime';dayjs.extend(relativeTime);dayjs.locale('zh-cn');// 全局过滤器:处理相对时间Vue.filter('relativeTime', (value)_vant4 dayjs

查看Linux磁盘及内存占用情况_linux占用-程序员宅基地

文章浏览阅读10w+次,点赞54次,收藏333次。查看磁盘使用情况: df -k:以KB为单位显示磁盘使用量和占用率 df -m:以Mb为单位显示磁盘使用量和占用率 df –help:查看更多df命令及使用方法 查看内存占用情况: 1.top PID:当前运行进程的ID USER:进程属主 PR:每个进程的优先级别 NInice:反应一个进程“优先级”状态的值,其取值范围是-20至19,一     共40个级别。这个值_linux占用

推荐文章

热门文章

相关标签