STL的模拟实现

string的模拟实现

#pragma once
#include<iostream>
#include<string.h>
#include<assert.h>
namespace bit
{
	class string
	{
	public:
		typedef char* iterator;
		typedef const char* const_iterator;
		iterator begin() { return _str; }
		iterator end() { return _str + _size; }
		const_iterator begin()const  { return _str; }
		const_iterator end()const  { return _str + _size; }
		size_t size()const  { return _size; }
		size_t capatity()const { return _capatity; }
		static size_t max_size() { return npos; }
		bool empty()const { return size() == 0; }
		char* c_str()const { return _str; }
		string(const char* str = "")
			:_str(new char[strlen(str) + 1])
			, _size(strlen(str))
			, _capatity(_size)
		{
			strcpy(_str, str);
		}
		void swap(string& s)
		{
			std::swap(_str, s._str);
			std::swap(_size, s._size);
			std::swap(_capatity, s._capatity);
		}
		string(const string& s)
			:_str(nullptr)
			,_size(0)
			,_capatity(0)
		{
			string tmp(s._str);
			swap(tmp);
		}
		string& operator=(string s)
		{
			swap(s);
			return *this;
		}
		~string()
		{
			delete[]_str;
			_str = nullptr;
			_size = _capatity = 0;
		}
		char& operator[](size_t pos)
		{
			assert(pos < _size);
			return *(_str + pos);
		}
		const char& operator[](size_t pos) const
		{
			assert(pos < _size);
			return *(_str + pos);
		}
		void resize(size_t n, const char ch = '\0')
		{
			if (n < _size)
			{
				_str[_size] = '\0';
				_size = n;
			}
			else
			{
				if (n > _capatity)
				{
					reserve(n);
				}
				memset(_str + _size, ch, n - _size);
				_str[_size] = '\0';
				_size = n;
			}
		}
		void reserve(size_t n)
		{
			if (n > _capatity)
			{
				char* tmp = new char[n + 1];
				strcpy(tmp, _str);
				delete[]_str;
				_str = tmp;
				_capatity = n;
			}
		}
		void push_back(const char ch = char())
		{
			if (_size == _capatity)
			{
				reserve(_capatity == 0 ? 4 : 2 * _capatity);
			}
			_str[_size++] = ch;
			_str[_size] = '\0';
		}
		void pop_back()
		{
			assert(!empty());
			_str[--_size] = '\0';
		}
		void append(const char ch)
		{
			push_back(ch);
		}
		void append(const char* str)
		{
			int len = strlen(str);
			if (len + _size > _capatity)
			{
				reserve(len + _size);
			}
			strcpy(_str + _size, str);
			_size += len;
		}
		void append(const string& s)
		{
			append(s._str);
		}
		string& operator+=(const char* str)
		{
			append(str);
			return *this;
		}
		string& operator+=(const char ch)
		{
			push_back(ch);
		}
		void clear()
		{
			_str[0] = '\0';
			_size = 0;
		}
		string& insert(size_t pos,const char ch)
		{
			assert(pos < _size);
			if (_size == _capatity)
			{
				reserve(_capatity == 0 ? 4 : 2 * _capatity);
			}
			size_t end = _size + 1;
			while (end > pos)
			{
				_str[end] = _str[end - 1];
				--end;
			}
			_str[pos] = ch;
			++_size;
			return *this;
		}
		string& insert(size_t pos, const char* str)
		{
			assert(pos < _size);
			int len = strlen(str);
			if (_size + len > _capatity)
			{
				reserve(_size + len);
			}
			size_t end = _size + len;
			while (end > pos)
			{
				_str[end] = _str[end - len];
				--end;
			}
			strncpy(_str + pos, str, len);
			_size += len;
			return *this;
		}
		string& erase(size_t pos = 0, size_t len = npos)
		{
			assert(pos < _size);
			if (pos + len > _size)
			{
				_str[pos] = '\0';
				_size = pos;
			}
			else
			{
				strcpy(_str + pos, _str + pos + len);
				_size -= len;
			}
			return *this;
		}
		size_t find(char c, size_t pos = 0) const
		{
			for (size_t i = 0; i < _size; ++i)
			{
				if (_str[i] == c)
				{
					return i;
				}
			}
			return npos;
		}
		size_t find(const char* str, size_t pos = 0) const
		{
			char* tmp = strstr(_str, str);
			if (tmp == nullptr)
			{
				return npos;
			}
			else
			{
				return tmp - _str;
			}
		}
		
	private:
		char* _str;
		size_t _size;
		size_t _capatity;
		static size_t npos;
	};
	size_t string::npos = -1;


	void string_test1()
	{
		string s1("hello c++");
		string s2(s1);
		string s3 = s2;
		//s3.reserve(100);
		//s3.resize(100);
		//std::cout << s3.size() << std::endl;
		/*for (auto e : s2)
		{
			std::cout << e << " ";
		}*/
		/*s3.pop_back();
		s3.append("my love");
		s3.append(s1);
		s3.clear();*/
		//s3.insert(s3.size() -1, 'x');
		//s3.insert(1, "my love");
		//std::cout<<s3.max_size()<<std::endl;
		s3.erase(0,6);
		for (size_t i = 0; i < s3.size(); ++i)
		{
			std::cout << s3[i] << " ";
		}
		std::cout << std::endl;
	}
}

vector的模拟实现

