各STL容器的模拟实现

string

c 复制代码
//string.h
#pragma once
#include<iostream>
namespace my_string
{
	class string
	{
	public:
		typedef char* iterator;
		typedef const char* const_iterator;
		iterator  begin();
		const_iterator  begin()const;
		iterator  end();
		const_iterator  end()const;
		string(const char* s="");
		string(const string& s);
		const string& operator=(const string& s);
		void reserve(size_t size);//接收size表示需要提前准备的空间,不够就扩容,够了就什么也不做
		void resize(size_t n, char c = '\0');
		void append(const char* str);
		const string& operator+=(const string& s);
		const string& operator+=(const char* str);
		const string& operator+=( char c);
		void push_back( char c);
		void insert(size_t pos,char c);
		void insert(size_t pos, const char* str);
		string& erase(size_t pos, size_t len = -1);
		bool operator==(const string& s)const;
		char& operator[](size_t pos);
		const char& operator[](size_t pos)const;
		
		size_t size()const;
		size_t capacity()const;
		const char* c_str()const;
		bool operator<(const string& s)const;
		bool operator>(const string& s)const;
		bool operator>=(const string& s)const;
		bool operator<=(const string& s)const;
		bool operator!=(const string& s)const;

		~string();
		void clear();
		// friend std::ostream& operator<<(std::ostream& out, string& s);
	private:
		char* _str;
		size_t _capacity;
		size_t _size;

	};
	std::ostream& operator<<(std::ostream& out,const string& s);
	std::istream& operator>>(std::istream& in,string& s);
}
c 复制代码
//string.cc
#include<string>
#include "string.h"
#include <iostream>
#include <cstring>
#include <assert.h>
namespace my_string
{

	string::iterator string::begin()
	{
		return _str;
	}
	string::const_iterator string::begin() const
	{
		return _str;
	}
	string::iterator string::end()
	{
		return _str + _size;
	}
	string::const_iterator string::end() const
	{
		return _str + _size;
	}
	string::string(const char *s)
		: _size(_capacity),		  
		  _capacity(strlen(s))
	{
		_str = new char[_capacity + 1];
		strcpy(_str, s);
	}
	string::string(const string &s)
		: _capacity(0),
		  _size(0)
	{
		_capacity = s._capacity;
		_size = s._size;
		char *tmp = new char[s._capacity + 1];
		strcpy(tmp, s._str);
		_str = tmp;
	}
	const string &string::operator=(const string &s)
	{
		if (s == *this)
		{
			return s;
		}
		char *tmp = new char[s._capacity + 1];
		delete[] _str;
		_str = tmp;
		_capacity = s._capacity;
		_size = s._size;
		strcpy(_str, s._str);
		return *this;
	}
	void string::reserve(size_t size) // 接收size表示需要提前准备的空间,不够就扩容,够了就什么也不做
	{
		if (size > _capacity)
		{
			char *tmp = new char[size + 1];
			strcpy(tmp, _str);
			delete[] _str;
			_str = tmp;
			_capacity = size;
		}
	}
	void string::resize(size_t n, char c)
	{
		reserve(n);
		if (n < _size)
		{
			_size = n;
			_str[n] = '\0';
			return;
		}
		for (size_t begin = _size; begin < n; begin++)
		{
			_str[begin] = c;
		}
		_str[n] = '\0';
	}
	void string::append(const char *str)
	{
		int len = strlen(str);
		reserve(_size + len);
		strcpy(_str + _size, str);
		_size += len;
	}
	const string &string::operator+=(const string &s)
	{
		reserve(s.size() + _size);
		strcpy(_str + _size, s._str);
		_size += s.size();
		return *this;
	}
	const string &string::operator+=(const char *str)
	{
		size_t len = strlen(str);
		reserve(_size + len);
		strcpy(_str + _size, str);
		_size += len;
		return *this;
	}
	const string &string::operator+=(char c)
	{
		push_back(c);
		return *this;
	}
	void string::push_back(char c)
	{
		reserve(_size + 1);
		_str[_size] = c;
		_size++;
		_str[_size] = '\0';
	}
	void string::insert(size_t pos, char c)
	{
		assert(pos<_size);
		reserve(_size + 1);
		/*size_t end = _size ;*/ // 这里end为size_t无符号整形,因为这里当pos等于0时,当end减到0走进循环,本应该是这次之后end为 - 1,下一次判断就跳出循环,但是如果是无符号整形没有负数,没有符号位,经过end--后会变为4294967295,就这样陷入死循环
		/*while (pos <= end)
		{
			_str[end + 1] = _str[end];
			end--;
		}
		_str[pos] = c;
		_size++;*/
		size_t end = _size + 1;
		while (pos < end)
		{
			_str[end] = _str[end - 1];
			end--;
		}
		_str[pos] = c;
		_size++;
	}
	void string::insert(size_t pos, const char *str)
	{
		assert(pos<_size);
		size_t len = strlen(str);
		reserve(_size + len);
		/*size_t end = _size;*///同理
		// while (pos <= end)  
		//{
		//	_str[end + len] = _str[end];
		//	end--;
		// }
		size_t end = _size + len;
		while (pos + len - 1 < end)
		{
			_str[end] = _str[end - len];
			end--;
		}
		for (size_t i = 0; i < len; i++)
			_str[pos + i] = *(str + i);
		_size += len;
	}
	string &string::erase(size_t pos, size_t len)
	{
		if (len + pos >= _size)
		{
			_size = pos;
			_str[pos] = '\0';
		}
		else
		{
			size_t begin = pos + len;
			size_t end = _size;
			while (begin <= end)
			{
				_str[begin - len] = _str[begin];
				begin++;
			}
			_size -= len;
		}
		return *this;
	}

	bool string::operator==(const string &s) const
	{

		return !strcmp(_str, s._str);
	}
	char &string::operator[](size_t pos)
	{
		assert(pos < _size);
		return _str[pos];
	}
	const char& string::operator[](size_t pos)const{
		assert(pos < _size);
		return _str[pos];
	}
	size_t string::size() const
	{
		return _size;
	}
	size_t string::capacity() const
	{
		return _capacity;
	}
	const char *string::c_str()const
	{
		return _str;
	}
	bool string::operator<(const string &s) const
	{
		return strcmp(_str, s._str) < 0;
	}
	bool string::operator>(const string &s) const
	{
		return !(*this < s || *this == s);
	}
	bool string::operator>=(const string &s) const
	{
		return !(*this < s);
	}
	bool string::operator<=(const string &s) const
	{
		return !(*this > s);
	}
	bool string::operator!=(const string &s) const
	{
		return !(*this == s);
	}
	string::~string()
	{
		delete _str;
		_str = nullptr;
		_capacity = _size = 0;
	}
	void string::clear()
	{
		_size = 0;
		_str[0] = '\0';
	}

	// std::ostream& operator<<(std::ostream& out,string&s)//利用友元解决
	// {
	// 	out << s.c_str() ;
	// 	return out;
	// }
	std::ostream &operator<<(std::ostream &out,const string &s) // 没有利用友元解决
	{
		for (auto e : s)
		{
			std::cout << e;
		}
		return out;
	}

	std::istream &operator>>(std::istream &in, string &s)
	{
		s.clear();
		char ch;
		char buff[128];
		int i;
		if (!in.get(ch))
		{
			std::cout << "处理失败" << std::endl;
			return in;
		}
		for (i = 0; ch != ' ' && ch != '\n'; i++)
		{
			if (i == 127)
			{
				buff[i] = '\0';
				s += buff;
				i = 0;
			}
			buff[i] = ch;
			if (!in.get(ch))
			{
				std::cout << "处理失败" << std::endl;
				break;
			}
		}
		buff[i] = '\0';
		s += buff;

		return in;
	}

}
c 复制代码
//main.cc
#include "string.h"

