C++学习之第二十一天-vector容器底层实现以及类模板实现快排、堆排

1.Vector容器底层实现

1.空间的申请和释放:allocate和deallocate
//空间的申请,申请的是原始的,未初始化的空间
pointer allocate( size_type n, const void * hint = 0 );
T* allocate( std::size_t n, const void * hint); 
T* allocate( std::size_t n );
//空间的释放
void deallocate( T* p, std::size_t n );

2.对象的销毁和释放:construct 和 destroy
//对象的构建,在指定的未初始化的空间上构建对象,使用的是定位new表达式
void construct( pointer p, const_reference val );
//对象的销毁
void destroy( pointer p )

3.vector容器中有三个指针:

     T *_start;//指向数组中的第一个元素
     T *_finish;//指向最后一个实际元素之后的那个元素
     T *_end_of_storage;//指向数组本身之后的位置

#include <iostream>
#include <memory>
using std::cout;
using std::endl;

template <class T>
class Vector
{
public:
    using iterator = T *;//迭代器本身是一个广义的指针
    
    Vector()//构造函数
    :_start(nullptr),
    _finish(nullptr),
    _end_of_storage(nullptr)
    {}

    ~Vector();
    void push_back(const T &t);
    void pop_back();

    iterator begin()//用于打印
    {
        return _start;
    }
    iterator end()
    {
        return _finish;
    }
    int size()const
    {
        return _finish-_start;
    }
    int capacity()const
    {
        return _end_of_storage - _start;
    }
private:
    void reallocator();//重新分配内存,动态扩容要用的

private:
     static std::allocator<T> _alloc;//静态成员声明
    T *_start;//指向数组中的第一个元素
    T *_finish;//指向最后一个实际元素之后的那个元素
    T *_end_of_storage;//指向数组本身之后的位置
};
//静态成员变量类外定义
template <class T>
std::allocator<T> Vector<T>::_alloc;

template<class T>
Vector<T>::~Vector()//析构函数:先释放对象destroy,再销毁空间deallocate
{
    //先销毁对象,再释放空间
    if(_start)
    {
        while(_finish !=_start)
        {
            _alloc.destroy(--_finish);
        }
        _alloc.deallocate(_start,capacity());
    }
}
template <class T>
void Vector<T>::reallocator()//自己实现的扩容
{
    int oldCapacity = capacity();
    int newCapacity = 2 * oldCapacity > 0? 2*oldCapacity:1;

    T *ptmp = _alloc.allocate(newCapacity);//申请空间

    //考虑边界条件
    if(_start)
    {
        //std::copy(_start,_finish,ptmp);//拷贝老空间的数据到新空间
        std::uninitialized_copy(_start,_finish,ptmp);//ptmp上没有对象,所以使用未初始化的copy算法
        while(_finish!=_start)
        {
            //考虑边界条件
            _alloc.destroy(--_finish);//释放老空间中的对象
        }//执行完后,_start和_finish所执行的空间的对象都被销毁
        _alloc.deallocate(_start,oldCapacity);//释放老空间
    }
    //重新置位
    _start = ptmp;
    _finish = _start+oldCapacity;
    _end_of_storage = _start + newCapacity;


}
template<class T>
void Vector<T>::push_back(const T &t)//
{
    if(size() == capacity())//
    {
       reallocator();//vector满了,进行扩容
    }
    if(size()<capacity())
    {
        _alloc.construct(_finish++,t);//对象的构建
    }
}
template<class T>
void Vector<T>:: pop_back()
{
    //pop_back(),把空间里的对象销毁就行了,不用管空间内存
    if(size()>0)
    {
        _alloc.destroy(--_finish);//对象的销毁
    }
}
template <typename Container>
void display(const Container &c)
{
    cout<<"c.size()="<<c.size()<<endl;
    cout<<"c.capacity()="<<c.capacity()<<endl;
}
void test01()
{
    Vector<int> number;
    display(number);
    number.push_back(1);
    number.push_back(3);
    number.push_back(5);
    number.push_back(7);
    number.push_back(9);

    display(number);
    
    for(auto &elem: number)
    {
        cout<<elem<<" ";
    } 
    cout<<endl;
}
int main()
{
    test01();
    return 0;
}

2.类模板实现堆排序

#include <iostream>
#include <math.h>
#include <vector>
#include <ostream>

using std::cout;
using std::cin;
using std::endl;
using std::vector;