#pragma once
#include<iostream>
namespace bit
{
	template<class T>
	class vector 
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;
		iterator begin() { return _start; }
		iterator end() { return _finsh; }
		const_iterator begin()const  { return _start; }
		const_iterator end()const  { return _finsh; }
		size_t size()const { return _finsh - _start; }
		size_t capatity()const { return _endfstaoce - _start; }
		size_t empty()const { return size() == 0; }
		vector()
			:_start(nullptr)
			, _finsh(nullptr)
			, _endfstaoce(nullptr)
		{

		}
		template<class InputIterator>
		vector(InputIterator first, InputIterator last)
				:_start(nullptr)
				, _finsh(nullptr)
				, _endfstaoce(nullptr)
		{
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}
		void swap(vector<T>& v)
		{
			std::swap(_start, v._start);
			std::swap(_finsh, v._finsh);
			std::swap(_endfstaoce, v._endfstaoce);
		}
		vector(const vector<T>& v)
			:_start(nullptr)
			, _finsh(nullptr)
			, _endfstaoce(nullptr)
		{
			vector<T> tmp(v.begin(), v.end());
			swap(tmp);
		}
		vector<T>& operator=(vector<T> v)
		{
			swap(v);
			return *this;
		}
		void reserve(size_t n)
		{
			if (n > capatity())
			{
				T* tmp = new T[n];
				size_t sz = size();
				if (_start)
				{
					for (size_t i = 0; i < size(); ++i)
					{
						tmp[i] = _start[i];
					}
					delete[]_start;
				}
				_start = tmp;
				_finsh = _start + sz;
				_endfstaoce = _start + n;

			}
		}
		void resize(size_t n,const T&val = T())
		{
			if (n < size())
			{
				_finsh = _start + n;
			}
			else
			{
				if (n > capatity())
				{
					reserve(n);
				}
				iterator it = _finsh;
				_finsh = _start + n;
				while (it != _finsh)
				{
					*it = val;
					++it;
				}
			}
		}
		void push_back(const T& val = T())
		{
			if (_finsh == _endfstaoce)
			{
				reserve(capatity() == 0 ? 4 : 2 * capatity());
			}
			*_finsh = val;
			++_finsh;
		}
		void pop_back()
		{
			assert(!empty());
			--_finsh;
		}
		void clear()
		{
			_finsh = _start;
		}
		iterator insert(iterator pos,const T& val)
		{
			assert(pos >=_start &&	pos < _finsh);
			if (_finsh == _endfstaoce)
			{
				size_t len = pos - _start;
				reserve(capatity() == 0 ? 4 : 2 * capatity);
				pos = _start + pos;
			}
			*pos = val;
			++_finsh;
			return pos;
		}
		iterator erase(iterator pos)
		{
			assert(pos >= _start && pos < _finsh);
			iterator begin = pos + 1;
			while (begin != _finsh)
			{
				*(begin - 1) = *(begin);
				++begin;
			}
			--_finsh;
			return pos;
		}
		T& operator[](size_t pos)
		{
			assert(pos < size());
			return *(_start + pos);
		}
		T& front()
		{
			return *_start;
		}
		T& back()
		{
			T* tmp = _finsh -1;
			return *tmp;
		}
		~vector()
		{
			_start = _finsh = _endfstaoce = nullptr;
		}
	private:
		T* _start;
		T* _finsh;
		T* _endfstaoce;
	};
	void vectortest1()
	{
		vector<int> v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		v1.push_back(5);
		vector<int> v2(v1);
		vector<int> v3 = v2;
	/*	for (auto e : v3)
		{
			std::cout << e << " ";
		}*/
		std::cout << v3.front() << " " << v3.back() << std::endl;
		for (size_t i = 0; i < v3.size(); ++i)
		{
			std::cout << v3[i] << " ";
		}
		std::cout << std::endl;
	}
}

list模拟实现

#pragma once
#include<iostream>
namespace bit
{
	template<class T>
	struct _list_node
	{
		_list_node(const T&val = T())
			:_next(nullptr)
			,_prev(nullptr)
			, _val(val)
		{

		}
		_list_node<T>* _next;
		_list_node<T>* _prev;
		T _val;
	};
	template<class T, class pef, class ptr> //封装自定义类型的指针成迭代器,强类型,通过重载运算符使用
	class list_iterator
	{
	public:
		typedef _list_node<T> Node;
		typedef list_iterator<T, pef, ptr> self;   //通过模板参数可以解决const对象的迭代器的使用,解决代码的冗余
		list_iterator(Node* node = nullptr) :_node(node) { }


		bool operator!=(const self& val) { return _node != val._node; }
		bool operator==(const self& val) { return _node != val._node; }
		pef& operator*() { return _node->_val; }
		ptr* operator->() { return &_node->_val; }
		self& operator++()
		{
			_node = _node->_next;
			return *this;
		}
		self operator++(int)
		{
			self tmp(*this);
			_node = _node->_next;
			return tmp;
		}
		self& operator--()
		{
			_node = _node->_prev;
			return *this;
		}
		self operator--(int)
		{
			self tmp(*this);
			_node = _node->prev;
			return tmp;
		}
		Node* _node;
	};
	template<class T>
	class list
	{
	public:
		typedef _list_node<T> Node;
		typedef  list_iterator<T, T&, T*> iterator;
		typedef  list_iterator<const T, const T&, const T*> const_iterator;
		iterator begin() { return iterator(_head->_next); }
		iterator end() { return iterator(_head); }
		const_iterator begin()const { return const_iterator(_head->next); }
		const_iterator end()const { return const_iterator(_head); }


		size_t size()
		{
			iterator it = begin();
			int count = 0;
			while (it != end())
			{
				++count;
				++it;
			}
			return count;
		}
		bool empty()
		{
			return _head->_next == _head;
		}
		T& front()const
		{
			return _head->_next->_val;
		}
		T& back()const
		{
			return _head->_prev->_val;
		}
		template<class iterator>
		list(iterator first, iterator last)
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}
		list()
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;
		}
		list(list<T>& val)
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;
			list<T>tmp(val.begin(), val.end());
			std::swap(_head, tmp._head);
		}
		list<T>& operator=(list<T> val)
		{
			std::swap(_head, val._head);
			return *this;
		}
		void push_back(const T & val)
		{
			/*Node* tail = _head->_prev;
			Node* newnode = new Node(val);
			tail->_next = newnode;
			newnode->_prev = tail;
			newnode->_next = _head;
			_head->_prev = newnode;*/
			insert(end(), val);
		}
		void pop_back(const T& val)
		{
			insert(begin(), val);
		}
		void pop_front()
		{
			erase(begin());
		}
		void pop_back()
		{
			erase(--end());
		}
		void resize(size_t n, const T& v = T())
		{
			size_t sz = size();
			for (size_t i = 0; i < n - sz ; ++i)
			{
				push_back(v);
			}
		}
		iterator erase(iterator pos)
		{
			assert(pos != end());
			Node* prev = pos._node->_prev;
			Node* next = pos._node->_next;
			delete pos._node;
			prev->_next = next;
			next->_prev = prev;
			return iterator(next);
		}
		iterator insert(iterator pos, const T& val)
		{
			Node* newnode = new Node(val);
			Node* cur = pos._node;
			Node* prev = cur->_prev;
			prev->_next = newnode;
			newnode->_prev = prev;
			newnode->_next = cur;
			cur->_prev = newnode;
			return iterator(newnode);
		}

		void clear()
		{
			iterator it = begin();
			while (it != end())
			{
				erase(it++);
			}
		}
		~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}
	private:
		Node* _head;
	};
	void listest1()
	{
		list<int> l1;
		l1.push_back(1);
		l1.push_back(2);
		l1.push_back(3);
		l1.push_back(4);
		list<int>l2(l1);
		list<int>l3 = l2;
		//l3.clear();
		//std::cout << l3.size() << std::endl;
		//std::cout << l3.front() <<std::endl;
		//std::cout << l3.back() << std::endl;
		//l3.pop_front();
		//l3.pop_back();
		std::cout << l3.size() << std::endl;
		l3.resize(10,1);
		std::cout << l3.size() << std::endl;
		list<int>::iterator it = l3.begin();
		while (it != l3.end())
		{
			std::cout << *it << " ";
			++it;
		}
		std::cout << std::endl;
	}
}