void stringtest()
{
    using std::cout;
    using std::endl;
    using std::cin;
    my_string::string s1("hello lhr");
    s1.erase(1, 4);
    cout << s1 << endl;
    s1.push_back('l');
    cout << s1 << endl;
    s1.insert(s1.size() - 1, "ljp");
    cout << s1 << endl;
    s1 += " 你好";
    cout << s1 << endl;
    my_string::string s2("how are you");
    s1 += s2;
    cout << s1 << endl;
    s1 += 'h';
    cout << s1 << endl;
    s1.append("you fly");
    cout << s1 << endl;
    s1.resize(70, 'a');
    cout << s1 << endl;
    cout << "****************************************" << endl;
    s2 = s1;
    cout << s2 << endl;
    cout << s1 << endl;
    my_string::string s3(s1);
    cout << s3 << endl;
    my_string::string s4("l h r");
    cout << s4 << endl;
    // s4.insert(7, 'm');
    // cout << s4 << endl;
    // s4.erase(8, 30);
    // cout << s4 << endl;
    my_string::string s5(s4);
    cout << (s5 == s4) << endl;
    cout << (s5 >= s4) << endl;
    cout << (s5 <= s4) << endl;
    cout << (s5 == s1) << endl;
    cout << (s5 > s1) << endl;
    cout << (s5 != s1) << endl;
    cout << s4[4] << endl;
    cout << s4.c_str() << endl;
     cout << s1 << endl;
    s1.resize(20, 'a');
    cout << s1 << endl;
    s4.insert(0, 'm');
    cout << s4 << endl;
    s4.insert(0, "lhr ljp");
    cout << s4 << endl;
    cin >> s4;
    cout << s4 << endl;
    const my_string::string s6("heheheh");
    cout<<s6[4]<<endl;
}
int main()
{
    stringtest();
}

运行后输入test结果如下:

vector

cpp 复制代码
//vector.hpp
#pragma once
#include<assert.h>
#include<iostream>
#include <algorithm>
namespace my_vector
{
	template<typename T>
	class vector
	{
	public:
		typedef T* iterator;
		vector();
		vector(const vector<T>&v);
		vector<T>& operator=(vector<T>v);//传值传入会调用拷贝构造,从而有现成的对象,故该函数的实现:直接交换内部的指针即可
		void swap(vector<T>& v);

		vector(size_t n, const T& val=T());//vector<int> vv(10,5);这种传参会导致需要类型转换,需要将int转换为size_t才能匹配到这个构造,所以编译器不会优先调用这个,会优先调用vector(inputiterator first, inputiterator last) 从而出错
		vector(int n, const T& val=T());//写这个n为int的函数重载,就解决了上面的问题,因为类型更加匹配
		template<class inputiterator>
		vector(inputiterator first, inputiterator last);
		void reserve(size_t n);
		void resize(size_t n,const T& val=T());
		size_t _size()const;
		size_t _capacity()const;
		void push_back(const T&v );
		void pop_back();
		const iterator begin()const;
		const iterator end()const;
	    iterator begin();
        iterator end();
		iterator insert(iterator pos, const T& val);
		iterator erase(iterator pos);
		
		T& operator[](size_t pos);
        const T& operator[](size_t pos)const;
	
		~vector();

	private:
		iterator _begin=nullptr;
		iterator _finish=nullptr;
		iterator _end_of_storage=nullptr;
	};
    
	template<typename T>
    vector<T>::vector()
			/*:_begin(nullptr),
			_finish(nullptr),
			_end_of_storage(nullptr)*/
		{}
		template<typename T>
    vector<T>::vector(const vector<T>&v)
			/*:_begin ( nullptr),
			_finish ( nullptr),
			_end_of_storage  (nullptr)*/
		{
			
			reserve(v._capacity());
			for (size_t i = 0; i < v._size(); i++)
			{
				_begin[i] =v. _begin[i];
				_finish++;
			}
		}
        template<typename T>
		vector<T>& vector<T>::operator=(vector<T>v)
		{
			swap(v);
			return *this;
		}
        template<typename T>
		void vector<T>::swap(vector<T>& v)
		{
			std::swap(_begin, v._begin);
			std::swap(_finish, v._finish);
			std::swap(_end_of_storage, v._end_of_storage);
		}
        template<typename T>
		vector<T>::vector(size_t n, const T& val)
		{
			reserve(n);
			for (auto e : val)
			{
				push_back(e);
			}
		}
        template<typename T>
		vector<T>::vector(int n, const T& val)
		{
			reserve(n);
			for (int i = 0; i < n; i++)
			{
				*(_begin + i) = val;
				_finish++;
			}
			
		}

template<typename T>
		template<class inputiterator>
		vector<T>::vector(inputiterator first, inputiterator last)
		{
			reserve(std::distance(first,last));
			while (first != last)
			{
				push_back(*first);
				first++;
			}
		}
        template<typename T>
		void vector<T>::reserve(size_t n)
		{
			T* tmp = new T[n];
			size_t len  = _size();//记录大小,如果没有这条,可能会由于_begin被提前赋为tmp而导致_size()函数得出的数据个数是无效数据
			if (_begin)                    //如果这是第一次创建对象后的扩容,也就没有必要拷贝数据,同时也不能通过下面的方式拷贝数据(会出现对空指针的解引用),所以用_begin是否为空来作为判断
			{
				for (size_t i = 0; i < len; i++)
				{
					tmp[i] = _begin[i];
				}
				delete[]_begin;
			}
			_begin = tmp;
			_finish = _begin +len;
			_end_of_storage = _begin + n;
		}
        template<typename T>
		void vector<T>::resize(size_t n,const T& val)
		{
			if (_size() > n)
			{
				_finish = _begin + n;
			}
			else
			{
				if (n >= _capacity())
				{
					reserve(n);
				}
				iterator begin = _finish;
				while (begin != _begin + n)
				{
					*begin = val;
					begin++;
					_finish++;
				}
			}
		}
        template<typename T>
		size_t vector<T>::_size()const
		{
			return _finish - _begin;
		}
        template<typename T>
		size_t vector<T>::_capacity()const
		{
			return _end_of_storage-_begin;
		}
        template<typename T>
		void vector<T>::push_back(const T&v )
		{
			if ( _finish==_end_of_storage)
			{
				reserve(_capacity() == 0 ? 4 : 2 * _capacity());
			}
			*_finish = v;
			_finish++;
		}
        template<typename T>
		void vector<T>::pop_back()
		{
			assert(_begin != _finish);
				_finish--;
		}
        template<typename T>
		const typename vector<T>::iterator vector<T>::begin()const
		{
			return _begin;
		}
        template<typename T>
		const typename vector<T>::iterator vector<T>::end()const
		{
			return _finish;
		}
        template<typename T>
	    typename vector<T>::iterator vector<T>::begin()
		{
			return _begin;
		}
        template<typename T>
        typename  vector<T>::iterator vector<T>::end()
		{
			return _finish;
		}
        template<typename T>
		typename vector<T>::iterator vector<T>::insert(vector<T>::iterator pos, const T& val)
		{
			
			if (_finish == _end_of_storage)
			{
				size_t len = pos - _begin;//扩容前记录_begin与pos之间的距离,为之后重新计算pos做准备
				reserve(_capacity() == 0 ? 4 : 2 * _capacity());
				pos = _begin + len;//扩容以后重新分配空间,原来的pos迭代器失效,建立一个新的pos
			}
			iterator end=_finish - 1;
			while (pos <= end)
			{
				*(end + 1) = *end;
				end--;
			}
			*pos = val;
			pos++;
			_finish++;
			return pos;
		}
        template<typename T>
		typename vector<T>::iterator vector<T>::erase(vector<T>::iterator pos)
		{
			iterator begin = pos + 1;
			while (begin < _finish)
			{
				*(begin - 1) = *begin;
				begin++;
			}
			_finish--;
			return pos;
		}
		template<typename T>
		T& vector<T>::operator[](size_t pos)
		{
			return _begin[pos];
		}
        template<typename T>
        const T& vector<T>::operator[](size_t pos)const{
            return _begin[pos];
        }
		template<typename T>
		vector<T>::~vector()
		{
			delete[]_begin;
			_begin = nullptr;
			_finish = nullptr;
			_end_of_storage = nullptr;
			// std::cout << "~vector" << std::endl;
		}
};
cpp 复制代码
//main.cc
#include "vector.hpp"
#include<list>
int main()
{
    my_vector::vector<int> v(3, 4);
    v.push_back(44);
    v.pop_back();
    v.push_back(55);
    v.insert(v.begin(), 66);
    auto it = v.begin();
    while (it != v.end())
    {
        std::cout << *it << std::endl;
        it++;
    }
    const my_vector::vector<int> v2 = v;
    auto iter = v2.begin();
    while (iter != v2.end())
    {
        std::cout << *iter << std::endl;
        iter++;
    }
    v = v2;
    it = v.begin();
    while (it != v.end())
    {
        std::cout << *it << std::endl;
        it++;
    }
    std::cout << v[1] << std::endl;
    std::cout << v2[1] << std::endl;
    v.erase(v.end());
    it = v.begin();
    while (it != v.end())
    {
        std::cout << *it << std::endl;
        it++;
    }
    std::cout << "********************" << std::endl;
    std::list<int>l;
    l.push_back(2);
    l.push_back(4);
    l.push_back(1);
    my_vector::vector<int> v3(l.begin(), l.end());
    it = v3.begin();
    while (it != v3.end())
    {
        std::cout << *it << std::endl;
        it++;
    }
}

