IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> (入门自用)C++--list--list的模拟实现--0917 -> 正文阅读

[数据结构与算法](入门自用)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;
	}

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

l是被const修饰的,而l.begin()是可读可写的。这就需要实现一个const迭代器,而const迭代器的解引用操作符 ->操作符的重载仅是返回值不同:

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

T& operator*()? ????????????????const T& operator*()? 二者仅返回值不同,不能构成函数重载。

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

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

迭代器和const迭代器

使用实例化以区分

#pragma once
namespace chy
{
    //迭代器
	template<class T, class Ref, class Ptr>
	struct list_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;
};

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-09-24 21:19:25  更:2022-09-24 21:23:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 19:21:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码