stack模拟实现

#include<iostream>
#include"vector.h"
namespace bit
{
	template<class T, class Container = vector<T>>
	class stack
	{
	public:
		void push(const T& val)
		{
			_con.push_back(val);
		}
		void pop()
		{
			_con.pop_back();
		}
		bool empty()
		{
			return _con.empty();
		}
		T& top()
		{
			return _con.back();
		}
		size_t size()
		{
			return _con.size();
		}
	private:
		Container _con;
	};
	void TestStack()
	{
		stack<int> st;
		st.push(1);
		st.push(2);
		st.push(3);
		st.push(4);
		st.push(5);
		while (!st.empty())
		{
			std::cout << st.top() << " ";
			st.pop();
		}
		std::cout << std::endl;
	}
}

queue模拟实现

#pragma once
#include<iostream>
#include"list.h"

namespace bit
{
	template<class T , class Container = list<T>>
	class queue
	{
	public:
		void push(const T& val)
		{
			_con.push_back(val);
		}
		void pop()
		{
			_con.pop_front();
		}
		T& front()
		{
			return _con.front();
		}
		T& back()
		{
			return _con.back();
		}
		bool empty()
		{
			return _con.empty();
		}
		size_t size()
		{
			return _con.size();
		}
		
	private:
		Container _con;
	};
	void QueueTest()
	{
		queue<int> q;
		q.push(1);
		q.push(2);
		q.push(3);
		q.push(4);
		q.push(5);
		while (!q.empty())
		{
			std::cout << q.front() << " ";
			q.pop();
		}
	}
}

priortty_queue(优先级队列) 

#pragma once
#include<iostream>
#include"vector.h"
#include<algorithm>
#include<vector>
#include"data.h"

namespace bit
{
	template <class T>
	struct Less  //防函数
	{
		bool operator()(const T &a, const T &b)const 
		{
			return a < b;
		}
	};
	template<>
	struct Less<Data*>
	{
		bool operator()(const Data* a, const  Data* b)const
		{
			return *a < *b;
		}
	};
	template <class T>
	struct Greater
	{
		bool operator()(const T& a, const T& b)const
		{
			return a > b;
		}
	};
	template<>
	struct Greater<Data*>
	{
		bool operator()(const Data* a, const  Data* b)const
		{
			return *a > *b;
		}
	};
	template <class T, class Container = vector<T>, class Compare = Less<T>> //默认Less是大堆
	class priorirty_queue
	{
	private:
		void AdJustUp(int child)
		{
			Compare com;
			int parent = (child - 1) / 2;
			while (child > 0)
			{
				//if (_con[parent] < _con[child])
			   if(com(_con[parent],_con[child]))
				{
					std::swap(_con[parent], _con[child]);
					child = parent;
					parent = (child - 1) / 2;
				}
				else
				{
					break;
				}
			}
		}
		void AdjustDown(int parent)
		{
			Compare com;
			int child = 2 * parent + 1;
			while (child < _con.size())
			{
				//if (child + 1 < _con.size() && _con[child] > _con[parent])
				if(child + 1 < _con.size() && com(_con[child], _con[child + 1]))
				{
					++child;
				}
				if (com(_con[parent],_con[child]))
			  //if(com(_con[child], _con[child + 1]))
				{
					std::swap(_con[child], _con[parent]);
					parent = child;
					child = 2 * parent + 1;
				}
				else
				{
					break;
				}
			}
		}
	public:
		priorirty_queue() :_con(){};
		template <class iterator>
		priorirty_queue(iterator frist, iterator last)
			:_con( frist, last)
		{
			for (int i = (_con.size() - 1 - 1) / 2; i >= 0; --i)
			{
				AdjustDown(i);
			}
		}
		void push(const T & val)
		{
			_con.push_back(val);
			AdJustUp(_con.size() -1);
		}
		void pop()
		{
			if (empty()) return;
			std::swap(_con.front(), _con.back());
			_con.pop_back();
			AdjustDown(0);
		}
		 T& top()
		{
			return _con.front();
		}
		bool empty() const 
		{
			return _con.empty();
		}
		size_t size() const 
		{
			_con.size();
		}
	private:
		Container _con;
	};


	void priority_queue_test()
	{
		//priorirty_queue<int> pq;
		//pq.push(1);
		//pq.push(2);
		//pq.push(9);
		//pq.push(3);
		//pq.push(5);
		priorirty_queue<Data*> pq;
		pq.push(new Data(2021, 4, 19));
		pq.push(new Data(2020, 4, 19));
		pq.push(new Data(2022, 4, 19));
		while (!pq.empty())
		{
			std::cout << *pq.top();
			pq.pop();
		}
	}
}

AVL树

#pragma once
#include<iostream>
#include<stack>
#include<assert.h>
#define NUM 0
namespace bit
{