list

cpp 复制代码
//list.hpp
#pragma once
#include <iostream>
namespace my_list
{
    template <class T>
    struct node
    {
        node<T> *prev = nullptr;
        node<T> *next = nullptr;
        T val;
        node(const T &_val = T())
            : val(_val)
        {
        }
    };

    template <class T, class Ref, class Ptr>
    class list_iterator
    {
    public:
        typedef node<T> Node;
        // 用来给reverse_iterator获取类型
        typedef Ptr ptr;
        typedef Ref ref;
        typedef T t;

        typedef list_iterator<T, Ref, Ptr> self; // 这里不用self也行,可以直接用 list_iterator来表示自己这个类型
        Node *_node;
        list_iterator(Node *pos);
        list_iterator(const list_iterator &val);

        Ref operator*();
        self &operator++();
        self operator++(int);
        self &operator--();
        self operator--(int);
        bool operator!=(list_iterator x);
        bool operator==(list_iterator x);
        Ptr operator->();
    };

    template <class iterator>
    struct reverse_iterator
    {
        typedef typename iterator::ptr Ptr;
        typedef typename iterator::ref Ref;
        typedef typename iterator::t T;
        iterator _it;

        reverse_iterator(const iterator &x);
        reverse_iterator(const reverse_iterator &x);
        Ref operator*();
        Ptr operator->();
        reverse_iterator operator++();
        reverse_iterator operator++(int);
        reverse_iterator operator--();
        reverse_iterator operator--(int);
        bool operator==(reverse_iterator x);
        bool operator!=(reverse_iterator x);
    };
    template <class T>
    class list
    {
    public:
        typedef node<T> Node;
        typedef list_iterator<T, T &, T *> iterator;
        typedef list_iterator<T, const T &, const T *> const_iterator;
        typedef my_list::reverse_iterator<const_iterator> const_reverse_iterator;
        typedef my_list::reverse_iterator<iterator> reverse_iterator;

        list();
        template <class inputiterator>
        list(inputiterator first, inputiterator last);
        void swap(list &other);
        list(const list &tmp); // 这里不用是const修饰this指针,因为拷贝构造是在定义初始化时调用的,就算是const对象在这个时候也是不具备const属性的。
        void push_back(const T &val);
        void push_front(const T &val);
        iterator begin();
        iterator end();
        const_iterator begin() const; // 如果是具有const属性的对象调用begin这个函数会调用这个重载,并且由于是具有const属性的对象,所以理所当然的得到的迭代器是 不能对该对象的内容进行修改的迭代器 所以返回的迭代器是const_iterator类型的
        const_iterator end() const;

        const_reverse_iterator rend() const;
        const_reverse_iterator rbegin() const;
        reverse_iterator rbegin();
        reverse_iterator rend();
        void insert(iterator pos, const T &val); // 如果是用const_iterator迭代器来进行插入会报错,因为类的类型不符,故如果要用迭代器指定插入位置,迭代器不能是const_iterator,因为const_iterator本身就以为着该迭代器指向的位置不被改变,所以对于插入操作就不允许这么做
        void erase(iterator pos);
        void clear();
        void pop_front();
        void pop_back();
        ~list();

    private:
        void list_initial();
        Node *_head;
    };

    // list_iterator中的函数定义
    //**********************************************************
    template <class T, class Ref, class Ptr>
    list_iterator<T, Ref, Ptr>::list_iterator(Node *pos)
    {
        _node = pos;
    }
    template <class T, class Ref, class Ptr>
    list_iterator<T, Ref, Ptr>::list_iterator(const list_iterator &val)
    {
        _node = val._node;
    }
    template <class T, class Ref, class Ptr>
    Ref list_iterator<T, Ref, Ptr>::operator*()
    {
        return _node->val;
    }
    template <class T, class Ref, class Ptr>
    typename list_iterator<T, Ref, Ptr>::self &list_iterator<T, Ref, Ptr>::operator++()
    {
        _node = _node->next;
        return *this;
    }
    template <class T, class Ref, class Ptr>
    typename list_iterator<T, Ref, Ptr>::self list_iterator<T, Ref, Ptr>::operator++(int)
    {
        Node *ret_node = _node;
        _node = _node->next;
        return self(ret_node);
    }
    template <class T, class Ref, class Ptr>
    typename list_iterator<T, Ref, Ptr>::self &list_iterator<T, Ref, Ptr>::operator--()
    {
        _node = _node->prev;
        return *this;
    }
    template <class T, class Ref, class Ptr>
    typename list_iterator<T, Ref, Ptr>::self list_iterator<T, Ref, Ptr>::operator--(int)
    {
        Node *ret_node = _node;
        _node = _node->prev;
        return self(ret_node);
    }
    template <class T, class Ref, class Ptr>
    bool list_iterator<T, Ref, Ptr>::operator!=(list_iterator x)
    {
        return _node != x._node;
    }
    template <class T, class Ref, class Ptr>
    bool list_iterator<T, Ref, Ptr>::operator==(list_iterator x)
    {
        return _node == x._node;
    }
    template <class T, class Ref, class Ptr>
    Ptr list_iterator<T, Ref, Ptr>::operator->()
    {
        return &_node->val;
    }

