C++:vector结构算法

news/2023/6/7 0:10:28

Vector

1.模板参数T指定向量元素类型
2.向量结构在内部维护一个元素类型为T的私有数组_elem[],容量由_capacity指示,有效元素数量由变量_size指示。
3.构造方法:默认构造方法、基于复制的构造方法
4.析构方法:释放数组_elem[]
5.静态空间管理:_size/_capacity装填因子不超过1也不太接近0
6.扩容、缩容算法:insert函数调用expand函数,若当前数据区满,将原数组替换成更大的数组,remove 函数调用shrink函数,若当前数据量*2<容量,将容量减半。
7.对向量元素访问沿用数组方式,重载操作符[]。
8.置乱算法:使元素等概率出现在各位置
9.查找算法:无序查找、有序查找
10.去重算法:无需向量去重、有序向量去重
11.排序算法:归并排序、选择排序、起泡排序

#pragma onceusing Rank = int; //秩
#define DEFAULT_CAPACITY  3 //默认的初始容量(实际应用中可设置为更大)template <typename T> class Vector { //向量模板类
protected:Rank _size; Rank _capacity;  T* _elem; //规模、容量、数据区void copyFrom ( T const* A, Rank lo, Rank hi ); //复制数组区间A[lo, hi)void expand(); //空间不足时扩容void shrink(); //装填因子过小时压缩bool bubble ( Rank lo, Rank hi ); //扫描交换void bubbleSort ( Rank lo, Rank hi ); //起泡排序算法Rank maxItem ( Rank lo, Rank hi ); //选取最大元素void selectionSort ( Rank lo, Rank hi ); //选择排序算法void merge ( Rank lo, Rank mi, Rank hi ); //归并算法void mergeSort ( Rank lo, Rank hi ); //归并排序算法void heapSort ( Rank lo, Rank hi ); //堆排序(稍后结合完全堆讲解)Rank partition ( Rank lo, Rank hi ); //轴点构造算法void quickSort ( Rank lo, Rank hi ); //快速排序算法void shellSort ( Rank lo, Rank hi ); //希尔排序算法
public:
// 构造函数//默认构造方法Vector ( int c = DEFAULT_CAPACITY, Rank s = 0, T v = 0 ) //容量为c、规模为s、所有元素初始为v{ _elem = new T[_capacity = c]; for ( _size = 0; _size < s; _elem[_size++] = v ); } //s<=cVector ( T const* A, Rank n ) { copyFrom ( A, 0, n ); } //数组整体复制Vector ( T const* A, Rank lo, Rank hi ) { copyFrom ( A, lo, hi ); } //区间Vector ( Vector<T> const& V ) { copyFrom ( V._elem, 0, V._size ); } //向量整体复制Vector ( Vector<T> const& V, Rank lo, Rank hi ) { copyFrom ( V._elem, lo, hi ); } //区间
// 析构函数~Vector() { delete [] _elem; } //释放内部空间
// 只读访问接口Rank size() const { return _size; } //规模bool empty() const { return !_size; } //判空Rank find ( T const& e ) const { return find ( e, 0, _size ); } //无序向量整体查找Rank find ( T const& e, Rank lo, Rank hi ) const; //无序向量区间查找Rank search ( T const& e ) const //有序向量整体查找{ return ( 0 >= _size ) ? -1 : search ( e, 0, _size ); }Rank search ( T const& e, Rank lo, Rank hi ) const; //有序向量区间查找
// 可写访问接口T& operator[] ( Rank r ); //重载下标操作符,可以类似于数组形式引用各元素const T& operator[] ( Rank r ) const; //仅限于做右值的重载版本Vector<T> & operator= ( Vector<T> const& ); //重载赋值操作符,以便直接克隆向量T remove ( Rank r ); //删除秩为r的元素int remove ( Rank lo, Rank hi ); //删除秩在区间[lo, hi)之内的元素Rank insert ( Rank r, T const& e ); //插入元素Rank insert ( T const& e ) { return insert ( _size, e ); } //默认作为末元素插入void sort ( Rank lo, Rank hi ); //对[lo, hi)排序void sort() { sort ( 0, _size ); } //整体排序void unsort ( Rank lo, Rank hi ); //对[lo, hi)置乱void unsort() { unsort ( 0, _size ); } //整体置乱Rank deduplicate(); //无序去重Rank uniquify(); //有序去重
// 遍历void traverse ( void (* ) ( T& ) ); //遍历(使用函数指针,只读或局部性修改)template <typename VST> void traverse ( VST& ); //遍历(使用函数对象,可全局性修改)
}; //Vectortemplate <typename T> //T为基本类型,或已重载赋值操作符'='
void Vector<T>::copyFrom ( T const* A, Rank lo, Rank hi ) { //以数组区间A[lo, hi)为蓝本复制向量_elem = new T[ _capacity = 2 * ( hi - lo ) ]; //分配空间,双倍容量for (_size = 0; lo < hi; _size++, lo++ ) //A[lo, hi)内的元素逐一_elem[ _size ] = A[ lo ]; //复制至_elem[0, hi - lo)
} //用const修饰,保证A中的元素不致被篡改;运行时间 = O(hi-lo)template <typename T> Vector<T>& Vector<T>::operator= ( Vector<T> const& V ) { //重载if ( _elem ) delete [] _elem; //释放原有内容copyFrom ( V._elem, 0, V.size() ); //整体复制return *this; //返回当前对象的引用,以便链式赋值
}template <typename T> void Vector<T>::expand() { //向量空间不足时扩容if ( _size < _capacity ) return; //尚未满员时,不必扩容if ( _capacity < DEFAULT_CAPACITY ) _capacity = DEFAULT_CAPACITY; //不低于最小容量T* oldElem = _elem;  _elem = new T[_capacity <<= 1]; //容量加倍for ( Rank i = 0; i < _size; i++ )_elem[i] = oldElem[i]; //复制原向量内容(T为基本类型,或已重载赋值操作符'=')delete [] oldElem; //释放原空间
}template <typename T> //将e作为秩为r元素插入
Rank Vector<T>::insert ( Rank r, T const& e ) { //assert: 0 <= r <= sizeexpand(); //若有必要,扩容for ( Rank i = _size; r < i; i-- ) //自后向前,后继元素_elem[i] = _elem[i-1]; //顺次后移一个单元_elem[r] = e; _size++; //置入新元素并更新容量return r; //返回秩
}template <typename T> void Vector<T>::shrink() { //装填因子过小时压缩向量所占空间if ( _capacity < DEFAULT_CAPACITY << 1 ) return; //不致收缩到DEFAULT_CAPACITY以下if ( _size << 2 > _capacity ) return; //以25%为界T* oldElem = _elem;  _elem = new T[_capacity >>= 1]; //容量减半for ( Rank i = 0; i < _size; i++ ) _elem[i] = oldElem[i]; //复制原向量内容delete [] oldElem; //释放原空间
}template <typename T> int Vector<T>::remove ( Rank lo, Rank hi ) { //删除区间[lo, hi)if ( lo == hi ) return 0; //出于效率考虑,单独处理退化情况,比如remove(0, 0)while ( hi < _size ) //区间[hi, _size)_elem[lo++] = _elem[hi++]; //顺次前移hi - lo个单元_size = lo; //更新规模,直接丢弃尾部[lo, _size = hi)区间shrink(); //若有必要,则缩容return hi - lo; //返回被删除元素的数目
}template <typename T> T & Vector<T>::operator[] ( Rank r ) //重载下标操作符
{ return _elem[r]; } // assert: 0 <= r < _sizetemplate <typename T> void Vector<T>::unsort ( Rank lo, Rank hi ) { //等概率随机置乱区间[lo, hi)T* V = _elem + lo; //将子向量_elem[lo, hi)视作另一向量V[0, hi - lo)for ( Rank i = hi - lo; i > 0; i-- ) //自后向前swap ( V[i - 1], V[rand() % i] ); //将V[i - 1]与V[0, i)中某一元素随机交换
}
template <typename T> //无序向量的顺序查找:返回最后一个元素e的位置;失败时,返回lo - 1
Rank Vector<T>::find ( T const& e, Rank lo, Rank hi ) const { //assert: 0 <= lo < hi <= _sizewhile ( ( lo < hi-- ) && ( e != _elem[hi] ) ); //从后向前,顺序查找return hi; //若hi < lo,则意味着失败;否则hi即命中元素的秩
}
template <typename T> //在有序向量的区间[lo, hi)内,确定不大于e的最后一个节点的秩
Rank Vector<T>::search ( T const& e, Rank lo, Rank hi ) const { //assert: 0 <= lo < hi <= _sizereturn ( rand() % 2 ) ? //按各50%的概率随机使用二分查找或Fibonacci查找binSearch ( _elem, e, lo, hi ) : fibSearch ( _elem, e, lo, hi );
}
template <typename T> Rank Vector<T>::deduplicate() { //删除无序向量中重复元素Rank oldSize = _size; //记录原规模for ( Rank i = 1; i < _size; ) //自前向后逐个考查_elem[1,_size)if ( find(_elem[i], 0, i) < 0 ) //在前缀[0,i)中寻找与之雷同者(至多一个)i++; //若无雷同则继续考查其后继elseremove(i); //否则删除当前元素return oldSize - _size; //被删除元素总数
}
template <typename T> Rank Vector<T>::uniquify() { //有序向量重复元素剔除算法(高效版)Rank i = 0, j = 0; //各对互异“相邻”元素的秩while ( ++j < _size ) //逐一扫描,直至末元素if ( _elem[i] != _elem[j] ) //跳过雷同者_elem[++i] = _elem[j]; //发现不同元素时,向前移至紧邻于前者右侧_size = ++i; shrink(); //直接截除尾部多余元素return j - i; //向量规模变化量,即被删除元素总数
}template <typename T> void Vector<T>::traverse ( void ( *visit ) ( T& ) ) //借助函数指针机制
{ for ( Rank i = 0; i < _size; i++ ) visit ( _elem[i] ); } //遍历向量template <typename T> template <typename VST> //元素类型、操作器
void Vector<T>::traverse ( VST& visit ) //借助函数对象机制
{ for ( Rank i = 0; i < _size; i++ ) visit ( _elem[i] ); } //遍历向量// 二分查找算法 :在有序向量的区间[lo, hi)内查找元素e,0 <= lo <= hi <= _size
template <typename T> static Rank binSearch ( T* S, T const& e, Rank lo, Rank hi ) {while ( lo < hi ) { //每步迭代仅需做一次比较判断,有两个分支Rank mi = ( lo + hi ) >> 1; //以中点为轴点(区间宽度的折半,等效于宽度之数值表示的右移)( e < S[mi] ) ? hi = mi : lo = mi + 1; //经比较后确定深入[lo, mi)或(mi, hi)} //成功查找不能提前终止return lo - 1; //循环结束时,lo为大于e的元素的最小秩,故lo - 1即不大于e的元素的最大秩
} //有多个命中元素时,返回秩最大者;查找失败时,能够返回失败的位置template <typename T> void Vector<T>::sort ( Rank lo, Rank hi ) { //向量区间[lo, hi)排序switch ( rand() % 6 ) {case 1:  bubbleSort ( lo, hi ); break; //起泡排序case 2:  selectionSort ( lo, hi ); break; //选择排序case 3:  mergeSort ( lo, hi ); break; //归并排序case 4:  heapSort ( lo, hi ); break; //堆排序case 5:  quickSort ( lo, hi ); break; //快速排序default: shellSort ( lo, hi ); break; //希尔排序} //随机选择算法以充分测试。实用时可视具体问题的特点灵活确定或扩充
}
template <typename T> //向量的起泡排序(跳跃版)
void Vector<T>::bubbleSort( Rank lo, Rank hi ) { //assert: 0 <= lo < hi <= sizefor( Rank last = --hi; lo < hi; hi = last )for( Rank i = last = lo; i < hi; i++ )if( _elem[i] > _elem[i + 1] ) //若逆序,则swap( _elem[ last = i ], _elem[ i + 1 ] ); //经交换使局部有序
}
template <typename T> //向量选择排序
void Vector<T>::selectionSort ( Rank lo, Rank hi ) { //0 <= lo < hi <= sizewhile ( lo < --hi )swap ( _elem[ maxItem ( lo, hi ) ], _elem[ hi ] ); //将[hi]与[lo, hi]中的最大者交换
}template <typename T>
Rank Vector<T>::maxItem ( Rank lo, Rank hi ) { //在[lo, hi]内找出最大者Rank mx = hi;while ( lo < hi-- ) //逆向扫描if ( _elem[ hi ] > _elem[ mx ] ) //且严格比较mx = hi; //故能在max有多个时保证后者优先,进而保证selectionSort稳定return mx;
}
template <typename T> //向量归并排序
void Vector<T>::mergeSort ( Rank lo, Rank hi ) { //0 <= lo < hi <= sizeif ( hi - lo < 2 ) return; //单元素区间自然有序,否则...Rank mi = ( lo + hi ) / 2; //以中点为界mergeSort ( lo, mi ); mergeSort ( mi, hi ); //分别排序merge ( lo, mi, hi ); //归并
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.exyb.cn/news/show-4567593.html

如若内容造成侵权/违法违规/事实不符,请联系郑州代理记账网进行投诉反馈,一经查实,立即删除!

相关文章

《 Unity Shader 入门精要》第5章 开始 Unity Shader 学习之旅

第5章 开始 Unity Shader 学习之旅 5.2 一个最简单的顶点/片元着色器 顶点/片元着色器的基本结构 // Upgrade NOTE: replaced mul(UNITY_MATRIX_MVP,*) with UnityObjectToClipPos(*)// 定义 shader 的名字 Shader "Chapter 5/Simple Shader" {SubShader{Pass {//…

First Week :Linux系统学习

CSDN学习小组 第一周Linux常用命令用户以及用户组0.显示用户信息1.创建/删除/修改用户2.添加/删除用户组&#xff0c;查看用户组信息3. 查看用户4. 密码操作5. 用户切换和退出登陆文件系统0.目录结构1. 查看文件2. 创建文件3. 删除文件4. 修改文件5.复制文件/剪切6.其他小命令7…

Python Cookbook by Eric

1 Basics 1.1 代码命令规范 请参考《代码规范 — mmengine 文档》 1.2 常见缩写释义 PEP: Python Enhancement Proposal 2 Variable 2.1 Python中的immutable变量 Immutable变量类型: str, tuple和numbers。 2.2 判断变量类型 # 判断变量是否是字符串 isinstance(a,st…

嘿~ 基于分布式架构的技术交流社区(WhiteHoleV0.7)即将竣工!

文章目录前言项目介绍WhiteHole期望立项作者功能/模块简介用户模块问答模块社区模块博文模块Next前言 拖更&#xff0c;拖延了这么久&#xff0c;耗时超过3个月的项目&#xff0c;WhiteHoleV0.7 版本即将迎来最后的收尾工作。当然考虑到服务成本&#xff0c;和开发进度&#x…

HTML+css前段美食博客(期末大作业)内有源代码

提示&#xff1a;参考时&#xff0c;可加入自己的想法&#xff0c;可在评论区给我留言。 文章目录 前言一、网页效果二、代码展示 1.HTML2.css总结前言 此为美食博客&#xff0c;虽然简洁但我会在后面一点点不断完善。相遇即是缘分&#xff0c;在此祝大家天天开心 一、网页效果…

[过年菜谱之]腰果虾仁

制作步骤 1. 所用到的材料&#xff1a;虾仁、腰果、毛豆、胡萝卜。2. 将虾仁用椒盐粉、料酒、盐腌15分钟。3. 毛豆煮熟后过凉水沥干水份。4. 腰果热锅冷油中放入&#xff0c;用锅铲不断翻动它&#xff0c;颜色转黄时即要关火。5. 炸好的腰果放吸油纸上吸吸油&#xff0c;倒…

MindManager盘点——舌尖上的中国

中国的饮食文化博大精深&#xff0c;我国先民从部落时代就有种植水稻的记录。而中国饮食发展了几千年&#xff0c;早已经发展成了几大特色菜系。而每个菜系都有自己的特色菜&#xff0c;美味的让人欲罢不能。今天我们就通过思维导图&#xff0c;给吃货们一个福利。 红烧肉&…

ole db 错误 通讯链接失败_花生米怎样炒香酥脆?掌握这技巧,炒花生米香酥脆,保证零失败...

每到冬天总会像小松鼠冬藏干果一样&#xff0c;买上一些带壳的花生米&#xff0c;贮存起来以备不时之需。花生米的吃法有很多&#xff0c;比如老醋花生米、麻辣花生米&#xff0c;五香花生米等&#xff0c;或者煲汤时加入花生米也是营养倍增&#xff0c;如猪蹄花生煲&#xff0…