	template<class K, class V>
	class AVLTreeNode
	{
	public:
		AVLTreeNode(const std::pair<K, V> kv = std::pair<K, V>())
			:_left(nullptr)
			, _right(nullptr)
			, _parent(nullptr)
			, _kv(kv)
			, _bf(NUM)
		{

		}
		AVLTreeNode<K, V>* _left;
		AVLTreeNode<K, V>* _right;
		AVLTreeNode<K, V>* _parent;
		std::pair<K, V> _kv;
		int _bf; //balance number
	};
	template<class K, class V>
	class AVLTree
	{
	public:
		typedef AVLTreeNode<K, V> Node;
		AVLTree() :_root(nullptr)
		{

		}
		bool insert(const std::pair<K, V>& kv)
		{
			if (_root == nullptr)
			{
				_root = new Node(kv);
				return true;
			}
			Node* parent = nullptr;
			Node* cur = _root;
			while (cur != nullptr)   // 找到插入的位置
			{
				if (kv.first > cur->_kv.first)
				{
					parent = cur;
					cur = cur->_right;
				}
				else if (kv.first < cur->_kv.first)
				{
					parent = cur;
					cur = cur->_left;
				}
				else
				{
					return false;
				}
			}
			//申请新节点插入在AVL中
			cur = new Node(kv);
			if (kv.first > parent->_kv.first)
			{
				parent->_right = cur;
			}
			else
			{
				parent->_left = cur;
			}
			//更新平衡因子
			while (parent != nullptr)
			{
				if (cur == parent->_right)  //比他大平衡因子加加
				{
					parent->_bf++;
				}
				else
				{
					parent->_bf--;   //比他小平衡因子减减
				}
				if (parent->_bf == 0)
				{
					break;        //不需要更新了,跳出循环
				}
				else if (parent->_bf == 1 || parent->_bf == -1)  //继续往上跟新
				{
					cur = parent;
					parent = parent->_parent;
				}
				else if (parent->_bf == 2 || parent->_bf == -2) //旋转
				{
					if (parent->_bf == 2 && cur->_bf == 1) //右单旋
					{
						RotateR(parent);
					}
					else if (parent->_bf == -2 && cur->_bf == -1) //左单旋
					{
						RotateL(parent);
					}
					else if (parent->_bf == 2 && cur->_bf == -1)  //右左单旋(右单选 + 左单旋)
					{
						RotateRL(parent);
					}
					else if (parent->_bf == -2 && cur->_bf == 1) //左右单旋(左单旋 + 右单旋)
					{
						RotateLR(parent);
					}
					else
					{
						assert(false);
					}
					break;
				}
				else
				{
					assert(false);
				}
				return true;
			}
		}
	private:
		void RotateL(Node* parent)
		{
			Node* subR = parent->_right;
			Node* subRL = subR->_left;

			parent->_right = subRL;
			if (subRL)
			{
				subRL->_parent = parent;
			}

			Node* parentParent = parent->_parent;
			subR->_left = parent;
			parent->_parent = subR;

			if (_root == parent)
			{
				_root = subR;
				subR->_parent = nullptr;
			}
			else
			{
				if (parentParent->_left == parent)
					parentParent->_left = subR;
				else
					parentParent->_right = subR;
				subR->_parent = parentParent;
			}
		}

		void RotateR(Node* parent)
		{
			Node* subL = parent->_left;
			Node* subLR = subL->_right;

			parent->_left = subLR;
			if (subLR)
				subLR->_parent = parent;

			Node* parentParent = parent->_parent;

			subL->_right = parent;
			parent->_parent = subL;

			if (parent == _root)
			{
				_root = subL;
				_root->_parent = nullptr;
			}
			else
			{
				if (parentParent->_left == parent)
					parentParent->_left = subL;
				else
					parentParent->_right = subL;

				subL->_parent = parentParent;
			}
		}
		void RotateRL(Node* parent)  //右单旋 + 左单旋
		{
			Node* subR = parent->_right;
			Node* subRL = subR->_left;
			int bf = subRL->_bf;
			RotateR(parent->_right);
			RotateL(parent);
			if (bf == 0)
			{
				parent->_bf = 0;
				subR->_bf = 0;
				subRL->_bf = 0;
			}
			else if (bf == 1)  //在右边插入
			{
				parent->_bf = -1;
				subR->_bf = 0;
				subRL->_bf = 0;
			}
			else if (bf == -1) //在左边插入
			{
				subR->_bf = 1;
				parent->_bf = 0;
				subRL->_bf = 0;
			}
			else
			{
				assert(false);
			}
		}
		void RotateLR(Node* parent) //左单旋 + 右单旋
		{
			Node* subL = parent->_left;
			Node* subLR = subL->_right;
			int bf = subLR->_bf;
			RotateL(parent->_left);
			RotateR(parent);
			if (bf == 0)
			{
				parent->_bf = 0;
				subL->_bf = 0;
				subLR->_bf = 0;
			}
			else if (bf == 1)  //在右边插入
			{
				subL->_bf = -1;
				parent->_bf = 0;
				subLR->_bf = 0;
			}
			else if (bf == -1)  //在左边插入
			{
				parent->_bf = 1;
				subL->_bf = 0;
				subLR->_bf = 0;
			}
			else
			{
				assert(false);
			}
		}
	public:
		void inoder()
		{
			std::stack<Node*> st;
			Node* cur = _root;
			while (cur != nullptr || !st.empty())
			{
				while (cur != nullptr)
				{
					st.push(cur);
					cur = cur->_left;
				}
				Node* top = st.top();
				std::cout << top->_kv.first << ":" << top->_kv.second << std::endl;
				st.pop();
				cur = top->_right;
			}
			/*
			Node* cur = _root;
			Node* MostRight = nullptr;
			while (cur != nullptr)
			{
				MostRight = cur->_left;
				if (MostRight != nullptr)
				{
					while (MostRight->_right != nullptr && MostRight->_right != cur)
					{
						MostRight = MostRight->_right;
					}
					if (MostRight->_right == nullptr)
					{
						MostRight->_right = cur;
						cur = cur->_left;
						continue;
					}
					else
					{
						MostRight->_right = nullptr;
					}
				}
				std::cout << cur->_kv.first << ":" << cur->_kv.second << std::endl;
				cur = cur->_right;
			}
			*/
		}
	private:
		Node* _root;
	};
}

红黑树

