// 模拟vector
#include<cstdio>
#include<iostream>
#include<cmath>
#include"Fibonacci.h"
#define DEFAULT_CAPACITY 10
using namespace std;
using Rank = int; //typedef int Rank ,与using相比,差了点
template<typename T>
struct func_add { // 定义函数对象
int add_num=5;
func_add(int num) :add_num(num) {} // 构造函数,注意与java区分
func_add(){}
void operator()(T& e) {
e += add_num;
}
};
template<typename T>
class my_vector
{
private:
Rank _size; int capacity; T* _elem;
// 内部操作
public:
void copyFrom(T const* Arr,Rank low,Rank high);
void expand();
void insert(Rank r, T const& data); // 在秩为r的地方插入data
int remove(Rank low, Rank high); //删除[low,high)的元素
T remove(Rank r); //删除秩为r的元素,返回该元素原值
Rank find(T const& e, Rank low, Rank high); //无序向量的查找,所谓无序,即只支持==操作,不支持“>,<”操作
//命中多个元素返回秩最大的
//void traverse(void(*visit)(T& e,int value),int Value); // 遍历向量,对每个元素实行visit操作,visit是一个函数指针
template<typename FunClass>void traverse(FunClass& func); // 模板类的模板函数
int deduplicate(); // 返回剔了多少个重复元素
int uniquify(); // 有序向量的唯一化
int disordered(); // 返回多少个相邻的逆序对
void Sort(Rank low, Rank high); //[low,high]闭区间
void swap(T& a, T& b);
void bubble_sort(Rank low, Rank high);
void merge_sort(Rank low, Rank high);
Rank Search(T const& e, Rank low, Rank high); // [low,high)开区间
Rank bi_search(T const& e, Rank low, Rank high);
Rank fib_search(T const& e, Rank low, Rank high);
my_vector& operator=(my_vector const& v);
T& operator [](Rank r); // 数组要r为下标才可以访问,故函数参数是r。可作为左值eg:v[r]=(T)...
const T& operator [](Rank r)const; // 仅可作为右值引用,eg:T a=v[1]+v[3],因为左值要可以修改,不可为const
// 对外接口
public:
// 构造函数
/*vector()
{
r = 0, _size = 0, capacity = DEFAULT_CAPACITY;
}*/ // 这样写不太行
// 注意一个问题:this关键字,复值的时候别弄错了
my_vector(Rank size=0,int Capacity=DEFAULT_CAPACITY,T e=0) //带默认参数的构造函数,准备把向量全部初始化为0
{
this->_size = size;
// 保证capacity>=DEFAULT_CAPACITY
_elem = new T[this->capacity = Capacity > DEFAULT_CAPACITY ? Capacity : DEFAULT_CAPACITY];
for (int i = 0; i < this->capacity; ++i)
{
_elem[i] = e;
}
}
// 通过初始化调用构造函数,复制一部分
my_vector(my_vector<T> const& v, Rank low, Rank high)
{
//copyFrom(v, low, high); 你这就完全搞错了,vector v是一个结构体,传递参数要注意呀!!!
copyFrom(v._elem, low, high);
}
// 复制整体eg: vector<int> v1; vector<int> v2=v1(此处便是调用下面的构造函数)
my_vector(my_vector<T> const& v)
{
copyFrom(v._elem, 0, v._size);
}
// 析构函数
~my_vector()
{
//delete _elem[];
delete[] _elem;
}
// 定义接口
void show()
{
for (int i = 0; i < _size; ++i)
cout << _elem[i] << " ";
cout << endl;
}
int size() { return _size; }
};
template<class T> void my_vector<T>::copyFrom(T const* Arr, Rank low, Rank high)
{
_elem = new T[ capacity=max((high - low)<<1,DEFAULT_CAPACITY)]; // 为什么要*2,见扩容部分,且要把capacity加进去
// 否则capacity仍然是0
_size = 0;
while (low < high)
{
_elem[_size++] = Arr[low++]; // 不得不说这样写是真NB,虽然Arr[high]被复制了,但是size并不承认Arr[high]
}
}
// 采用倍增式扩容,注意分摊复杂度
template<class T> void my_vector<T>::expand()
{
if (_size < capacity) return; // 此处不可以为=
if (capacity < DEFAULT_CAPACITY)
capacity = DEFAULT_CAPACITY;
T* old_elem = _elem;
_elem = new T[capacity <<= 1];
for (int i = 0; i < _size; ++i)
{
_elem[i] = old_elem[i]; // 复制原有的old序列
}
//delete old_elem; // 这是一个数组,要用delete []
/*printf("\n[]*size:%d capacity:%d after expend->[]*size:%d capacity:%d", \
size, capacity / 2, size, capacity);*/
// 此处为printf的局限性
cout << "capacity:" << capacity / 2 << " after expand->" << "capacity:" << capacity << endl;
delete []old_elem;
}
// 运算符重载
template<class T> my_vector<T>& my_vector<T>::operator=(const my_vector<T>& v)
{
// 自身赋值问题
if (&v == this) // 直接比较地址
return *this;
// 多次赋值内存管理问题
if (this->_elem != NULL)
delete[] _elem;
this->_elem = new T[v.capacity];
for (int i = 0; i < v._size; ++i)
{
this->_elem[this->_size++] = v->_elem[i];
}
return *this;
}
template<class T> T& my_vector<T>::operator[](Rank r)
{
return this->_elem[r];
}
//template<class T> const T& my_vector<T>::operator[](Rank r) 与上面的那个operator[]重载类型不兼容!!!
template<class T> const T& my_vector<T>::operator[](Rank r)const
{
return this->_elem[r];
}
template<class T> void my_vector<T>::insert(Rank r, T const& data)
{
expand();
for (int i = _size; i > r; i--) // i==r,就直接往后插
{
_elem[i] = _elem[i - 1];
}
_elem[r] = data;
_size++;
}
//template<class T> T my_vector<T>::remove(Rank r)
//{
// T temp = _elem[r];
// for (int i = r; i < _size-1; ++i) { _elem[i] = _elem[i + 1]; }
// _size--;
// return temp;
//}
template<class T> T my_vector<T>::remove(Rank r)
{
T temp = _elem[r];
remove(r, r + 1);
return temp;
}
// 返回被删除的元素的个数
template<class T> int my_vector<T>::remove(Rank low, Rank high)
{
if (low == high)
return 0; //不删
while (high<_size)
{
_elem[low++] = _elem[high++];
}
_size -= (high - low);
return high - low;
}
//输入敏感性算法:best O(1) worst O(n)
template<class T> Rank my_vector<T>::find(T const& e, Rank low, Rank high)
{
// 从右往左找:因为命中多个元素返回秩最大的
while (low < high-- && _elem[high] != e); //about low<high--<===>先low<high? 后high--
return high;
}
template<class T>int my_vector<T>::deduplicate()
{
/*int old_size = _size;
for (int i = 1; i < _size; ++i)
{
Rank index = find(_elem[i], 0, i);
if (index >= 0)
remove(index);
}
return old_size - _size;*/
// 注意!!! 此种做法会改变vector内部数据,导致index失效
int old_size = _size;
int i = 1;
while (i < _size)
{
Rank index = find(_elem[i], 0, i);
if (index >= 0)
remove(i); // means删除后来重复的元素,保留前面的
// remove(index) means 把前面重复的去掉,保留后面新进来的元素
else
i++;
}
return old_size - _size;
}
template<typename T> int my_vector<T>::uniquify()
{
//int cnt = 0; // cnt means 重复几次元素 eg:2 2 2 表示重复两次元素
//int i = 0;
//int old_size = _size;
//while (i < _size)
//{
// T temp = _elem[i];
// for (int j = i+1; j < _size&&_elem[j] == temp; ++j)
// {
// cnt++;
// }
// if (cnt > 0)
// {
// remove(i + 1, i + 1 + cnt);
// cnt = 0;
// }
// i++;
//}
//return old_size - _size; // 此类复杂度仍无实质改变,对于1,1,2,2,3,3,4,4序列,仍为O(n^2)
// 对算法进行反思:
// 造成这种退化情况,仍然是remove 操作一次只删除一个元素
// 改进算法如下:
int i = 0, j = 0; int old_size = _size;
while (++j < _size)
if (_elem[i] != _elem[j]) _elem[++i] = _elem[j];
remove(i + 1, j);
return _size - old_size;
}
template<typename T> int my_vector<T>::disordered()
{
int cnt = 0; // 初始逆序对的值设为0
for (int i = 1; i < _size; ++i)
{
if (_elem[i - 1] != _elem[i])
cnt++;
}
return cnt;
}
//template<typename T>void increase_all_elem(T&e,int value )
//{
// e += value;
//}
//template<typename T>void my_vector<T>::traverse(void(*increase_all_elem)(T& e,int value),int Value)
//{
// for (int i = 0; i < _size; ++i)
// {
// increase_all_elem(_elem[i],Value);
// }
//}
// 这样写好麻烦,并且效率不高
// 改进后的版本
template<typename T> template<typename FunClass>
void my_vector<T>::traverse(FunClass& func_add) {
for (int i = 0; i < _size; ++i)
func_add(_elem[i]);
}
template<typename T> void my_vector<T>::Sort(Rank low, Rank high)
{
switch (rand() % 1+1) {
case 1:
bubble_sort( low, high);
break;
case 2:
merge_sort( low, high);
break;
}
}
template<typename T>void my_vector<T>:: swap(T& a, T& b)
{
//T temp = new T;
T temp;
temp = a;
a = b;
b = temp;
}
template<typename T>void my_vector<T>::bubble_sort(Rank low, Rank high) //[low,high]
{
Rank last = high;
for (Rank i = last; i >low;)
{
for (Rank j = (last=low)+1; j <= i; ++j) // // 假设每次向量是有序的,即last=0
if (_elem[j - 1] > _elem[j]) {
swap(_elem[j - 1], _elem[j]);
last = j - 1;
}
i = last; // last(包含last)之后必定有序
}
}
template<typename T> void merge(T* elem, Rank low, Rank mid, Rank high)
{
T* arr_A = new T[mid - low + 1];
int i = low;
for (int cnt=0; cnt <= mid - low + 1; ++cnt)
{
arr_A[cnt] = elem[i++];
}
i = low;
int j = mid + 1, k = low;
while (i <= mid && j <= high) // 双方均未越界
{
elem[k++] = arr_A[i] > elem[j] ? elem[j++] : arr_A[i++];
}
while (i <= mid) // 后面的数组越界,直接拷贝前面的即可
{
elem[k++] = arr_A[i++];
}
}
template<typename T> void my_vector<T>::merge_sort(Rank low, Rank high)
{
// low<=high Error:核心是单个元素有序
if ((high-low)>1)
{
Rank mid = (low + high) >>1;
merge_sort(low, mid);
merge_sort(mid+1, high);
merge(_elem, low, mid, high);
}
}
template<typename T> Rank my_vector<T>::Search(T const& e, Rank low, Rank high)
{
switch (rand() % 2 + 1) {
case 1:
bi_search( e, low, high);
break;
case 2:
fib_search( e, low, high);
break;
}
}
template<typename T> Rank my_vector<T>::bi_search(T const& e, Rank low, Rank high)
{
while (low < high)
{
Rank mid = (low + high) >> 1;
e < _elem[mid] ? high = mid : low = mid + 1;
}
return --low; // 区间缩短至0,arr[high=low]为大于e的最小元素
}
template<typename T> Rank my_vector<T>::fib_search(T const& e, Rank low, Rank high)
{
for (Fib fib(high - low);high > low;)
{
// 找出黄金分割点
int mid;
while (fib.get() > (high - low)) { mid = fib.pre()+low; }
if (e < _elem[mid])
high = mid;
else if (_elem[mid] < e)
low = mid + 1;
else
return mid;
}
return -1;
}
int main()
{
my_vector<int> v1(6, 3, 1);
my_vector<int> v2 = v1;
func_add<int> funAdd(5);
v2.traverse(funAdd);
v2.show();
// v2.traverse(new func_add<int>(9)); // Error:Simple reference cannot bind to temp var(变量)
my_vector<int> v3;
for (int i = 0; i < 10; ++i) { v3.insert(rand() % 10, rand() % 20); }
v3.show();
v3.Sort(0, v3.size() - 1);
v3.show();
v3.insert(v3.bi_search(6,0,v3.size()) + 1, 6);
v3.show();
}
番外篇:对C++基础知识的一些补充
01.函数对象与函数指针(传参问题可是折磨我等)
void add5(int& value)
{
value += 5;
}
class fun_add
{
private:
int num;
public:
fun_add(int number):num(number){}
void operator()(int add_num)
{
num += add_num;
}
};
template<typename Func>
void add(int* arr, int n, Func func)
{
for (int i = 0; i < n; ++i)
{
func(arr[i]);
}
}
int main()
{
int array[10] = { 1,4,7,2 };
add(array, 10, add5); // 传递过后func是void(*)(int&)类型,即函数指针
add<void(*)(int&)>(array, 10, add5);
// func是fun_add类型,以上均属于隐式的实例化函数模板
add(array, 10, fun_add(5)); //add<func_add(5)>(array, 10, fun_add(5)) Error:显示实例化是传class类型而不是对象
add<fun_add>(array, 10, fun_add(5));
//add<void(*)(int&)>...为显式
}
C++模拟vector
最新推荐文章于 2023-07-18 13:53:34 发布