    // reverse_iterator中构造函数的定义
    //**********************************************************
    template <class iterator>
    reverse_iterator<iterator>::reverse_iterator(const iterator &x)
        : _it(x)
    {
    }
    template <class iterator>
    reverse_iterator<iterator>::reverse_iterator(const reverse_iterator &x)
        : _it(x._it)
    {
    }
    template <class iterator>
    typename reverse_iterator<iterator>::Ref reverse_iterator<iterator>::operator*()
    {
        return *_it;
    }
    template <class iterator>
    typename reverse_iterator<iterator>::Ptr reverse_iterator<iterator>::operator->()
    {
        return &(*_it);
    }
    template <class iterator>
    reverse_iterator<iterator> reverse_iterator<iterator>::operator++()
    {
        _it--;
        return *this;
    }
    template <class iterator>
    reverse_iterator<iterator> reverse_iterator<iterator>::operator++(int)
    {
        iterator res = _it;
        _it--;
        return reverse_iterator(res);
    }
    template <class iterator>
    reverse_iterator<iterator> reverse_iterator<iterator>::operator--()
    {
        _it++;
        return *this;
    }
    template <class iterator>
    reverse_iterator<iterator> reverse_iterator<iterator>::operator--(int)
    {
        iterator res = _it;
        _it++;
        return reverse_iterator(res);
    }
    template <class iterator>
    bool reverse_iterator<iterator>::operator==(reverse_iterator x)
    {
        return _it == x._it;
    }
    template <class iterator>
    bool reverse_iterator<iterator>::operator!=(reverse_iterator x)
    {
        return _it != x._it;
    }

    // list中的函数定义
    //**********************************************************
    template <class T>
    void list<T>::list_initial()
    {
        _head = new Node;
        _head->next = _head;
        _head->prev = _head;
    }
    template <class T>
    list<T>::list()
    {
        list_initial();
    }
    template <class T>
    template <class inputiterator>
    list<T>::list(inputiterator first, inputiterator last)
    {
        list_initial();
        while (first != last)
        {
            push_back(*first);
            first++;
        }
    }
    template <class T>
    void list<T>::swap(list &other)
    {
        std::swap(_head, other._head);
    }
    template <class T>
    list<T>::list(const list &tmp)
    {
        list_initial();
        list _tmp(tmp.begin(), tmp.end());
        swap(_tmp);
    }
    template <class T>
    void list<T>::push_back(const T &val) //
    {
        /*Node* new_node = new Node(val);
        Node* tail = _head->prev;
        _head->prev = new_node;
        new_node->next = _head;
        tail->next = new_node;
        new_node->prev = tail;*/
        insert(end(), val);
    }
    template <class T>
    void list<T>::push_front(const T &val)
    {
        /*Node* new_node = new Node(T);
        Node* next = _head->next;
        _head->next = new_node;
        new_node->prev = _head;
        new_node->next = next;
        next->prev = new_node;*/
        insert(begin(), val);
    }
    template <class T>
    typename list<T>::iterator list<T>::begin()
    {
        return iterator(_head->next);
    }
    template <class T>
    typename list<T>::iterator list<T>::end()
    {
        return iterator(_head);
    }
    template <class T>
    typename list<T>::const_iterator list<T>::begin() const
    {
        return const_iterator(_head->next);
    }
    template <class T>
    typename list<T>::const_iterator list<T>::end() const
    {
        return const_iterator(_head);
    }

    template <class T>
    typename list<T>::const_reverse_iterator list<T>::rbegin() const
    {
        return const_reverse_iterator(--end());
    }
    template <class T>
    typename list<T>::const_reverse_iterator list<T>::rend() const
    {
        return const_reverse_iterator(--begin());
    }

    template <class T>
    typename list<T>::reverse_iterator list<T>::rbegin()
    {
        return reverse_iterator(--end());
    }
    template <class T>
    typename list<T>::reverse_iterator list<T>::rend()
    {
        return reverse_iterator(--begin());
    }

    template <class T>
    void list<T>::insert(iterator pos, const T &val)
    {
        Node *new_node = new Node(val);
        new_node->prev = pos._node->prev;
        new_node->next = pos._node;
        pos._node->prev->next = new_node;
        pos._node->prev = new_node;
        // Node* prev = pos._node->prev;
        // Node* next = pos._node;
        // next->prev = new_node;
        // prev->next = new_node;
        // new_node->prev = prev;
        // new_node->next = next;
    }
    template <class T>
    void list<T>::erase(iterator pos)
    {
        Node *prev = (pos._node)->prev;
        Node *next = pos._node->next;
        delete pos._node;
        prev->next = next;
        next->prev = prev;
    }
    template <class T>
    void list<T>::clear()
    {
        iterator it = begin();
        while (it != end())
        {
            erase(it++);
        }
    }
    template <class T>
    void list<T>::pop_front()
    {
        erase(begin());
    }
    template <class T>
    void list<T>::pop_back()
    {
        erase(iterartor(_head->prev));
    }
    template <class T>
    list<T>::~list()
    {
        clear();
        delete _head;
        _head = nullptr;
    }
}
cpp 复制代码
//main.cc
#include "list.hpp"
#include <iostream>
void test()
{
    using std::cout;
    using std::endl;
    my_list::list<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    v.push_back(5);
    my_list::list<int>::iterator it = v.begin();
    cout << *it << endl;
    cout << "******************" << endl;

    while (it != v.end())
    {
        cout << *it << endl;
        ++it;
    }
    it = v.begin();
    v.erase(it);

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

    it = v.begin();
    it++;
    it++;
    v.erase(it);
    cout << "******************" << endl;
    it = v.begin();
    while (it != v.end())
    {
        cout << *it << endl;
        ++it;
    }
    cout << "******************" << endl;
    const my_list::list<int> s(v);
    for (auto e : s)
    {
        cout << e << endl;
    }
    cout << "******************" << endl;
    v.push_back(6);
    v.push_back(7);
    v.push_back(8);

    auto r_it=v.rbegin();
    while (r_it != v.rend())
    {
        cout << *r_it << endl;
        ++r_it;
    }
    cout << "******************" << endl;
    auto cr_it=s.rbegin();
     while (cr_it != s.rend())
    {
        cout << *cr_it << endl;
        ++cr_it;
    }
    cout << "******************" << endl;
}
int main()
{
    test();
}

STL中vector和list的区别是什么?

  • vector底层实现是数组;list是双向 链表。

  • vector支持随机访问,list不支持。

  • vector是顺序内存,list不是。

  • vector在中间节点进行插入删除会导致内存拷贝,list不会。

  • vector一次性分配好内存,不够时才进行2倍扩容;list每次插入新节点都会进行内存申请。

  • vector随机访问性能好,插入删除性能差;list随机访问性能差,插入删除性能好。

stack

cpp 复制代码
//stack.hpp
#pragma once
#include <vector>
namespace my_stack
{
    template <typename T, typename Container = std::vector<T>>
    class stack
    {
    public:
    stack(const Container&container=Container());
    bool empty()const;
    std::size_t size()const;
    T& top();
    const T& top()const;
    void push(const T&);
    void pop();

        private : 
        Container _container;
    };

     template <typename T, typename Container>
    stack<T,Container>::stack(const Container&container):_container(container){

    }
    template <typename T, typename Container>
    bool stack<T,Container>::empty()const{
        return _container.empty();
    }
    template <typename T, typename Container>
    std::size_t stack<T,Container>::size()const{
        return _container.size();
    }
    template <typename T, typename Container>
    T& stack<T,Container>::top(){
        return  _container.back();
    }
     template <typename T, typename Container>
    const T& stack<T,Container>::top()const{
        return _container.back();
    }
     template <typename T, typename Container>
    void stack<T,Container>::push(const T&x){
        return _container.push_back(x);
    }
       template <typename T, typename Container>
    void stack<T,Container>::pop(){
        return _container.pop_back();
    }

}
cpp 复制代码
//main.cc
#include "stack.hpp"
#include <iostream>
int main()
{
    my_stack::stack<int> s;
    s.push(2);
    s.push(5);
    s.push(6);

    s.push(3);

    s.push(1);
    std::cout << s.top() << std::endl;
    s.pop();
    s.pop();
    std::cout << s.top() << std::endl;

}

queue