#pragma once
#include<iostream>
namespace bit
{
	enum Colour
	{
		RED,
		BALCK
	};
	template<class K,class V>
	class RBTreeNode
	{
	public:
		RBTreeNode(const std::pair<K, V>& kv)
			:_left(nullptr)
			,_right(nullptr)
			,_parent(nullptr)
			,_kv(kv)
			,_col(RED)
		{

		}
		RBTreeNode<K, V>* _left;
		RBTreeNode<K, V>* _right;
		RBTreeNode<K, V>* _parent;
		std::pair<K, V> _kv;
		Colour _col;
	};
	template<class K, class V>
	class RBTree
	{
		typedef RBTreeNode<K, V> Node;
	public:
		RBTree()
			:_root(nullptr)
		{
		}
		bool insert(const std::pair<K, V>& kv)
		{
			if (_root == nullptr)
			{
				_root = new Node(kv);
				_root->_col = BALCK;
				return true;
			}
			Node* parent = nullptr;
			Node* cur = _root;
			while (cur != nullptr)
			{
				if (kv.first > cur->_kv.first)
				{
					parent = cur;
					cur = cur->_right;
				}
				else if (kv.first < cur->_kv.first)
				{
					parent = cur;
					cur = cur->_left;
				}
				else
				{
					return false;
				}
			}
			//申请节点
			cur = new Node(kv);
			cur->_col = RED;
			if (kv.first > parent->_kv.first)
			{
				parent->_right = cur;
				cur->_parent = parent;
			}
			else
			{
				parent->_left = cur;
				cur->_parent = cur;
			}
			//当parent存在且parent 的颜色为红
			while (parent != nullptr && parent->_col == RED)
			{
				Node* grandfather = parent->_parent;
				if (parent == grandfather->_left)
				{
					Node* uncle = grandfather->_right;
					//情况1,uncle存在且为红
					if (uncle != nullptr && uncle->_col == RED)
					{
						parent->_col = uncle->_col = BALCK;
						grandfather->_col = RED;

						cur = grandfather;
						parent = cur->_parent;
					}
					else  //情况2 + 3-> uncle不存在或者存在且为黑
					{
						if (cur == parent->_left)
						{
							RotateR(grandfather);
							parent->_col = BALCK;
							grandfather->_col = RED;
						}
						else
						{
							RotateL(parent);
							RotateR(grandfather);
							cur->_col = BALCK;
							grandfather->_col = BALCK;
						}
						break;
					}
				}
				else
				{
					Node* uncle = grandfather->_left;
					//情况1,uncle存在且为红
					if (uncle != nullptr && uncle->_col == RED)
					{
						parent->_col = uncle->_col = BALCK;
						grandfather->_col = RED;

						cur = grandfather;
						parent = cur->_parent;
					}
					else  //情况2 + 3-> uncle不存在或者存在且为黑
					{
						if (cur == parent->_right)
						{
							RotateL(grandfather);
							parent->_col = BALCK;
							grandfather->_col = RED;
						}
						else
						{
							RotateR(parent);
							RotateL(grandfather);
							cur->_col = BALCK;
							grandfather->_col = BALCK;
						}
					}
					break;
				}
			}
			_root->_col = BALCK;
			return true;
		}
	private:
		void RotateR(Node* parent)
		{
			Node* subL = parent->_left;
			Node* subLR = subL->_left;
			Node* parentparent = parent->_parent;

			parent->_left = subLR;
			if (subLR != nullptr)
				subLR->_parent = parent;
			subL->_right = parent;
			parent->_parent = subL;
			if (parent == _root)
			{
				_root = subL;
				subL->_parent = nullptr;
			}
			else
			{
				if (parentparent->_left == parent)
					parentparent->_left = subL;
				else
					parentparent->_right = subL;
			}
		}
		void RotateL(Node* parent)
		{
			Node* subR = parent->_right;
			Node* subRL = subR->_left;
			Node* parentparent = parent->_parent;

			parent->_right = subRL;
			if (subRL != nullptr)
			{
				subRL->_parent = parent;
			}
			parent->_parent = subR;
			if (parent == _root)
			{
				_root = subR;
				subR->_parent = nullptr;
			}
			else
			{
				if (parentparent->_left == parent)
					parentparent->_left = subR;
				else
					parent->_right = subR;
			}
		}
	public:
		void inoder()
		{
			Node* cur = _root;
			Node* MostRight = nullptr;
			while (cur != nullptr)
			{
				MostRight = cur->_left;
				if (MostRight != nullptr)
				{
					while (MostRight->_right != nullptr && MostRight->_right != cur)
					{
						MostRight = MostRight->_right;
					}
					if (MostRight->_right == nullptr)
					{
						MostRight->_right = cur;
						cur = cur->_left;
						continue;
					}
					else
					{
						MostRight->_right = nullptr;
					}
				}
				std::cout << cur->_kv.first << ": " << cur->_kv.second << std::endl;
				cur = cur->_right;
			}
		}
	private:
		Node* _root;
	};
}

红黑树封装map和set

#pragma once
#pragma once
#include<iostream>
namespace bit
{
	enum Colour
	{
		RED,
		BALCK
	};
	template<class T>
	class RBTreeNode
	{
	public:
		RBTreeNode(const T& data)
			:_left(nullptr)
			, _right(nullptr)
			, _parent(nullptr)
			, _data(data)
			, _col(RED)
		{

		}
		RBTreeNode<T>* _left;
		RBTreeNode<T>* _right;
		RBTreeNode<T>* _parent;
		T _data;
		Colour _col;
	};
	template<class T,class Ref,class Ptr>
	class RBTreeIterator
	{
		typedef RBTreeNode<T> Node;
		typedef RBTreeIterator<T, Ref, Ptr> Self;
	public:
		RBTreeIterator(Node* node)
			:_node(node)
		{

		}
		Ref operator*()
		{
			return _node->_data;
		}
		Ptr operator->()
		{
			return &_node->_data;
		}
		Self& operator++()
		{
			if (_node->_right != nullptr)
			{
				Node* min = _node->_right;
				while (min != nullptr && min->_left != nullptr)
				{
					min = min->_left;
				}
				_node = min;
			}
			else
			{
				Node* cur = _node;
				Node* parent = cur->_parent;
				while (parent != nullptr && cur == parent->_right)
				{
					cur = cur->_parent;
					parent = parent->_parent;
				}
				_node = parent;
			}
			return *this;
		}
		Self& operator--()
		{
			if (_node->_left != nullptr)
			{
				Node* max = _node->_left;
				while (max->_right != nullptr)
				{
					max = max->_right;
				}
				_node = max;
			}
			else
			{
				Node* cur = _node;
				Node* parent = cur->_parent;
				while (parent != nullptr && cur == parent->_left)
				{
					cur = parent;
					parent = parent->_parent;
				}
				_node = parent;
			}
			return *this;
		}
		bool operator !=(const Self& s) const 
		{
			return _node != s._node;
		}
		bool operator==(const Self& s) const 
		{
			return _node == s._node;
		}
	private:
		Node* _node;
	};

