(C++初阶) list的基本使用与模拟实现

目录

一 知识点总结

二 list的基本使用

1.list遍历方式

2.list排序(不推荐)

3.list数据操作

三 list 模拟实现

1 List.h

2 List.cpp


一 知识点总结

1.原生指针可以当做天然迭代器使用。其实vector/string 的迭代器就是原生指针。但是,如list物理空间不连续的容器,使用原生指针就已经无法完成迭代器的功能了,所以就需要用迭代器去封装list的节点指针node*,重载这个类的* ++ 等运算符,去模拟指针的访问行为。

2.迭代器的作用:可以让我们不用在意容器的底层结构到底是数组、链表、树型结构等等,封装隐藏了底层的细节,让我们可以用简单统一的方式去访问修改容器。

3.常见容器的的迭代器分为三种:①单向(++) forwora_list  ②双向:(++/--) list ③随机:(++/--/+/-)vector/string

4.算法实现的函数模板,理论而言,是通用的,传什么容器的迭代器都可以,但是算法中可能用不同的迭代器操作,具体就要看传的迭代器是否支持,也就是说,还是有要求。

5.list 节点的指针原生行为不满足迭代器定义。通过类去封装节点的指针,重载运算法来控制。

二 list的基本使用

1.list遍历方式

//list遍历方式 迭代器 范围for
//g++ test_list1.cpp -std=C++11 