cpp 复制代码
//queue.hpp
#pragma once
#include <list>
namespace my_queue
{
    template <typename T, typename Container = std::list<T>>
    class queue
    {
    public:
    queue(const Container&container=Container());
    bool empty()const;
    std::size_t size()const;
    T& back();
    const T& back()const;
    T& front();
    const T& front()const;
    void push(const T&);
    void pop();

        private : 
        Container _container;
    };

     template <typename T, typename Container>
    queue<T,Container>::queue(const Container&container):_container(container){

    }
    template <typename T, typename Container>
    bool queue<T,Container>::empty()const{
        return _container.empty();
    }
    template <typename T, typename Container>
    std::size_t queue<T,Container>::size()const{
        return _container.size();
    }
    template <typename T, typename Container>
    T& queue<T,Container>::back(){
        return  _container.back();
    }
     template <typename T, typename Container>
    const T& queue<T,Container>::back()const{
        return _container.back();
    }
     template <typename T, typename Container>
    T& queue<T,Container>::front(){
        return  _container.front();
    }
     template <typename T, typename Container>
    const T& queue<T,Container>::front()const{
        return _container.front();
    }
     template <typename T, typename Container>
    void queue<T,Container>::push(const T&x){
        return _container.push_back(x);
    }
       template <typename T, typename Container>
    void queue<T,Container>::pop(){
        return _container.pop_front();
    }

}
cpp 复制代码
//main.cc
#include "queue.hpp"
#include <iostream>
int main()
{
    my_queue::queue<int> s;
    s.push(2);
    s.push(5);
    s.push(6);
    s.push(3);
    s.push(1);

    std::cout << "front:" << s.front() << std::endl;
    std::cout << "back:" << s.back() << std::endl;
    s.pop();
    std::cout << "front:" << s.front() << std::endl;
    std::cout << "back:" << s.back() << std::endl;
}

map和set

二叉搜索树

二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:

  • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
  • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
  • 它的左右子树也分别为二叉搜索树
  1. 二叉搜索树的查找
    • 从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。
    • 最多查找高度次,走到到空,还没找到,这个值不存在。
  2. 二叉搜索树的插入
    • 树为空,则直接新增节点,赋值给root指针
    • 树不空,按二叉搜索树性质查找插入位置,插入新节点
  3. 二叉搜索树的删除
    • 首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情
      况:
      1. 要删除的结点无孩子结点
      2. 要删除的结点只有左孩子结点
      3. 要删除的结点只有右孩子结点
      4. 要删除的结点有左、右孩子结点
    • 把情况1和情况2或3中的一个合并。然后有3种情况的处理方式
      2. 删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点
      3. 删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点
      4. 在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,再来处理该结点的删除问题;或者找左子树中最大的节点替换被删除节点
cpp 复制代码
#pragma once

template <class K>
class BStree
{
    struct BStree_Node
    {
        BStree_Node *right = nullptr;
        BStree_Node *left = nullptr;
        K _val;
        BStree_Node(const K &val)
        {
            _val = val;
        }
    };
    typedef BStree_Node Node;

    Node *Copy(const Node *const &_root); // 通过递归要被拷贝的搜索二叉树来new节点,并且通过返回值进行链接
    void Delete(Node *_root);             // 释放整个二叉搜索树

    void modify_left_tree(Node *&_root, K &val);         // 在删除节点时,若同时有左右节点,可将左子树根节点和当前节点val的引用传入,该函数将把左子树的最大节点值替换到被删除节点,然后释放掉对应节点,并进行托孤调整,使树的结构依旧为二叉搜索树
    bool insertR(Node *parent, Node *cur, const K &val); // 递归方式插入调用的递归函数
    bool FindR(Node *_root, const K &val);               // 递归方式查找调用的递归函数
    bool EraseR(Node *&_root, const K &val);             // 递归方式删除节点调用的递归函数

    void inorder(Node *_root); // 中序遍历递归函数

public: 
    BStree() = default; // 强制生成默认构造函数
    BStree(const BStree &t);

    BStree operator=(BStree t); // 让拷贝构造帮助我们进行深拷贝
    ~BStree();

    bool insert(const K &val);   // 循环方式插入
    bool _insertR(const K &val); // 递归方式插入

    bool Find(const K &val);   // 循环方式查找
    bool _FindR(const K &val); // 递归方式查找

    bool Erase(const K &val); // 循环方式删除节点

    bool _EraseR(const K &val); // 递归方式删除节点

    void _inorder(); // 中序遍历递归启动函数

