c++:容器&顺序配置器

1.容器的概念

容器是保存一组给定类型对象的类型。每个标准类型都是一个模版类型。为了定义一个容器,我们必须指定保存在容器中的元素的类型。除了array之外,标准库容器都是大小可变的

2.容器的分类

容器分为两类: (1)关联容器 (2)顺序容器

顺序容器:保存相同类型对象有序集合的类型。顺序容器中的元素通过位置来访问
关联容器:元素的位置由相关联的关键字值决定的。也就是所关联容器中元素的位置与关键字关联。

顺序容器分为三种:
  • vector 支持快速随机访问
  • list 支持快速插入/删除
  • deque 双端队列

下面介绍顺序容器:(顺序容器都提供了快速顺序访问元素的能力)

(1)vector:可变大小数组,支持快速的随机访问,只能在末尾实现高效的插入/删除。
(2)list:双向链表,支持任意位置快速插入,插入和删除速度都很快,很方便。
(3)deque:双端队列,支持快速随机访问,在首尾插入、删除速度很快。
(4)forward_lis:单向链表,只能顺序访问,支持任意位置的快速插入/删除。
(5)array:固定大小数组,支持随机快速访问,不能删除或填加元素

顺序容器的使用方法:

(1)除了array固定大小,其他顺序容器都提供高效、灵活的内存管理,可以添加、删除、扩张和收缩容器。
(2)string 和 vector 等容器将元素保存在连续的内存空间中,即其元素的内存是连续存储的,可以支持下标操作。
(3)通常使用 vector 是很好的选择,除非有更好的理由选择其他容器。
(4)如果在读取时需要插入元素,但是随后需要使用随机访问元素,根据情况可以选择sort重排vector,更通用情况是输入阶段使用list,输入完成后,将list中的内容放入到一个vector中。

顺序容器配置器:

关于new,delete与配置器:

对于new,我们都是先配置内存,然后调用对应的构造函数;而delete则是先调用对应的析构函数,然后释放内存。

只需要开辟一定大小内存,并不想去构造对象,删除是只进行对象析构,但不释放这块内存,以后继续留用。

使用容器的空间配置器的目的:把对象的内存开辟和对象的构造分开;把对象的析构和内存释放分开。

实现容器的配置器:
template<typename T>
class Allocator
{
public:
	T* allocate(size_t size) // 开辟内存
	{
		return (T*)malloc(size);
	}
	void deallocate(void *ptr) // 释放内存
	{
		free(ptr);
	}
	void construct(T *ptr, const T &val) // 构造
	{
		new (ptr) T(val);
	}
	void destroy(T *ptr) // 析构
	{
		ptr->~T();
	}
};


实现带空间配置器Vector

// 实现容器的空间配置器
template<typename T>
class Allocator
{
public:
	T* allocate(size_t size) // 开辟内存
	{
		return (T*)malloc(size);
	}
	void deallocate(void *ptr) // 释放内存
	{
		free(ptr);
	}
	void construct(T *ptr, const T &val) // 构造
	{
		new (ptr) T(val);
	}
	void destroy(T *ptr) // 析构
	{
		ptr->~T();
	}
};

template<typename T, 
		typename allocator = Allocator<T>>
class Vector
{
public:
	// 按指定size进行构造,size个空间,没有元素
	Vector(int size = 0)
		:mCur(0), mSize(size)
	{
		if (size == 0)
		{
			mpVec = nullptr;
		}	
		else
		{
			//mpVec = new T[mSize];
			mpVec = mAllocator.allocate(mSize * sizeof(T));
		}
	}
	
	// 按指定size进行构造,添加size个元素,元素值是val
	Vector(int size, const T &val)
		:mCur(size), mSize(size)
	{
		mpVec = new T[mSize];
		for (int i = 0; i < mSize; ++i)
		{
			mpVec[i] = val;
		}
	}
	
	// 按[first, last)区间的元素来构造Vector
	Vector(T *first, T *last)
	{
		int size = last - first;
		mSize = size;
		mpVec = new T[mSize];
		for (mCur=0; first < last; ++first)
		{
			mpVec[mCur++] = *first;
		}
	}
	
	~Vector() 
	{ 
		//delete[]mpVec; 
		// 析构有效的对象
		for (int i = 0; i < mCur; ++i)
		{
			mAllocator.destroy(mpVec+i);
		}
		// 释放内存
		mAllocator.deallocate(mpVec);
	}
	
