(入门自用)C++--list--list的模拟实现--0917

list

相关功能

头文件

#include <iostream>

#include <list>

迭代器的相关函数find insert earse

find函数包含于 头文件<algorithm>

#include <iostream>
#include <list>
using namespace std;
int main()
{
    list<int> l1;
    for(int i=1;i<=5;i++)
    {
        l1.push_back(i);
    }
    auto pos=find(l1.begin(),l1.end(),3);//找到返回3的pos 找不到返回end()
    if(pos!=l1.end())
    {
        l1.insert(30);
        l1.insert(40);//链表插入不会出现迭代器失效问题 开新空间但pos指向位置始终不变
        //也可以修改
    }
    if(pos!=l1.end())
    {
        l1.earse(pos);//不判断就删除会报错
        //earse不能连续使用,pos所指向位置已经不在链表内
    }
    return 0;

}

splice 转移

void splice(literator postion,List&x);//把x链表内容转移到pos位置

#include <iostream>
#include <list>
using namespace std;
int main()
{
    list<int> l1,l2;
    for(int i=1;i<=4;i++)
    {
        l1.push_back(i);// l1  1 2 3 4
    }
    for(int j=1;j<=3;j++)
    {
        l2.push_back(j*10);// l2  10 20 30
    }
    list<int>::iterator it=l1.begin();
    ++it;
    l1.splice(it,l2);// 1 10 20 30 2 3 4
    //l2称为空链表
    return 0;
}

remove 消除某个值

list<int> l1;//1 2 3 3 4 5 9 3 1

l1.remove(3);// 1 2 4 5 9 1

clear 清空链表

l1.clear();

sort 排序

库里面也有一个sort();函数

sort(l1.begin(), l1.end());//这里会报错 而且报在库里面的sort函数。

原因是库里面的sort函数底层是快排,而list存储空间不连续不能取中无法调用。

l1.sort();//底层是归并排序

注意:用list排序,不如把数据拷到vector排序完毕再拷回来。

unique 去掉重复的

使用前需要先排序

l1.sort();// 1 1 2 3 3 3 4 5 9

l1.unique();// 1 2 3 4 5 9

list的模拟实现

#pragma once
namespace chy
{
    //结点结构体
    template<class T>
    stuct list_node    
    {
        T _data;
        list_node<T>* _prev;
        list_node<T>* _next;
        //list_node的构造函数
        list_node(const T& x= T() )  //用T类型的匿名对象初始化
            :_data(x)                //T是什么类型就去调什么类型的构造函数
            ,_prev(nullptr)
            ,_next(nullptr)
        {}                            
    };

    //链表
    template<class T>
    class List
    {
        typedef list_node<T> Node;
    public:
        //构造函数
        List()
        {
            _head= new Node;
            _head->_next=_head;
            _head->_prev=_head;
        }
        //功能函数
        // ....
    private:
        Node* _head; 
    };
    
    //迭代器
    //{...}
}

迭代器的模拟实现

template class<T>
//迭代器像指针一样
struct list_iterator
{
    typedef list_node<T> Node;
    Node* _node;
    typedef list_iterator<T> iterator;
    iterator(Node* node)
        :_node(node)
    {}
    
    //实现迭代器功能
    // 遍历 
    //++it
    iterator operator++()
    {
        _node=_node->next;
        return *this;
    }
    //it ++
    iterator operator++(int) //无需传参 只是区分
    {
       iterator tmp(*this);//创建一个迭代器类型的tmp
        _node=_node->next;
        return tmp;
    }
    //--it 和 it-- 同理
    
    //解引用
    T& operator*()
    {
        return _node->_data;
    }
    // -> 返回指针类型 即返回结点的地址
    T* operator->()
    {
        return &(operator*());// _data是结构体的成员 他的地址就是结构体的地址
    }
}

->重载的意义

这里为了理解创建一个自定义类

struct pos
{
    int _row;
    int _column;
    pos(int row=0, int column=0)
        :_row(row)
        ,_column(column)
    {}
};
	void test_list2()
	{
		list<Pos> lt;
		lt.push_back(Pos(10, 20));
		lt.push_back(Pos(10, 21));

		list<Pos>::iterator it = lt.begin();
		while (it != lt.end())
		{
			//cout << (*it)._a1 << ":" << (*it)._a2 << endl; *it是pos结构体
			
            cout << it->_a1 << ":" << it->_a2 << endl;
			++it;
		}
		cout << endl;
	}

 

 迭代器和const迭代器

下述迭代器 有权限放大问题。

	void Func(const list<int>& l)
	{
		list<int>::iterator it = l.begin();
		while (it != l.end())
		{
			//*it = 10;

			cout << *it << " ";
			++it;
		}
		cout << endl;
	}