    private : 
    Node *root = nullptr;
};
template <class K>
BStree<K>::BStree(const BStree& t)
	{
		root=Copy(t.root);
	}
    template <class K>
	typename BStree<K>::Node* BStree<K>::Copy(const Node*const& _root)//通过递归要被拷贝的搜索二叉树来new节点,并且通过返回值进行链接
	{
		if (_root == nullptr)
			return nullptr;
		Node* cur = new Node(_root->_val);
		cur->left = Copy(_root->left);
		cur->right = Copy(_root->right);
		return cur;
	}
    template <class K>
	BStree<K> BStree<K>::operator=(BStree t)//让拷贝构造帮助我们进行深拷贝
	{
		swap(root, t.root);//将各自的root的值交换,得到要被赋值的内容,并且这样做当该函数结束时,t会自动调用它的析构函数帮我们释放之前要被赋值的搜索二叉树中的节点内容。
	}
    template <class K>
	BStree<K>::~BStree()
	{
		Delete(root);
	}
    template <class K>
	void BStree<K>::Delete(Node*_root)//和后序遍历是一个道理的递归删除方式
	{
		if (_root == nullptr)
			return;
		Delete(_root->left);
		Delete(_root->right);
		delete _root;
	}
    template <class K>
	bool BStree<K>::insert(const K& val)
	{
		if (root == nullptr)
		{
			root = new Node(val);
		}
		Node* cur = root;
		Node* parent = nullptr;
		while (cur)
		{
			if (cur->_val < val)
			{
				parent = cur;
				cur = cur->right;
			}
			else if (cur->_val > val)
			{
				parent = cur;
				cur = cur->left;
			}
			else
			{
				return false;
			}
		}
		if (parent->_val > val)
		{
			parent->left = new Node(val);
		}
		else
		{
			parent->right = new Node(val);
		}
	}
    template <class K>
	bool BStree<K>::insertR(Node* parent, Node* cur, const K& val)
	{
		if (cur == nullptr)//cur为空,说明找到了插入元素的正确位置,但是要讨论是否为第一次插入,因为如果是第一次插入parent为空不能解引用来用left或者right来进行链接(也可以理解为第一次插入元素所在节点没有父节点,所以不用链接,所以要分开讨论)
		{
			if (parent == nullptr)
			{
				root = new Node(val);
			}
			else
			{
				if (parent->_val > val)
				{
					parent->left = new Node(val);
				}
				else
				{
					parent->right = new Node(val);
				}
			}
			return true;
		}
		if (cur->_val > val)//比该节点小,向左递归。
		{
			return insertR(cur, cur->left, val);
		}
		else if (cur->_val < val)//比该节点大,向右递归
		{
			return insertR(cur, cur->right, val);
		}
		else//相等说明该元素不能被插入,故插入失败返回false
		{
			return false;
		}
	}
    template <class K>
	bool BStree<K>::_insertR(const K& val)
	{
		return insertR(root, root, val);
	}
    template <class K>
	bool BStree<K>::Find(const K& val)
	{
		if (root == nullptr)
			return false;
		Node* cur = root;
		while (cur)
		{
			if (cur->_val < val)
			{
				cur = cur->right;
			}
			else if(cur->_val>val)
			{
				cur = cur->left;
			}
			else
			{
				return true;
			}
		}
		return false;
	}
    template <class K>
	bool BStree<K>::FindR(Node*_root,const K&val)
	{
		if (_root == nullptr)
			return false;
		if (_root->_val > val)
		{
			return FindR(_root->left, val);
		}
		else if(_root->_val<val)
		{
			return FindR(_root->right, val);
		}
		else
		{
			return true;
		}
	}
    template <class K>
	bool BStree<K>::_FindR(const K& val)
	{
		return FindR(root, val);
	}
    template <class K>
	bool BStree<K>::Erase(const K& val)
	{
		//if (root == nullptr)
		//	return false;
		//if (root->_val == val) //在这里将root所在节点即要删除元素的位置,并且root的左节点或右节点为空的情况先讨论
		//{
		//	if (root->right == nullptr)
		//	{
		//		Node* cur = root->left;
		//		delete root;
		//		root = cur;
		//	}
		//	if (root->left == nullptr)
		//	{
		//		Node* cur = root->right;
		//		delete root;
		//		root = cur;
		//	}
		//}
		//Node* cur = root;
		//Node* parent = nullptr;
		//while (cur)
		//{
		//	if (cur->_val < val)
		//	{
		//		parent = cur;
		//		cur = cur->right;
		//	}
		//	else if (cur->_val > val)
		//	{
		//		parent = cur;
		//		cur = cur->left;
		//	}
		//	else
		//	{
		//		if (cur->right == nullptr )
		//		{
		//			if (cur->_val > parent->_val)
		//			{
		//				Node* pos = cur->left;
		//				delete cur;
		//				parent->right =pos;//如果之前没有单独把上面root所在节点即要删除元素的位置,并且root的左节点或右节点为空的情况先讨论,那么这里在遇到这种情况时进入while循环会直接跳转到else的内容里,造成parent没有被给定指向内容,是空针,导致对空针的解引用
		//			}
		//			else
		//			{
		//				Node* pos = cur->left;
		//				delete cur;
		//				parent->left= pos;//这里也一样
		//			}
		//		}
		//		else if (cur->left == nullptr)
		//		{

		//			if (cur->_val > parent->_val)
		//			{
		//				Node* pos = cur->right;
		//				delete cur;
		//				parent->right = pos;//这里也一样
		//			}
		//			else
		//			{
		//				Node* pos = cur->right;
		//				delete cur;
		//				parent->left = pos;//这里也一样
		//			}

		//		}
		//		else
		//		{
		//			Node* _pos = cur;
		//			Node* _parent = cur;//注意控制好这个父节点,不然容易出问题
		//			cur = cur->left;
		//			while (cur->right)
		//			{
		//				_parent = cur;
		//				cur = cur->right;
		//			}
		//			_pos->_val = cur->_val;
		//			if (_pos->left == cur)//这种情况说明在要删除元素所在节点的左树部分的第一个节点就是左树最右边的节点,这时候应该在要删除元素所在节点的左边链接
		//			{
		//				_parent->left = cur->right;
		//			}
		//			else//这种情况说明左树最右的节点不是上面的那种情况,应该在左树最右节点的父节点的右节点上
		//			{
		//				_parent->right = cur->right;
		//			}
		//			delete cur;
		//		}
		//		return true;
		//	}
		//}
		//return false;
		if (root == nullptr)
			return false;
		
		Node* cur = root;
		Node* parent = nullptr;
		while (cur)
		{
			if (cur->_val < val)
			{
				parent = cur;
				cur = cur->right;
			}
			else if (cur->_val > val)
			{
				parent = cur;
				cur = cur->left;
			}
			else
			{
				if (cur->right == nullptr)
				{
					if (parent == nullptr)//在root处就找到该元素,也就是说parent还没有被赋予指向的对象,是空针(或者可以理解为root节点没有父节点),所以要单独来讨论,避免后面对空针的解引用(或者可以理解避免对不存在的父节点的左或右进行链接)
					{
						root = root->left;
						delete cur;
					}
					else
					{
						if (cur->_val > parent->_val)
						{
							Node* pos = cur->left;
							delete cur;
							parent->right = pos;
						}
						else
						{
							Node* pos = cur->left;
							delete cur;
							parent->left = pos;
						}
					}
				}
				else if (cur->left == nullptr)
				{
					if (parent == nullptr)//同上
					{
						root = root->right;
						delete cur;
					}
					else
					{
						if (cur->_val > parent->_val)
						{
							Node* pos = cur->right;
							delete cur;
							parent->right = pos;
						}
						else
						{
							Node* pos = cur->right;
							delete cur;
							parent->left = pos;
						}
					}

				}
				else
				{
					Node* _pos = cur;
					Node* _parent = cur;//注意控制好这个父节点,不然容易出问题
					cur = cur->left;
					while (cur->right)
					{
						_parent = cur;
						cur = cur->right;
					}
					_pos->_val = cur->_val;
					if (_pos->left == cur)//这种情况说明在要删除元素所在节点的左树部分的第一个节点就是左树最右边的节点,这时候应该在要删除元素所在节点的左边链接
					{
						_parent->left = cur->left;
					}
					else//这种情况说明左树最右的节点不是上面的那种情况,应该在左树最右节点的父节点的右节点上
					{
						_parent->right = cur->left;
					}
					delete cur;
				}
				return true;//找到并删除完毕,直接返回.
			}
		}
		return false;
	}
    template <class K>
	bool BStree<K>::EraseR(Node*& _root,const K& val)
	{
		if (_root == nullptr)
		{
			return false;
		}
		if (_root->_val > val)
		{
			return EraseR(_root->left, val);
		}
		else if (_root->_val < val)
		{
			return EraseR(_root->right, val);
		}
		else
		{
			if (_root->left == nullptr)//左边为空,让父节点领养子节点的右
			{
				Node* cur = _root;
				_root = _root->right;
				delete cur;
			}
			else if (_root->right == nullptr)//右节点为空,让父节点领养子节点的左
			{
				Node* cur = _root;
				_root = _root->left;
				delete cur;
			}
			else//左右都不为空,找以该节点为起点的左树部分的最大值替代该节点的值,或者找以该节点为起点的右树部分的最小值替代该节点的值
			{
				//modify_left_tree(_root->left, _root->_val);//方法一:递归找左树最大值取代该节点对应的值
				Node* cur = _root->left;//方法二:先通过循环找到左树最大值代替该值,然后通过递归EraseR再找到处于要被代替节点左树部分的最右边的节点(也就是左树部分的最大值对应节点)来删除该节点,这次递归最后找到该节点一定属于只有一个儿子或者没有儿子的情况,也就是说把转化为上面两种情况来处理
				while (cur->right)
				{
					cur = cur->right;
				}
				_root->_val = cur->_val;
				EraseR(_root->left, cur->_val);
			}
			return true;
		}
	}
    template <class K>
	void BStree<K>::modify_left_tree(Node*&_root, K&val)
	{
		if (_root->right ==nullptr)//当_root的下一个右为空,就停下,把该节点的值给要被替代的那个节点,并把这个结点给释放掉,且将该节点的左节点托孤给该节点的父节点
		{
			val = _root->_val;
			Node* cur = _root->left;
			delete _root;
 			_root = cur;
   			return;
		}
		modify_left_tree(_root->right, val);
	}
    template <class K>
	bool BStree<K>::_EraseR(const K& val)
	{
		return EraseR(root, val);
	}
    template <class K>
	void BStree<K>::inorder(Node* _root)
	{
		if (_root == nullptr)
		{
			return;
		}
		inorder(_root->left);
		std::cout << (_root->_val) << " ";
		inorder(_root->right);

	}
    template <class K>
	void BStree<K>::_inorder()
	{
		inorder(root);
		std::cout << std::endl;
	}

二叉搜索树性能