//打印list
void print(const list& lt)
{
	auto it = lt.begin();
	//list::const_iterator it = lt.begin();
	while (it != lt.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
}

//通用的容器打印函数。
template
void PrintContainer(const Con& c)
{
	typename Con::const_iterator it = c.begin();
	while (it != c.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
}

void test_list1()
{
	list lt1;
	lt1.push_back(1);
	lt1.push_back(2);
	lt1.push_back(3);
	lt1.push_back(4);
	print(lt1);

	int a[] = { 1,5,8,9 };
	list lt2(a,a+4);
	print(lt2);
}

2.list排序(不推荐)

//list排序
void sort_test()
{
	int a[] = { 9,5,8,9 };
	list lt1(a, a + 4);
	print(lt1);
	vector v1(a, a + 4);

	// < 升序 默认
	// > 降序 
	sort(v1.begin(), v1.end());//升序
	//sort(v1.begin(), v1.end(), greater());//降序

	//sort的底层使用的是快速排序,快速排序要求容器迭代器必须是随机迭代器。
	//比如:快排要三数取中优化,不支持随机访问,效率就不够了。
	//sort(lt1.begin(), lt1.end());//不支持

	//不建议用,效率低。
	//lt1.sort(); //默认升序
	lt1.sort(greater()); //降序
	print(lt1);

}

3.list数据操作

//数据操作
void test_list2()
{
	list lt1 = { 1,2,3,50,50,50,49,50,50,50 };
	//cout << lt1.max_size();
	PrintContainer(lt1);

	//lt1.assign(2, 10);//assign 将list中数据覆盖清除
	//PrintContainer(lt1);

	//vector的insert 会导致pos失效,但是list不会。
	list::iterator pos = find(lt1.begin(), lt1.end(), 50);
	lt1.insert(pos, 1000);
	lt1.insert(pos, 9999);
	PrintContainer(lt1);

	//erase会导致list的pos失效
	lt1.erase(pos);
	PrintContainer(lt1);

	lt1.remove(1000);//找到就删除
	PrintContainer(lt1);
	lt1.remove(100000); //没找到就不做处理
	PrintContainer(lt1);

	//去重复
	lt1.unique();
	PrintContainer(lt1);
	//配合排序,才能真正去重
	lt1.sort();//归并,一般情况下,不建议使用链表排序,效率不高。
	lt1.unique();
	PrintContainer(lt1);

	//逆置
	lt1.reverse();
	PrintContainer(lt1);
}

三 list 模拟实现

1 List.h

#pragma once
#include
#include
#include
using namespace std;

namespace zsd
{
	//结点
	template
	struct _list_node
	{
		T _val;
		_list_node* _next;
		_list_node* _prev;

		_list_node(const T& val=T())
			:_val(val)
			,_prev(nullptr)
			,_next(nullptr)
		{}
	};

	//迭代器
	// typedef _list_iterartor iterator;
	// typedef _list_iterartor const_iterator;
	template
	struct _list_iterator 
	{
		typedef _list_node node;
		typedef _list_iterator self;

		node* _pnode;

		_list_iterator(node* pnode)
			:_pnode(pnode)
		{}

		// 拷贝构造、operator=、析构我们不写,编译器默认生成就可以用

		Ref operator*()
		{
			return _pnode->_val;
		}

		Ptr operator->()
		{
			return &_pnode->_val;
		}

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

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

		//++it
		self& operator++()
		{
			_pnode = _pnode->_next;
			return *this;
		}
		//it++
		self operator++(int)
		{
			self tmp(*this); 
			_pnode = _pnode->_next;
			return tmp; //返回操作前的
		}
		//--it
		self& operator--()
		{
			_pnode = _pnode->_prev;
			return *this;
		}
		//it--
		self operator--(int)
		{
			self tmp(*this);
			_pnode = _pnode->_prev;
			return tmp;
		}
	};
	
	//链表
	template
	class list
	{
		typedef _list_node node;
	public:
		typedef _list_iterator iterator;
		typedef _list_iterator const_iterator;

		iterator begin()
		{
			return iterator(_head->_next);
		}

		const_iterator begin() const
		{
			return const_iterator(_head->_next);
		}

		iterator end()
		{
			return iterator(_head);
		}

		const_iterator end() const
		{
			return const_iterator(_head);
		}

		list()
		{
			//_head = new node(T()); //构造一个匿名对象 T(),也可以在_list_node的构造函数传参数时赋缺省值
			_head = new node;
			_head->_next = _head;
			_head->_prev = _head;
		}
		//copy(lt)
		list(const list& lt)
		{
			_head = new node;
			_head->_next = _head;
			_head->_prev = _head;
			for (const auto& e : lt)
			{
				push_back(e);
			}
		}
		//copy= lt1 
		list& operator = (list lt)
		{
			swap(_head, lt._head);
			return *this;
		}

		void insert(iterator pos, const T& x)//在指定位置前插入数据
		{
			assert(pos._pnode);
			node* cur = pos._pnode;
			node* prev = cur->_prev;
			node* newnode = new node(x);

			prev->_next = newnode;
			newnode->_prev = prev;
			newnode->_next = cur;
			cur->_prev = newnode;
		}

		iterator erase(iterator pos) //删除指定位置节点
		{
			assert(pos._pnode);
			assert(pos != end());
			node* prev = pos._pnode->_prev;
			node* next = pos._pnode->_next;
			delete pos._pnode;
			prev->_next = next;
			next->_prev = prev;

			return iterator(next);
		}

		void push_back(const T& x)//尾插
		{
			//node* newnode = new node(x);
			//node* tail = _head->_prev;
			//tail->_next = newnode;
			//newnode->_prev = tail;
			//newnode->_next = _head;
			//_head->_prev = newnode;
			insert(end(),x);
		}
		void push_front(const T& x)//头插
		{
			insert(begin(), x);
		}

		void pop_back()//尾删
		{
			erase(--end());
		}
		void pop_front()//头删
		{
			insert(begin());
		}
		bool empty()//是否为空
		{
			return begin() == end();
		}
		size_t size()  //O(N)
		{
			size_t sz=0;
			iterator it = begin();
			while (it != end())
			{
				++sz;
				++it;
			}
		}
		void clear() //删除链表
		{
			iterator it = begin();
			while (it != end())
			{
				erase(it++);
			}
		}
		~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}

	private:
		node* _head;
	};

	void PrintList(const list& lt)
	{
		list::const_iterator it = lt.begin();
		while (it != lt.end())
		{
			// *it += 1;
			cout << *it << " ";
			++it;
		}
		cout << endl;
	}

	//测试1
	void TestList1()
	{
		list lt;
		lt.push_back(1);
		lt.push_back(2);
		lt.push_back(3);
		lt.push_back(4);
		lt.push_front(1);
		lt.push_front(1);
		lt.push_front(1);
		lt.push_front(1);

		PrintList(lt);

		list::iterator it = lt.begin();
		while (it != lt.end())
		{
			*it += 10;
			cout << *it << " ";
			++it;
		}
		cout << endl;

		for (auto e : lt)
		{
			cout << e << " ";
		}
		cout << endl;
	}
	//测试2
	void TestList2()
	{
		list lt;
		lt.push_back(1);
		lt.push_back(2);
		lt.push_front(100);
		lt.push_front(100);
		PrintList(lt);

		list lt1(lt);
		lt1.push_back(1000);
		PrintList(lt1);

		lt.clear();
		PrintList(lt);
	}
}

2 List.cpp


#include"List.h"

int main()
{
	//zsd::TestList1();
	zsd::TestList2();
	return 0;
}

你可能感兴趣的:(C/C++学习笔记,c++)