l是被const修饰的,是只读的,而l.begin()和l.end()是可读可写的。普通迭代器和const迭代器的区别就是能不能被修改。

如果T& operator*(){} 将其的返回值改为const T&就可以解决这个问题。

T* operator->()                 const T* operator->()

T& operator*()                  const T& operator*() 

二者仅返回值不同,不能构成函数重载。

方法:

一、在写一个类命名为const_iterator 将里面的T& 改为const T&其他不变

二、使用实例化以区分

#pragma once
namespace chy
{
    //迭代器
	template<class T, class Ref, class Ptr>
	struct list_iterator
    {
        //之前
		//typedef list_node<T> Node;
        //typedef list_iterator<T> iterator;  
         
        //现在
        typedef list_node<T> Node;
		typedef list_iterator<T, Ref, Ptr> iterator;       
		Node* _node;

		list_iterator(Node* node)
			:_node(node)
		{}
    
        bool operator!=(const iterator& x)
        {
            return _node!=x._node;
        }
        bool operator==(const iterator& x)
        {
            return _node==x._node;
        }
    
    	Ref operator*()
		{
			return _node->_data;
		}

		//T* operator->() 
		Ptr operator->()
		{ 
			return &(operator*());
		}
    };  

    //链表
    template<class T>
    class List
    {
        //...
	public:
		typedef list_iterator<T, T&, T*> iterator;
		typedef list_iterator<T, const T&, const T*> const_iterator;
        //相当于 调用const_iterator时 Ref 就是 const T&
                                   //Ptr 就是 conts T*  
        iterator begin()
        {
            //iterator it=_head->next;
            //return it;
            return iterator(_head->next);//匿名对象
        }
        const_iterator begin() const
        {
            return const_iterator(_head->next);
        }
        iterator end()
        {
            return iterator(_head->prev);
        }
        const_iterator end() const
        {
            return const_iterator(_head->prev);
        }
    }; 
}

list的功能实现

析构 拷贝构造 插入 删除

template<class T>	
class list
{
	typedef list_node<T> Node;
public:
	typedef __list_iterator<T, T&, T*> iterator;
	typedef __list_iterator<T, const T&, const T*> const_iterator;

    //无参构造如上 
    stack()
    {
        empty_init();
    }
    void empty_init()
    {
        _head=new Node;
        _head->next=_head;
        _head->prev=_head;
    }
    
    //构造
    template <class Inputiterator>
    stack(Inputiterator begin,Inputiterator end) //这里使用不了初始化列表 
    {                                            //但push会访问而造成报错
        empty_nit();//这个函数需要实现头结点的初始化
        while(begin!=end)
        {
            push(begin);
            begin++;
        }
    }

    //析构
    ~stack()
    {
        //这里复用clear()函数
        //但需要删除头结点
        clear();
        delete _head;
        _head=nullptr;
    }
    
    //清空
    void clear()
    {
        iterator it=begin();
        while(it!=end())
        {
            it=earse(it);//利用删除函数 返回删除位置的下一个位置的迭代器
        }
    }
    
    //拷贝构造 现代写法 需要迭代器支持的构造
    //lt2(lt1)
    list (const list<T>& lt)
    {
        empty_init();
        list<T> tmp=(lt.begin(),it.end())
        std::swap(tmp);
    }

    //赋值运算符重载
    list<T>& operator=(list<T> lt)
    {
        std::swap(lt);
        return *this;   
    }
    

    void push_back(const T& x)
    {
        Node* tail=_head->prev;
        Node* newnode=new Node(x);
        //head tail newnode
        tail->_next=newnode;
        newnode->_prev=tail;
        newnode->_next=_head;
        _head->_prev=newnode;
    }
    void push_front(const T& x)
    {
        insert(begin(),x);
    }
    iterator insert(iterator pos, const T& x)
    {
        Node* cur=pos._node;//pos是迭代器结构体 用.
        Node* prev=cur->_next;
        Node* newnode=new Node(x);
        //cur newnode prev
        cur->_next=newnode;
        newnode-_>prev=cur;
        newnode->_next=prev;
        prev->_prev=newnode;
        return iterator(newnode);
    }
    void pop_back()
    {
        earse(--end());
    }
    void pop_front()
    {
        earse(begin());
    }
    iterator erase(iterator pos)
    {
        assert(pos!=begin());//不删头节点
        Node*cur=pos._node;
        Node*prev=cur->_prev;
        Node*next=cur->_next;
        // prev cur next
        prev->_next=next;
        next->_prev=prev;
        delete cur;
        return iterator(next);
    }
private:
    Node* _head;
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值