对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多。

但对于同一个关键码集合,如果各关键码插入的次序不同,可能得到不同结构的二叉搜索树:

最优情况下,二叉搜索树为完全二叉树(或者接近完全二叉树),其平均比较次数为:log2Nlog_2 Nlog2N

最差情况下,二叉搜索树退化为单支树(或者类似单支),其平均比较次数为:N2\frac{N}{2}2N

为了避免退化成单支树的情况,就有了AVL树和红黑树

AVL树

二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序,二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。因此,两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了一种解决上述问题的方法:

当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。

定义:一棵AVL树要么是空树,要么是具有以下性质的二叉搜索树:

  • 它的左右子树都是AVL树
  • 左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1)

AVL树如果它有n个结点,其高度可保持在O(log2n)O(log_2 n)O(log2n),搜索时间复杂度O(log2nlog_2 nlog2n)。
AVL树节点的定义

cpp 复制代码
template<class K,class V>
struct AVL_Tree_Node
{
	AVL_Tree_Node* left;//左孩子
	AVL_Tree_Node* right;//右孩子
	AVL_Tree_Node* parent;//父节点
	int _bf;//该节点的平衡因子
	std::pair<K, V>val;
	AVL_Tree_Node(const std::pair<K, V>&x)
		:left(nullptr),
		right(nullptr),
		parent(nullptr),
		_bf(0)
	{
		val = x;
	}
};

AVL树的插入

步骤:

  1. 按照二叉搜索树的方式插入新节点
  2. 新节点插入后,AVL树的平衡性可能会遭到破坏,此时就需要更新平衡因子,并检测是否破坏了AVL树的平衡性

具体来说

  • cur节点插入后,parent的平衡因子一定需要调整,在插入之前,parent的平衡因子分为三种情况:-1,0, 1,
  • 如果 如果cur插入到parent的左侧,只需给parent的平衡因子-1即可
  • 如果cur插入到parent的右侧,只需给parent的平衡因子+1即可
  • 此时:parent的平衡因子可能有三种情况:0,正负1, 正负2
  • 如果parent的平衡因子为0,说明插入之前parent的平衡因子为正负1,插入后被调整成0,此时满足AVL树的性质,插入成功,且此次插入并没有带来以parent为根的树的高度的变化,故不需要向上更新
  • 如果parent的平衡因子为正负1,说明插入前parent的平衡因子一定为0,插入后被更新成正负1,此时以parent为根的树的高度增加,需要继续向上更新
  • 如果parent的平衡因子为正负2,则parent的平衡因子违反平衡树的性质,需要对其进行旋转处理

AVL树的旋转

如果在一棵原本是平衡的AVL树中插入一个新节点,可能造成不平衡,此时必须调整树的结构,使之平衡化。根据节点插入位置的不同,AVL树的旋转分为四种:

1.新节点插入较高左子树的左侧---左左:右单旋

cpp 复制代码
void RotateR(Node* parent)
	{
		Node* SubL = parent->left;
		Node* SubLR = SubL->right;
		parent->left = SubLR;
		SubL->right = parent;
		Node* pparent = parent->parent;
		parent->parent = SubL;
		if (SubLR)
		{
			SubLR->parent =parent;
		}
		SubL->parent = pparent;
		if (pparent->val.first > SubL->val.first)
		{
			pparent->left = SubL;
		}
		else
		{
			pparent->right = SubL;
		}
		//更新平衡因子
		parent->_bf = SubL->_bf = 0;
	}
  1. 新节点插入较高右子树的右侧---右右:左单旋
cpp 复制代码
void RotateL(Node*parent)
	{
		Node* SubR = parent->right;
		Node* SubRL = SubR->left;
		parent->right = SubRL;
		SubR->left = parent;
		Node* pparent = parent->parent;
		parent->parent = SubR;
		if (SubRL)
		{
			SubRL->parent = parent;
		}
		SubR->parent = pparent;
		if (pparent->val.first > SubR->val.first)
		{
			pparent->left = SubR;
		}
		else
		{
			pparent->right = SubR;
		}
		//更新平衡因子
		parent->_bf = SubR->_bf = 0;
	}

3.新节点插入较高左子树的右侧---左右:先左单旋再右单旋

cpp 复制代码
void RotateLR(Node* parent)
	{
		Node* left = parent->left;
		Node* right = parent;
		Node* _parent = left->right;
		int _bf = _parent->_bf;
			RotateL(parent->left);
			RotateR(parent);
			//调整平衡因子
			if (_bf == 0)
			{
				left->_bf = 0;
				right->_bf = 0;
				_parent->_bf = 0;
			}
			else if(_bf == 1)
			{
				left->_bf = -1;
				right->_bf = 0;
				_parent->_bf = 0;
			}
			else if (_bf == -1)
			{
				left->_bf = 0;
				right->_bf = 1;
				_parent->_bf = 0;
			}
			else
			{
				assert(false);
			}
	}

将双旋变成单旋后再旋转,即:先对30进行左单旋,然后再对90进行右单旋,旋转完成后再考虑平衡因子的更新。

4。新节点插入较高右子树的左侧---右左:先右单旋再左单旋

cpp 复制代码
void RotateRL(Node* parent)
	{
		Node* left = parent;
		Node* right = parent->right;
		Node* _parent =right->left;
		int _bf = _parent->_bf;
		RotateR(parent->right);
		RotateL(parent);
		//调整平衡因子
		if (_bf == 0)
		{
			left->_bf = 0;
			right->_bf = 0;
			_parent->_bf = 0;
		}
		else if (_bf == 1)
		{
			left->_bf = -1;
			right->_bf = 0;
			_parent->_bf = 0;
		}
		else if (_bf == -1)
		{
			left->_bf = 0;
			right->_bf = 1;
			_parent->_bf = 0;
		}
		else
		{
			assert(false);
		}
	}

综上可得:

假如以parent为根的子树不平衡,即parent的平衡因子为2或者-2,分以下情况考虑

  1. parent的平衡因子为2,说明parent的右子树高,设parent的右子树的根为subR
    • 当subR的平衡因子为1时,执行左单旋
    • 当pSubR的平衡因子为-1时,执行右左双旋
  2. parent的平衡因子为-2,说明parent的左子树高,设parent的左子树的根为subL
    • 当subL的平衡因子为-1是,执行右单旋
    • 当subL的平衡因子为1时,执行左右双旋

旋转完成后,原parent为根的子树已经平衡,并且因为以parent为根的树的高度相较插入节点前没有变化,故不需要再向上更新。

** AVL树的验证**

1.满足二叉搜索树:如果中序遍历可得到一个有序的序列,就说明为二叉搜索树

cpp 复制代码
void inorder(Node* _root)
	{
		if (_root == nullptr)
			return;
		inorder(_root->left);
		cout << _root->val.first<< " ";
		inorder(_root->right);
	}

2.节点的平衡因子是否计算正确,且每个节点子树高度差的绝对值不超过1

cpp 复制代码
bool IsBalanceTree(Node*_root)
	{
		if (_root == nullptr)
			return true;
		int left = TreeHeight(_root->left);
		int right = TreeHeight(_root->right);
		int bf = right-left;
		if (_root->_bf != bf){
            cout << _root->val.first << "节点处平衡因子与该树的左右高度不符" << endl;
            return false;
        }
			
		return (bf == 0 || bf == -1 || bf == 1) && IsBalanceTree(_root->left) && IsBalanceTree(_root->right);
	}
	int TreeHeight(Node*_root)
	{
		if (_root == nullptr)
			return 0;
		int left = TreeHeight(_root->left);
		int right = TreeHeight(_root->right);
		return left > right ? left+1 : right+1;
	}

** AVL树的删除**