template <typename T>
void swap(T &lhs, T &rhs)
{
    auto temp = lhs;
    lhs = rhs;
    rhs = temp;
}
template <typename T, typename Compare=std::less<T>>
class HeapSort
{
public:
    HeapSort(T *arr, size_t size, Compare);//构造函数
    void heapAdjust(size_t,size_t,Compare &);//自顶向下进行调整大根堆
    void sort(Compare&);//排序接口
    void print();

private:
    vector<T> _vec;
};
template <typename T, typename Compare>
void HeapSort<T,Compare>::heapAdjust(size_t adjustPos, size_t arrlen, Compare &com)
{
    //把某个结点下的树,调整为大根堆
    size_t dad = adjustPos;//
    size_t son = 2*adjustPos + 1;//左孩子
    while(son < arrlen)
    {
        if(son + 1 <arrlen &&com(_vec[son], _vec[son+1]))//右孩子存在且节点值比左孩子大
        {
            ++son;//son指向右孩子
        }
		//父亲结点小于孩子结点
        if(com(_vec[dad],_vec[son]))//_vec[dad] < _vec[son]
        {
            swap(_vec[dad],_vec[son]);//互换
            dad = son;
            son = 2*dad+1;
        }
        else
        {
            break;
        }
    }
}
template <typename T,typename Compare>
HeapSort<T,Compare>::HeapSort(T *arr, size_t size,Compare com)
{
    for(int idx = 0;idx<size; ++idx)//1.把数组数据存入vector
    {
        _vec.push_back(arr[idx]);
    }
    //2.建堆,对_vec中的元素建立大根堆,从第一个非叶子结点开始调整,一直调整到根节点_vec[0]
    for(int i = size/2 - 1; i >=0 ; i--)
    {
        heapAdjust(i, size,com);
    }

    //3.调整为大根堆后,arr[0]是数组中最大的值
    swap(arr[0], arr[size-1]);//交换
    sort(com);//排序
}
template <typename T,typename Compare>
void HeapSort<T,Compare>::sort(Compare &com)//排序
{
    size_t size = _vec.size();
    for(size_t i = size; i > 1;i--)
    {
        heapAdjust(0,i,com);//每次与最后一个元素对调完,重新调节根节点,调整的数组长度每次减1
        swap(_vec[0],_vec[i-1]);//把大的元素放到正确的位置,再调整整棵树为大根堆
    }
}
template <typename T, typename Compare>
void HeapSort<T,Compare>::print()
{
    for(auto &elem : _vec)
    {
        cout<< elem << " ";
    }
    cout << endl;
}
void test01()
{
    int arr[10] = {1, 2, 6, 3, 4, 8, 5, 7, 9, 10};
    HeapSort<int> hs(arr, 10, std::less<int>());
    hs.print();
    cout << endl;
}
int main()
{
    test01();
    return 0;
}

3.类模板实现快速排序

//类模板实现快速排序
#include <iostream>
#include <math.h>
#include <vector>
#include <ostream>

using std::cout;
using std::cin;
using std::endl;
using std::vector;
template<typename T>
void swap(T &lhs,T &rhs)
{
    auto temp= lhs;
    lhs = rhs;
    rhs = temp;
}
template <typename T, typename Compare=std::greater<T>>
class MyQsort
{
public:
    MyQsort(T *arr,size_t size, Compare);//构造函数:
    void quick(int left,int right,Compare &);//递归处理
    int partition(int left, int right, Compare &);//分堆
    void print();//打印
private:
    vector<T> _vec;
};
template <typename T, typename Compare>
void MyQsort<T, Compare>::print()
{
    for(auto &elem: _vec)
    {
        cout<<elem<<" ";
    }
    cout<<endl;
        
}
template <typename T, typename Compare>//构造函数:先把数组内容push_back到容器,再调用排序接口
MyQsort<T,Compare>::MyQsort(T *arr, size_t size, Compare com)
{
    for(size_t i=0; i<size;i++)
    {
        _vec.push_back(arr[i]);
    }
    quick(0,_vec.size()-1,com);//快排
}
template <typename T, typename Compare>//快速排序
void MyQsort<T, Compare>::quick(int left, int right, Compare &com)
{
    int pivot;
    if(left<right)
    {
        pivot = partition(left, right,com);
        quick(left,pivot-1,com);
        quick(pivot+1, right,com);
    }
}
template <typename T,typename Compare>//分治
int MyQsort<T,Compare>:: partition(int left,int right,Compare &com)
{
    int indexi,indexk;
    for(indexi=left, indexk = left; indexi<right;indexi++)
    {
        if(com(_vec[indexi],_vec[right]))//以数组最右边的元素作为pivot
        {
            swap(_vec[indexi],_vec[indexk]);
            ++indexk;//indexk记录的是小于pivot的元素个数,
        }
    }
    swap(_vec[indexk], _vec[right]);//交换后indexk左边是小于pivot的元素,右边是大于Pivot的元素
    return indexk;//返回indexk
}
void test01()
{
    int arr[10] = {99,88,77,12,34,10,9,8,6,76};
    MyQsort<int> q(arr,10,std::greater<int>());
    q.print();
}
int main()
{
    test01();
    return 0;
}