	// 从末尾添加元素
	void push_back(const T &val)
	{
		if (full())
			resize();
		//mpVec[mCur++] = val;
		mAllocator.construct(mpVec+mCur, val);
		mCur++;
	}
	
	// 从末尾删除元素
	void pop_back()
	{
		if (empty())
			return;
		--mCur;
		mAllocator.destroy(mpVec+mCur);
	}
	
	bool full()const { return mCur == mSize; }
	bool empty()const { return mCur == 0; }
	
	// 返回容器元素的个数
	int size()const { return mCur; }
	
	// Vector的迭代器
	class iterator
	{
	public:
		iterator(T *p = nullptr) :_ptr(p) {}
		bool operator!=(const iterator &it)
		{
			return _ptr != it._ptr;
		}
		void operator++() { _ptr++; }
		T& operator*() { return *_ptr; }
	private:
		T *_ptr;
	};
	iterator begin() { return iterator(mpVec); }
	iterator end() { return iterator(mpVec + size()); }
	
private:
	T *mpVec;
	int mCur;
	int mSize;
	allocator mAllocator;  // 存储容器的空间配置器

	// 容器内存2倍扩容
	void resize()
	{
		if (0 == mSize)
		{
			mCur = 0;
			mSize = 1;
			mpVec = mAllocator.allocate(mSize * sizeof(T));
		}
		else
		{
			T *ptmp = mAllocator.allocate(2 * mSize * sizeof(T));
			for (int i = 0; i < mSize; ++i)
			{
				mAllocator.construct(ptmp + i, mpVec[i]);	
			}
			for (int i = 0; i < mSize; ++i)
			{
				mAllocator.destroy(mpVec + i);	
			}
			mAllocator.destroy(mpVec);
			mpVec = ptmp;
			mSize *= 2;
		}
	}
};

class A
{
public:
	A() :p(new int[2]) { cout << "A()" << endl; }
	A(const A &src) { cout << "A(const A&)" << endl; }
	~A() { cout << "~A()" << endl; }
private:
	int *p;
};
int main()
{
	A a1, a2, a3;
	// 这里只需要空间,不需要构造对象  malloc
	Vector<A> vec(100);
	vec.push_back(a1);
	vec.push_back(a2);
	vec.pop_back();
	vec.push_back(a3);
}


实现不带空间配置器vector

template<typename T>
class Vector
{
public:
	// 按指定size进行构造,size个空间,没有元素
	Vector(int size = 0):mCur(0),mSize(size)
	{
		if (size == 0)
		{
			mpVec = nullptr;
		}
		else
		{
			mpVec = new T[mSize];
		}
	}
	// 按指定size进行构造,添加size个元素,元素值是val
	Vector(int size, const T &val = T()):mCur(size)
	{
		mpVec = new T[size];
		mSize = size;
		for (int i = 0; i < size; ++i)
		{
			mpVec[i] = val;
			
		}
	}
	// 按[first, last)区间的元素来构造Vector
	Vector(T *first, T *last)
	{
		int size = last - first;
		mSize = size;
		mpVec = new T[mSize];
		for (mCur = 0; mCur < size; first++)
		{
			mpVec[mCur++] = *first;
		}
	}
	// 从末尾添加元素
	void push_back(const T &val)
	{
		if (full())
		{
			resize();
		}
		mpVec[mCur++] = val;
	}
	// 从末尾删除元素
	void pop_back()
	{
		if (empty())
		{
			return;
		}
		--mCur;
	}
	bool full()const
	{
		return mCur == mSize;
	}
	bool empty()const
	{
		return mSize == 0;
	}
	// 返回容器元素的个数
	int size()const
	{
		return mCur;
	}
	// Vector的迭代器
	class iterator
	{
	public:
		iterator(T *argv = nullptr):_mpVec(argv) {}
		void operator++()
		{
			_mpVec++;
		}
		bool operator!=(const iterator &rhs)
		{
			return _mpVec != rhs._mpVec;
		}
		T& operator*()
		{
			return *_mpVec;
		}
	private:
		T *_mpVec;
	};
	iterator begin()
	{
		return iterator(mpVec);
	}
	iterator end()
	{
		return iterator(mpVec + size());
	}
	
private:
	T *mpVec;
	int mCur;
	int mSize;
	// 容器内存2倍扩容
	void resize()
	{
		if (empty())
		{
			mpVec = new T[1];
			mSize = 1;
			mCur = 0;
		}
		else
		{
			T *tmp = new T[mSize * 2];
			for (int i = 0; i < mSize; i++)
			{
				tmp[i] = mpVec[i];
			}
			delete []mpVec;
			mpVec = tmp;
			mSize *= 2;
		}
	}
};
int main()
{
	Vector<int> vec1; // 底层不开辟空间
	for (int i = 0; i < 20; ++i)
	{
		vec1.push_back(rand() % 100 + 1);
	}
	cout << vec1.size() << endl;
	
	// 用通用的迭代器遍历方式,遍历vec1,并打印容器中所有的元素值
	Vector<int>::iterator it = vec1.begin();
	for (; it != vec1.end() ; ++it)
	{
		cout << *it << " ";
	}
	cout << endl;

	Vector<int> vec2(10, 20);

	Vector<int>::iterator it1 = vec2.begin();
	for (; it1 != vec2.end() ; ++it1)
	{
		cout << *it1 << " ";
	}
	cout << endl;

	int arr[] = { 12,4,56,7,89 };
	Vector<int> vec3(arr, arr + sizeof(arr) / sizeof(arr[0]));

	Vector<int>::iterator it2 = vec3.begin();
	for (; it2 != vec3.end() ; ++it2)
	{
		cout << *it2 << " ";
	}
	cout << endl;
	return 0;
}


