数据结构之vector的实现

数据结构之vector的实现

Vector类分为:构造函数、析构函数、只读函数、修改函数、私有函数、成员变量(数据区和大小)

# include <iostream>
# include <algorithm>
# include <cstdlib>

# define DEFAULT_CAPACITY 3

template <typename T> struct pp {
    
    
	void operator()(T & e) {
    
    
		std::cout << e << "\n";
	}
};

void bubbleSort(int * a, int n = 13)
{
    
    
	bool isSorted = false;
	for (int i = n - 1; !isSorted && i > 0; --i) // 待排序范围
	{
    
    
		isSorted = true;
		for (int j = 0; j < i; ++j) // 从开头到无序的前一个位置
		{
    
    
			if (a[j] > a[j + 1])
			{
    
    
				std::swap(a[j], a[j + 1]);
				isSorted = false;
			}
		}
	}
	return;
}

template <typename T> class Vector
{
    
    
public:
	// 析构函数
	~Vector() {
    
     delete []elem; }

	// 构造函数

	Vector(int c = DEFAULT_CAPACITY, int s = 0, T v=0)  // c 容量 s 规模 v 每个元素初始值
	{
    
    
		elem = new T[c];
		for (size = 0; size < s; ++size)
		{
    
    
			elem[size] = v;
		}
	}


	Vector(const Vector<T> & v) {
    
     copyForm(v.elem, 0, Vector.size); }

	Vector(T const * A, int lo, int hi) {
    
     copyForm(A, lo, hi); }

	// 运算符重载
	Vector<T>& operator = (const Vector<T> & v) // 
	{
    
    
		delete[]elem;
		elem = new T[v.capacity];
		copyFrom(v, 0, v.size);
		return *this;
	}
	T& operator[](int rank)
	{
    
    
		return elem[rank];
	}

	//  置乱
	void permute(void)
	{
    
    
		for (int i = size - 1; i > 0; --i)
		{
    
    
			std::swap(elem[i], elem[rand() % (i + 1)]);
		}
	}

	void unsort(int lo, int hi)
	{
    
    
		T * V = elem + lo;
		for (int i = hi - lo - 1; i > 0; --i)
		{
    
    
			std::swap(V[i], V[rand() % (i + 1)]);
		}
	}

	// 查找
	int find(T const & e, int lo, int hi)
	{
    
    
		for (; hi > lo && e != elem[hi - 1]; hi--);
		return hi;
	}

	// 插入
	void insert(T const & e, int rank)
	{
    
    
		expand();
		for (int i = size; i > rank; --i)
		{
    
    
			elem[i] = elem[i - 1];
		}
		elem[rank] = e;
		++size;
	}

	// 删除
	void remove(int lo, int hi)
	{
    
    
		if (lo == hi) return;
		for (int i = lo; i < size - hi + lo; ++i)
		{
    
    
			elem[i] = elem[i + hi - lo];
		}
		size -= hi - lo;
		shrink();
	}

	void remove(int rank)
	{
    
    
		remove(rank, rank + 1);
	}

	//  唯一化 返回删了多少个
	int unique(void)
	{
    
    
		int oldSize = size;
		for (int i = 0; i < size; ++i)
		{
    
    
			if (find(elem[i], i + 1, size)) remove(i);
			size--;
		}
		return oldSize - size;
	}

	// 遍历
	template <typename T2> void traverse(T2 & visit)
	{
    
    
		for (int i = 0; i < size; ++i)
		{
    
    
			visit(elem[i]);
		}
	}

	//*****************************************************以下是有序向量操作***************************************************

	// 有序性甄别,返回无序对儿数
	int disOrdered(void) const
	{
    
    
		int n = 0;
		for (int i = 0; i < size - 1; ++i)
		{
    
    
			if (elem[i] > elem[i + 1]) ++n;
		}
		return n;
	}

	// 针对有序vector的唯一化,O(n)
	void unique_ordered(void)
	{
    
    
		int i = 0, j = 1;
		while (j < size)
		{
    
    
			if (elem[i] == elem[j]) ++j;
			else
			{
    
    
				elem[i + 1] = elem[j];
				++i;
				++j;
			}
		}
		size = i + 1;
	}

	// 二分查找,找最靠右的等于e的元素的位置
	int search(const T & e)
	{
    
    
		int lo = 0; hi = size;
		while (lo < hi)
		{
    
    
			int mi = (lo + hi) / 2;
			if (e < mi) hi = mi;
			else lo = mi + 1;
		}
		return lo-1;
	}

protected:

	int size;
	int capacity;
	T * elem; //数据区

	void copyForm(T const * A, int lo, int hi) // 左开右闭,仅在构造时使用,所以从0开始装
	{
    
    
		elem = new T[(hi - lo) * 2];
		capacity = (hi - lo) * 2;
		size = 0;

		while (lo < hi)
		{
    
    
			elem[size] = A[lo];
			++size;
			++lo;
		}
	}

	void expand(void)
	{
    
    
		if (size < capacity) return;

		if (capacity < DEFAULT_CAPACITY) capacity = DEFAULT_CAPACITY;
		capacity *= 2;

		T * oldElem = elem;
		elem = new T[capacity];

		for (int i = 0; i < size; ++i)
		{
    
    
			elem[i] = oldElem[i];
		}
		delete[]oldElem;
		return;
	}

	void shrink(void)
	{
    
    
		if (capacity * 1.0 / size > 0.25) return;

		if (capacity < DEFAULT_CAPACITY * 2) capacity = DEFAULT_CAPACITY * 2;
		capacity /= 2;

		T * oldElem = elem;
		elem = new T[capacity];

		for (int i = 0; i < size; ++i)
		{
    
    
			elem[i] = oldElem[i];
		}
		delete[]oldElem;
		return;
	}

};
总结·易错篇:
  • 该模板类的类型是Vector<T> 而非 Vector
  • 模板template <typename T>template <class T> 的区别
  • return * this
  • 把elem数组封装为向量的好处:避免野指针,指针指向向量对象,里边包着的永远是有效的elem,若直接指向elem,则随着脱壳,指针无法及时的指向新壳。
  • # define DEFAULT_CAPACITY 3; 不能写分号
    宏定义写分号的报错
  • 非常量引用只能绑定到左值 简言之,临时对象不能寻址。出现这个错误的原因就是进行了强制类型转换+函数引用调用。
总结·效率篇:
  • const 类型名 & 变量名 效率高
  • 代码的重用,比如写operate=()时,可以用写好的copyFrom(),就不用重写详细的复制过程了
  • expand()为什么不重用copyFrom(),因为涉及到capacity的设置,在capacity很小的时候,是直接扩到最小容量,再二倍。
  • 二分查找与Fibonacci查找

猜你喜欢

转载自blog.csdn.net/weixin_45339670/article/details/131718933