	template<class K, class T,class KeyOfT>
	class RBTree
	{
	public:
		typedef RBTreeNode<T> Node;
		typedef RBTreeIterator<T, T&, T*> iterator;
		typedef RBTreeIterator<T, const T&, const T*> const_iterator;
	public:
		RBTree()
			:_root(nullptr)
		{

		}
		RBTree(const RBTree<K, T, KeyOfT>& t)
		{
			_root = Copy(t._root);
		}
		RBTree<K, T, KeyOfT>& operator=(RBTree<K, T, KeyOfT> t)
		{
			std::swap(_root, t._root);
			return *this;
		}
		~RBTree()
		{
			Destroy(_root);
			_root = nullptr;
		}
		iterator begin()
		{
			Node* min = _root;
			while (min != nullptr && min->_left != nullptr)
			{
				min = min->_left;
			}
			return iterator(min);
		}
		iterator end()
		{
			return iterator(nullptr);
		}
		iterator find(const K& key)
		{
			Node* cur = _root;
			if (key > kot(cur->_data))
			{
				cur = cur->_right;
			}
			else if (key < kot(cur->_data))
			{
				cur = cur->_left;
			}
			else
			{
				return iterator(cur);
			}
		}
		std::pair<iterator,bool> insert(const T& data)
		{
			if (_root == nullptr)
			{
				_root = new Node(data);
				_root->_col = BALCK;
				return std::make_pair(iterator(_root),true);
			}
			KeyOfT kot;
			Node* parent = nullptr;
			Node* cur = _root;
			while (cur != nullptr)
			{
				if (kot(data) > kot(cur->_data))
				{
					parent = cur;
					cur = cur->_right;
				}
				else if (kot(data) < kot(cur->_data))
				{
					parent = cur;
					cur = cur->_left;
				}
				else
				{
					return std::make_pair(iterator(cur),false);
				}
			}
			//申请节点
			cur = new Node(data);
			Node* newnode = cur;
			cur->_col = RED;
			if (kot(data) > kot(parent->_data))
			{
				parent->_right = cur;
				cur->_parent = parent;
			}
			else
			{
				parent->_left = cur;
				cur->_parent = parent;
			}
			//当parent存在且parent 的颜色为红
			while (parent != nullptr && parent->_col == RED)
			{
				Node* grandfather = parent->_parent;
				if (parent == grandfather->_left)
				{
					Node* uncle = grandfather->_right;
					//情况1,uncle存在且为红
					if (uncle != nullptr && uncle->_col == RED)
					{
						parent->_col = uncle->_col = BALCK;
						grandfather->_col = RED;

						cur = grandfather;
						parent = cur->_parent;
					}
					else  //情况2 + 3-> uncle不存在或者存在且为黑
					{
						if (cur == parent->_left)
						{
							RotateR(grandfather);
							parent->_col = BALCK;
							grandfather->_col = RED;
						}
						else
						{
							RotateL(parent);
							RotateR(grandfather);
							cur->_col = BALCK;
							grandfather->_col = BALCK;
						}
						break;
					}
				}
				else
				{
					Node* uncle = grandfather->_left;
					//情况1,uncle存在且为红
					if (uncle != nullptr && uncle->_col == RED)
					{
						parent->_col = uncle->_col = BALCK;
						grandfather->_col = RED;

						cur = grandfather;
						parent = cur->_parent;
					}
					else  //情况2 + 3-> uncle不存在或者存在且为黑
					{
						if (cur == parent->_right)
						{
							RotateL(grandfather);
							parent->_col = BALCK;
							grandfather->_col = RED;
						}
						else
						{
							RotateR(parent);
							RotateL(grandfather);
							cur->_col = BALCK;
							grandfather->_col = BALCK;
						}
					}
					break;
				}
			}
			_root->_col = BALCK;
			return std::make_pair(iterator(newnode), true);
		}
	private:
		void RotateL(Node* parent)
		{
			Node* subR = parent->_right;
			Node* subRL = subR->_left;
			Node* parentParent = parent->_parent;

			parent->_right = subRL;
			if (subRL)
			{
				subRL->_parent = parent;
			}

			
			subR->_left = parent;
			parent->_parent = subR;

			if (_root == parent)
			{
				_root = subR;
				subR->_parent = nullptr;
			}
			else
			{
				if (parentParent->_left == parent)
					parentParent->_left = subR;
				else
					parentParent->_right = subR;
				subR->_parent = parentParent;
			}
		}

		void RotateR(Node* parent)
		{
			Node* subL = parent->_left;
			Node* subLR = subL->_right;
			Node* parentParent = parent->_parent;
			parent->_left = subLR;
			if (subLR)
				subLR->_parent = parent;

			

			subL->_right = parent;
			parent->_parent = subL;

			if (parent == _root)
			{
				_root = subL;
				_root->_parent = nullptr;
			}
			else
			{
				if (parentParent->_left == parent)
					parentParent->_left = subL;
				else
					parentParent->_right = subL;

				subL->_parent = parentParent;
			}
		}
		Node* Copy(Node* root)
		{
			if (root == nullptr)
				return nullptr;
			Node* newnode = new Node(root->_data);
			newnode->_col = root->_col;

			newnode->_left = Copy(root->_left);
			newnode->_right = Copy(root->_right);
			if (newnode->_left != nullptr)
			{
				newnode->_left->_parent = newnode;
			}
			if (newnode->_right != nullptr)
			{
				newnode->_right->_parent = newnode;
			}
			return newnode;
		}
		void Destroy(Node* root)
		{
			if (root == nullptr)
				return;
			Destroy(root->_left);
			Destroy(root->_right);
			delete root;
		}

	private:
		Node* _root;
	};
}

map模拟实现

#pragma once
#include"stl_tree.h"