在使用Python来安装geopandas包时,由于geopandas依赖于几个其他的Python库(如GDAL, Fiona, Pyproj, Shapely等),因此安装过程可能需要一些额外的步骤。以下是一个基本的安装指南,适用于大多数用户: 使用pip安装 确保Python和pip已安装: 首先,确保你的计算机上已安装了Python和pip。pip是Python的包管理工具,用于安装和管理Python包。 安装依赖库: 由于geopandas依赖于GDAL, Fiona, Pyproj, Shapely等库,你可能需要先安装这些库。通常,你可以通过pip直接安装这些库,但有时候可能需要从其他源下载预编译的二进制包(wheel文件),特别是GDAL和Fiona,因为它们可能包含一些系统级的依赖。 bash pip install GDAL Fiona Pyproj Shapely 注意:在某些系统上,直接使用pip安装GDAL和Fiona可能会遇到问题,因为它们需要编译一些C/C++代码。如果遇到问题,你可以考虑使用conda(一个Python包、依赖和环境管理)来安装这些库,或者从Unofficial Windows Binaries for Python Extension Packages这样的网站下载预编译的wheel文件。 安装geopandas: 在安装了所有依赖库之后,你可以使用pip来安装geopandas。 bash pip install geopandas 使用conda安装 如果你正在使用conda作为你的Python包管理,那么安装geopandas和它的依赖可能会更简单一些。 创建一个新的conda环境(可选,但推荐): bash conda create -n geoenv python=3.x anaconda conda activate geoenv 其中3.x是你希望使用的Python版本。 安装geopandas: 使用conda-forge频道来安装geopandas,因为它提供了许多地理空间相关的包。 bash conda install -c conda-forge geopandas 这条命令会自动安装geopandas及其所有依赖。 注意事项 如果你在安装过程中遇到任何问题,比如编译错误或依赖问题,请检查你的Python版本和pip/conda的版本是否是最新的,或者尝试在不同的环境中安装。 某些库(如GDAL)可能需要额外的系统级依赖,如地理空间库(如PROJ和GEOS)。这些依赖可能需要单独安装,具体取决于你的操作系统。 如果你在Windows上遇到问题,并且pip安装失败,尝试从Unofficial Windows Binaries for Python Extension Packages网站下载相应的wheel文件,并使用pip进行安装。 脚本示例 虽然你的问题主要是关于如何安装geopandas,但如果你想要一个Python脚本来重命名文件夹下的文件,在原始名字前面加上字符串"geopandas",以下是一个简单的示例: python import os # 指定文件夹路径 folder_path = 'path/to/your/folder' # 遍历文件夹中的文件 for filename in os.listdir(folder_path): # 构造原始文件路径 old_file_path = os.path.join(folder_path, filename) # 构造新文件名 new_filename = 'geopandas_' + filename # 构造新文件路径 new_file_path = os.path.join(folder_path, new_filename) # 重命名文件 os.rename(old_file_path, new_file_path) print(f'Renamed "{filename}" to "{new_filename}"') 请确保将'path/to/your/folder'替换为你想要重命名文件的实际文件夹路径。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值