3.类模板实现归并排序

#include <iostream>
#include <string>
#include <time.h>
#include <math.h>
#include <vector>
#include <ostream>
#include <iterator>
#include <algorithm>
using std::copy;
using std::cout;
using std::cin;
using std::endl;
using std::vector;
using std::string;
class Person//自定义类型Person
{
   friend std::ostream& operator<<(std::ostream &os,const Person &rhs);
public:
   string get_age()const
   {
       return _age;
   }
    Person(string name = "", string age = "")
    :_name(name),_age(age)
    {
    }
private:
    string _name;
    string _age;
};
std:: ostream& operator<<(std::ostream &os,const Person &rhs)
{
    cout<<rhs._name<<" "<<rhs._age;
    return os;
}
namespace std//命名空间的扩展
{
template<>
struct less<Person>//仿函数,用于自定义类型的比较
{
    bool operator()(const Person &lhs, const Person &rhs)
    {
        return lhs.get_age()< rhs.get_age();
    }
};
}
template <typename T,typename Compare = std::less<T>>
class MergeSort
{
public:
    MergeSort(T *arr,size_t , Compare com);
    void print();
    void mergeSort(size_t left, size_t right, Compare &com);
    void merge(size_t left, size_t mid, size_t right, Compare &com);
private:
    vector<T> _vec;
};
template <typename T, typename Compare>
MergeSort<T,Compare>:: MergeSort(T *arr, size_t arrlen, Compare com)
{
    for(int idx = 0; idx<arrlen;idx++)
    {
        _vec.push_back(arr[idx]);
    }

    mergeSort(0,arrlen-1, com);//归并排序
}

template <typename T, typename Compare>//二路归并
void MergeSort<T,Compare>::mergeSort(size_t left, size_t right, Compare &com)
{
    if(left<right)
    {
        size_t mid = (left+right)/2;
        mergeSort(left,mid,com);
        mergeSort(mid+1,right,com);
        merge(left,mid,right,com);//归并
    }
}
template <typename T,typename Compare>
void MergeSort<T, Compare>::merge(size_t left, size_t mid, size_t right, Compare &com)
{
    vector<T> temp;//临时容量
    copy(_vec.begin(),_vec.end(), std::back_insert_iterator<vector<T>>(temp));
    //把_vec中的内容拷贝到temp,temp用来进行遍历,在归并的过程中,重写_vec容器里面的元素,按顺序存储
    int left_1 = left; 
    int k = left;//从左开始,作为_vec的下标,从小到大进行存储
    int left_2 = mid + 1;
    while(left_1 <=mid && left_2 <= right)
    {
        if(com(temp[left_1], temp[left_2]))
        {
            _vec[k++] = temp[left_1++];
        }
        else
        {
            _vec[k++] = temp[left_2++];
        }
    }
    while(left_1 <= mid)
    {

        _vec[k++] = temp[left_1++];
    }
    while(left_2<=right)
    {
        _vec[k++] = temp[left_2++];
    }
}
template <typename T, typename Compare>
void MergeSort<T,Compare>::print()
{
    for(auto &elem:_vec)
    {
        cout<<elem<<" ";
    }
    cout<<endl;
}
void test01()
{
    srand(time(NULL));
    int arr[10]={0};
    for(int idx=0;idx<10;idx++)
    {
        arr[idx] = rand()%100;
    }

    MergeSort<int> my_merge(arr, 10, std::less<int>());
    my_merge.print();
}
void test02()
{
    Person p1("孙悟空","550");
    Person p2("猪八戒","666");
    Person p3("沙僧","444");
    Person p4("唐僧","999");
    Person p5("白龙马","888");
    Person arr[5] = {p1,p2,p3,p4,p5};
    for(int idx=0;idx < 5;idx++)
    {
        cout<<arr[idx]<<endl;
    }

    MergeSort<Person> my_sort(arr, 5, std::less<Person>());
    my_sort.print();
}
int main()
{
    test01();
    test02();//自定义类型排序
    return 0;
}

4.按照以上三个排序的方式依次实现类模板选择排序、插入排序、计数排序。。。

2021.11.24记

C++基础(2021/10/26开始),跟着视频已过一遍,后续继续加强学习,巩固复习,路漫漫其修远兮。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

给你。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值