namespace bit
{
	template<class K, class V>
	class map
	{
	public:
		struct MapKeyOfT
		{
			const K& operator()(const std::pair<K, V>& kv)
			{
				return  kv.first;
			}
		};
		typedef typename RBTree<K, std::pair<K, V>, MapKeyOfT>::iterator iterator;
		std::pair<iterator, bool> insert(const std::pair<K, V>& kv)
		{
			return _rb.insert(kv);
		}
		iterator begin()
		{
			return _rb.begin();
		}
		iterator end()
		{
			return _rb.end();
		}
		V& operator[](const K& key)
		{
			auto ret = _rb.insert(std::make_pair(key, V()));
			return ret.first->second;
		}
	private:
		RBTree<K, std::pair<K, V>, MapKeyOfT> _rb;
	};

	void test_map()
	{
		map<std::string, std::string> dict;
		dict.insert(std::make_pair("sort", "排序"));
		dict.insert(std::make_pair("string", "字符串"));
		dict.insert(std::make_pair("map", "地图"));
		dict["left"];
		dict["left"] = "剩余";
		dict["map"] = "地图/容器";

		auto it = dict.begin();
		while (it != dict.end())
		{
			std::cout << it->first << ":" << it->second << std::endl;
			++it;
		}
		std::cout << std::endl;
	}
}

set模拟实现

#include"stl_tree.h"

namespace bit
{
	template<class K>
	class set
	{
	public:
		struct SetOfT
		{

			const K& operator()(const K& key)
			{
				return key;
			}
		};
	public:
			typedef typename RBTree<K, K, SetOfT>::iterator iterator;
			std::pair<iterator, bool> insert(const K& key)
			{
				return _rb.insert(key);
			}
			iterator begin()
			{
				return _rb.begin();
			}
			iterator end()
			{
				return _rb.end();
			}
			iterator find(const K& key)
			{
				return _rb.find(key);
			}
	private:
		RBTree<K, K, SetOfT> _rb;
	};
	void test_set()
	{
		set<int> s;
		s.insert(1);
		s.insert(4);
		s.insert(2);
		s.insert(24);
		s.insert(2);
		s.insert(12);
		s.insert(6);

		set<int>::iterator it = s.begin();
		while (it != s.end())
		{
			std::cout << *it << " ";
			++it;
		}
		std::cout << std::endl;

		for (auto e : s)
		{
			std::cout << e << " ";
		}
		std::cout << std::endl;

		set<int> copy(s);
		for (auto e : copy)
		{
			std::cout << e << " ";
		}
		std::cout << std::endl;

		set<int> ss;
		ss.insert(111);
		ss.insert(422);

		copy = ss;
		for (auto e : copy)
		{
			std::cout << e << " ";
		}
		std::cout << std::endl;
	}
}

HashTable封装unordered_map 和 unordered_set

#pragma once
#include<iostream>
#include<vector>
template<class K>
class Hash
{
public:
	size_t operator()(const K& key)
	{
		return key;
	}
};
template<>
class Hash<std::string>
{
public:
	size_t operator()(const std::string& key)
	{
		size_t value = 0;
		for (const auto& e : key)
		{
			value *= 31;
			value += e;
		}
		return value;
	}
};
static const unsigned long __stl_prime_list[28] =
{
	53, 97, 193, 389, 769,
	1543, 3079, 6151, 12289, 24593,
	49157, 98317, 196613, 393241, 786433,
	1572869, 3145739, 6291469, 12582917, 25165843,
	50331653, 100663319, 201326611, 402653189, 805306457,
	1610612741, 3221225473, 4294967291
};
static size_t GetNextPrime(size_t num)
{
	for (size_t i = 0; i < 28; ++i)
	{
		if (__stl_prime_list[i] > num)
			return __stl_prime_list[i];
	}
	return __stl_prime_list[27];
}
namespace OpenHash
{
	template<class T>
	class HashNode
	{
	public:
		HashNode(const T& data)
			:_data(data)
			, _next(nullptr)
		{

		}
		T _data;
		HashNode<T>* _next;
	};

	template<class K, class T, class KeyOfT, class HashFunc> //需要提前声明
	class HashTable;

	template<class T, class Ref, class Ptr, class K, class KeyOfT, class HashFunc>
	class HashTableIterator
	{
	public:
		typedef HashNode<T> Node;
		typedef HashTableIterator<T, Ref, Ptr, K, KeyOfT, HashFunc> Self;

		HashTableIterator(Node* node, HashTable<K, T, KeyOfT, HashFunc>* pht)
			:_node(node)
			, _pht(pht)
		{

		}
		Ref operator*()
		{
			return _node->_data;
		}
		Ptr operator->()
		{
			return &_node->_data;
		}
		Self& operator++()
		{
			if (_node->_next != nullptr)   //说明当前桶还没走完
			{
				_node = _node->_next;
			}
			else
			{
				HashFunc hf;
				KeyOfT kot;
				size_t index = hf(kot(_node->_data)) % _pht->_tables.size();    //这里指针访问不了私有成员,可以用友元
				++index;
				while (index < _pht->_tables.size())
				{
					if (_pht->_tables[index] != nullptr)
					{
						break;
					}
					else
					{
						++index;
					}
				}
				//走到有两中情况
				if (index == _pht->_tables.size())
				{
					_node = nullptr;
				}
				else
				{
					_node = _pht->_tables[index];
				}
			}
			return *this;
		}
		bool operator!=(const Self& s)
		{
			return _node != s._node;
		}
		bool operator==(const Self& s)
		{
			return _node == s._node;
		}
	private:
		Node* _node;
		HashTable<K, T, KeyOfT, HashFunc>* _pht;
	};

	template<class K, class T, class KeyOfT, class HashFunc = Hash<K>>
	class HashTable
	{
	public:
		typedef HashNode<T> Node;

		typedef HashTableIterator<T, T&, T*, K, KeyOfT, HashFunc> iterator;
		template<class T, class Ref, class Ptr, class K, class KeyOfT, class HashFunc>
		friend class HashTableIterator; //声明友元
		/*HashTable() //需要在初始化列表初始化vector和_n;所以需要提供默认构造
		{
		}*/
		HashTable() = default;  // c++11