因为AVL树也是二叉搜索树,可按照二叉搜索树的方式将节点删除,然后再更新平衡因子,最差情况下一直要调整到根节点的位置。这里就不多说了。

** AVL树的性能**

AVL树是一棵绝对平衡的二叉搜索树,其要求每个节点的左右子树高度差的绝对值都不超过1,这样可以保证查询时高效的时间复杂度,即log2(N)log_2 (N)log2(N)。但是如果要对AVL树做一些结构修改的操作,性能非常低下,比如:插入时要维护其绝对平衡,旋转的次数比较多,更差的是在删除时,有可能一直要让旋转持续到根的位置。因此:如果需要一种查询高效且有序的数据结构,而且数据的个数为静态的(即不会改变),可以考虑AVL树,但如果结构经常修改,就不太适合。
完整代码

cpp 复制代码
template<class K,class V>
struct AVL_Tree_Node
{
	AVL_Tree_Node* left;//左孩子
	AVL_Tree_Node* right;//右孩子
	AVL_Tree_Node* parent;//父节点
	int _bf;//该节点的平衡因子
	std::pair<K, V>val;
	AVL_Tree_Node(const std::pair<K, V>&x)
		:left(nullptr),
		right(nullptr),
		parent(nullptr),
		_bf(0)
	{
		val = x;
	}
};
template<class K, class V>
class AVL_Tree
{
	typedef  AVL_Tree_Node<K, V> Node;
public:
	bool insert(std::pair<K, V>x)
	{
		Node* newnode = new Node(x);
		if (root == nullptr)
		{
			root = new Node(x);
		}
		else
		{
			Node* parent =nullptr;
			Node* cur = root;
			while (cur)
			{
				if (cur->val.first > x.first)
				{
					parent = cur;
					cur = cur->left;
				}
				else if (cur->val.first < x.first)
				{
					parent = cur;
					cur = cur->right;
				}
				else
				{
					return false;
				}
			}
			if (parent->val.first > x.first)
			{
				parent->left = newnode;
				newnode->parent = parent;
			}
			else
			{
				parent->right = newnode;
				newnode->parent = parent;
			}
		}
		Node* _parent = newnode->parent;
		Node* cur = newnode;
		while (_parent)
		{
			if (_parent->right == cur)
			{
				_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)//若_parent->_bf == 2,则cur一定是_parent右子树的根,故不用判断cur是不是右子树的根
				{
					RotateL(_parent);
				}
				else if (_parent->_bf == 2 && cur->_bf == -1)//若_parent->_bf == 2,则cur一定是_parent右子树的根,故不用判断cur是不是右子树的根
				{
					RotateRL(_parent);
				}
				else if (_parent->_bf == -2 && cur->_bf == -1)//若_parent->_bf == -2,则cur一定是_parent左子树的根,故不用判断cur是不是左子树的根
				{
					RotateR(_parent);
				}
				else if (_parent->_bf == -2 && cur->_bf == 1)//若_parent->_bf == -2,则cur一定是_parent左子树的根,故不用判断cur是不是左子树的根
				{
					RotateLR(_parent);
				}
				else
				{
					assert(false);
				}
				break;
			}
		}
		return true;
	}
	void _inorder()
	{
		inorder(root);
		cout << endl;
	}
	bool _IsBalanceTree()
	{
		return IsBalanceTree(root);
	}




protected:
	bool IsBalanceTree(Node*_root)
	{
		if (_root == nullptr)
			return true;
		int left = TreeHeight(_root->left);
		int right = TreeHeight(_root->right);
		int bf = right-left;
		if (_root->_bf != bf){
            cout << _root->val.first << "节点处平衡因子与该树的左右高度不符" << endl;
            return false;
        }
			
		return (bf == 0 || bf == -1 || bf == 1) && IsBalanceTree(_root->left) && IsBalanceTree(_root->right);
	}
	int TreeHeight(Node*_root)
	{
		if (_root == nullptr)
			return 0;
		int left = TreeHeight(_root->left);
		int right = TreeHeight(_root->right);
		return left > right ? left+1 : right+1;
	}
	void inorder(Node* _root)
	{
		if (_root == nullptr)
			return;
		inorder(_root->left);
		cout << _root->val.first<< " ";
		inorder(_root->right);
	}
	void RotateL(Node*parent)
	{
		Node* SubR = parent->right;
		Node* SubRL = SubR->left;
		parent->right = SubRL;
		SubR->left = parent;
		Node* pparent = parent->parent;
		parent->parent = SubR;
		if (SubRL)
		{
			SubRL->parent = parent;
		}
		SubR->parent = pparent;
		if (pparent->val.first > SubR->val.first)
		{
			pparent->left = SubR;
		}
		else
		{
			pparent->right = SubR;
		}
		//更新平衡因子
		parent->_bf = SubR->_bf = 0;
	}
	void RotateR(Node* parent)
	{
		Node* SubL = parent->left;
		Node* SubLR = SubL->right;
		parent->left = SubLR;
		SubL->right = parent;
		Node* pparent = parent->parent;
		parent->parent = SubL;
		if (SubLR)
		{
			SubLR->parent =parent;
		}
		SubL->parent = pparent;
		if (pparent->val.first > SubL->val.first)
		{
			pparent->left = SubL;
		}
		else
		{
			pparent->right = SubL;
		}
		//更新平衡因子
		parent->_bf = SubL->_bf = 0;
	}
	void RotateLR(Node* parent)
	{
		Node* left = parent->left;
		Node* right = parent;
		Node* _parent = left->right;
		int _bf = _parent->_bf;
			RotateL(parent->left);
			RotateR(parent);
			//调整平衡因子
			if (_bf == 0)
			{
				left->_bf = 0;
				right->_bf = 0;
				_parent->_bf = 0;
			}
			else if(_bf == 1)
			{
				left->_bf = -1;
				right->_bf = 0;
				_parent->_bf = 0;
			}
			else if (_bf == -1)
			{
				left->_bf = 0;
				right->_bf = 1;
				_parent->_bf = 0;
			}
			else
			{
				assert(false);
			}
	}
	void RotateRL(Node* parent)
	{
		Node* left = parent;
		Node* right = parent->right;
		Node* _parent =right->left;
		int _bf = _parent->_bf;
		RotateR(parent->right);
		RotateL(parent);
		//调整平衡因子
		if (_bf == 0)
		{
			left->_bf = 0;
			right->_bf = 0;
			_parent->_bf = 0;
		}
		else if (_bf == 1)
		{
			left->_bf = -1;
			right->_bf = 0;
			_parent->_bf = 0;
		}
		else if (_bf == -1)
		{
			left->_bf = 0;
			right->_bf = 1;
			_parent->_bf = 0;
		}
		else
		{
			assert(false);
		}
	}
	Node* root=nullptr;
};
相关推荐
Genios2 小时前
今天是我正式开启Python学习之旅的第7天
开发语言·python·学习
重庆小透明2 小时前
Redis 九大数据结构:从原理到实战场景
数据结构·数据库·redis
Boop_wu2 小时前
[Java 算法] 快速排序和快速选择排序(※)
数据结构·算法·排序算法
怪我冷i2 小时前
在win11进行Rust Web 开发,采用Salvo框架
开发语言·前端·rust
吴声子夜歌2 小时前
Node.js——os操作系统模块
开发语言·node.js·php
曹牧2 小时前
Java:驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立连接
java·开发语言·ssl
郝学胜-神的一滴2 小时前
Linux高性能网络编程基石:epoll核心与文件描述符限制全解
linux·服务器·网络·c++·后端
cch89182 小时前
PHP vs C++:10倍性能差距的编程语言对决
android·java·开发语言
司马万2 小时前
RUST基础1----数据类型
开发语言·算法·rust