数据结构之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查找