		HashTable(const HashTable<K, T, KeyOfT, HashFunc>& s)
		{
			_tables.resize(s._tables.size());
			for (size_t i = 0; i < s._tables.size(); ++i)
			{
				Node* cur = s._tables[i];
				while (cur != nullptr)
				{
					Node* copy = new Node(cur->_data);
					copy->_next = _tables[i];
					_tables[i] = copy;

					cur = cur->_next;
				}
			}
		}
		HashTable<K, T, KeyOfT, HashFunc>& operator=(HashTable<K, T, KeyOfT, HashFunc> s)
		{
			swap(_n, s._n);
			_tables.swap(s._tables);
			return *this;
		}

		iterator begin()
		{
			for (size_t i = 0; i < _tables.size(); ++i)
			{
				if (_tables[i] != nullptr)
					return iterator(_tables[i], this); //把表指针传递过去
			}
			return end();
		}
		iterator end()
		{
			return iterator(nullptr, this);
		}
		iterator find(const K& key)
		{
			HashFunc hf;
			KeyOfT kot;
			if (_tables.size() == 0)
				return end();

			size_t index = hf(key) % _tables.size();
			if (_tables[index] == nullptr)
				return end();

			HashNode<T>* cur = _tables[index];
			while (cur != nullptr)
			{
				if (kot(cur->_data) == key)
					return iterator(cur, this);
				cur = cur->_next;
			}
			return end();
		}
		bool erase(const K& key)
		{
			if (_tables.empty())
				return false;
			HashFunc hf;
			size_t index = hf(key) % _tables.size();
			Node* prev = nullptr;
			Node* cur = _tables[index];
			while (cur != nullptr)
			{
				if (kot(cur->_data) == key)
				{
					if (prev == nullptr)
					{
						_tables[index] = cur->_next;
					}
					else
					{
						prev->_next = cur->_next;
					}
					delete cur;
					break;
				}
				prev = cur;
				cur = cur->_next;
			}
			--_n;
			return true;
		}

		std::pair<iterator, bool> insert(const T& data)
		{
			KeyOfT kot;
			//HashNode<T>* ret = find(kot(data));
			iterator ret = find(kot(data));
			if (ret != end())
				return std::make_pair(ret, false);
			HashFunc hf;
			if (_n == _tables.size())  //扩容
			{
				//size_t newSize = _tables.size() == 0 ? 10 : _tables.size() * 2;
				size_t Newsize = GetNextPrime(_tables.size());   //根据STL源码库扩容都是素数
				std::vector<Node*> NewVector;
				NewVector.resize(Newsize);

				for (size_t i = 0; i < _tables.size(); ++i)
				{
					Node* cur = _tables[i];
					while (cur != nullptr)
					{
						Node* next = cur->_next;
						size_t index = hf(kot(cur->_data)) % NewVector.size();

						cur->_next = NewVector[index];
						NewVector[index] = cur;

						cur = next;
					}
					_tables[i] = nullptr;
				}
				_tables.swap(NewVector);
			}
			size_t index = hf(kot(data)) % _tables.size();
			Node* newnode = new Node(data);
			newnode->_next = _tables[index];
			_tables[index] = newnode;
			++_n;
			return std::make_pair(iterator(newnode, this), true);
		}
	private:
		std::vector<Node*> _tables;
		size_t _n = 0; //有效数据个数
	};
}

unordered_set模拟实现

#pragma once
#include"HashTable.h"

namespace OpenHash
{
	template<class K, class hash = Hash<K>>
	class unordered_set
	{
	public:
		class SetOfT
		{
		public:
			const K& operator()(const K& key)
			{
				return key;
			}
		};
		typedef typename HashTable<K, K, SetOfT, hash>::iterator iterator;
		iterator begin()
		{
			return _ht.begin();
		}
		iterator end()
		{
			return _ht.end();
		}
		std::pair<iterator, bool> insert(const K& key)
		{
			return _ht.insert(key);
		}
		bool earse(const K& key)
		{
			return _ht.erase();
		}
		iterator find(const K& key)
		{
			return _ht.find(key);
		}

	private:
		HashTable<K, K, SetOfT, hash> _ht;
	};
	void test_unordered_set()
	{
		//unordered_set<int> us;
		/*us.insert(4);
		us.insert(14);
		us.insert(34);
		us.insert(7);
		us.insert(24);
		us.insert(17);*/
		unordered_set < std::string> us;
		us.insert("sort");
		us.insert("map");
		us.insert("left");
		us.insert("right");
		us.insert("apples");
		for (auto e : us)
		{
			std::cout << e << std::endl;
		}
	}
}

unordered_map模拟实现

#pragma once
#include"HashTable.h"

namespace OpenHash
{
	template<class K, class V, class hash = Hash<K>>
	class unodered_map
	{
	public:
		class MapOfT
		{
		public:
			const K& operator()(const std::pair<K, V>& kv)
			{
				return kv.first;
			}
		};
		typedef typename HashTable<K, std::pair<K, V>, MapOfT, hash>::iterator iterator;
		iterator begin()
		{
			return _ht.begin();
		}
		iterator end()
		{
			return _ht.end();
		}
		std::pair<iterator, bool> insert(const std::pair<K, V>& kv)
		{
			return _ht.insert(kv);
		}
		iterator find(const K& key)
		{
			return _ht.find(key);
		}
		bool erase(const K& key)
		{
			return _ht.erase(key);
		}
	private:
		HashTable<K, std::pair<K, V>, MapOfT, hash> _ht;
	};
	void unordered_map_test()
	{
		/*unodered_map<int, int> um;
		um.insert(std::make_pair(1, 1));
		um.insert(std::make_pair(11, 11));
		um.insert(std::make_pair(21, 21));
		um.insert(std::make_pair(31, 31));
		um.insert(std::make_pair(41, 41));
		um.insert(std::make_pair(51, 51));*/

		unodered_map<std::string, std::string> um;
		um.insert(std::make_pair("sort", "排序"));
		um.insert(std::make_pair("map", "地图"));
		um.insert(std::make_pair("left", "左边"));
		um.insert(std::make_pair("right", "右边"));
		auto it = um.begin();
		while (it != um.end())
		{
			std::cout << it->first << ":" << it->second << std::endl;
			++it;
		}
		std::cout << std::endl;
		unodered_map < std::string, std::string > um2 = um;
		auto rit = um2.begin();
		while (rit != um2.end())
		{
			std::cout << rit->first << ":" << rit->second << std::endl;
			++rit;
		}
	}
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值