数据结构1 - 向量
目录
- 一、基本概念
- 二、接口
- 1、向量的操作接口
- 2、Vector模板类
- 3、空间管理
- 4、容量扩充策略
- 三、有序向量
- 1、二分查找(版本A)
- 2、Fibonacci查找(二分查找改进)
- 3、通用策略
- 4、二分查找(版本B)
- 5、二分查找(版本C)(实用版本)
- 6、插值查找
- 四、向量排序
- 1、起泡排序
- 2、归并排序(分而治之、二路归并)
- 五、位图(Bitmap)
- 1、数据结构
- 2、典型应用
一、基本概念
向量(vector)就是线性数组的一种抽象与泛化,它也是由具有线性次序的一组元素构成的集合V = { v0, v1, …, vn-1 },其中的元素分别由秩相互区分。
各元素的秩(rank)互异,且均为[0, n)内的整数。(类似数组的下标)
向量的各元素可以为不同类型,也可通过泛型指定某一特定的类型。
二、接口
1、向量的操作接口
- 列表
操作接口 | 功能 | 适用对象 |
---|---|---|
size() | 报告向量当前的规模(元素总数) | 向量 |
get( r) | 获取秩为r的元素 | 向量 |
put(r, e) | 用e替换秩为r元素的值 | 向量 |
insert(r, e) | e作为秩为r的元素插入,原后继元素依次后移 | 向量 |
remove( r) | 删除秩为r的元素,返回该元素中原存放的对象 | 向量 |
disordered() | 判断所有元素是否已按费降序排列 | 向量 |
sort() | 调整各元素的位置,使之按非降序排列 | 向量 |
find(e) | 查找等于e且秩最大的元素 | 向量 |
search(e) | 查找目标元素e,返回不大于e且秩最大的元素 | 有序向量 |
deduplicate() | 剔除重复元素 | 向量 |
uniquify() | 剔除重复元素 | 有序向量 |
traverse() | 遍历向量并统一处理所有元素,处理方法由函数对象指定 | 向量 |
具体实例
#include <iostream> #include <vector> using namespace std;vector<int> v; //一个空向量 vector<int> s(32, 63); //{63, 63, 63, ..., 63}, 创建一个长度为32内容全是63的向量 s.insert(s.begin + 2, 2017); //{63, 63, 2017, 63, ..., 63},在秩为2的地方插入2017 s.erase(s.end - 30, s.end); //{63, 63, 2017},删除后30个元素,此句删除秩的区间为[3,33) //遍历向量 for(i = 0;i < s.size();i++){cout<< s[i] << endl; }
2、Vector模板类
typedef int Rank; //秩
#define DEFAULT_CAPACITY 3 //默认的初始容量(实际应用中可设置为更大)template <typename T> class Vector { //向量模板类private: Rank _size; int _capacity; T* _elem; //规模、容量、数据区protected:/* 内部函数 */public:/* 构造函数 *//* 析构函数 *//* 可读接口 *//* 可写接口 *//* 遍历接口 */
}; //Vector
构造与析构
默认构造方法
首先根据创建者指定的初始容量,向系统申请空间,以创建内部私有数组
_elem[]
;若容量未明确指定,则使用默认值DEFAULT_CAPACITY
。接下来,鉴于初生的向量尚不包含任何元素,故将指示规模的变量_size
初始化为0。基于复制的构造方法
template <typename T> //元素类型 void Vector<T>::copyFrom ( T const* A, Rank lo, Rank hi ) { //以数组匙间A[lo, hi)为蓝本复制向量_elem = new T[_capacity = 2 * ( hi - lo ) ]; _size = 0; //分配空间,规模清零while ( lo < hi ) //A[lo, hi)内的元素逐一_elem[_size++] = A[lo++]; //复制至_elem[0, hi - lo) }//O(hi - lo) = O(n)
3、空间管理
静态空间管理
内部数组所占物理空间的容量,若在向量的生命期内不允许调整,则称作静态空间管理策略。因为容量固定,总有可能在此后的某一时刻,无 法加入更多的新元素即导致所谓的上溢(overflow)。
动态空间管理
可扩充向量
一旦可用空间耗尽,就动态地扩大内部数组的容量。另行申请一个容量更大的数组B[],并将原数组中的成员集体搬迁至新的空间。并且原数组所占的空间,需要及时释放并归还操作系统。
动态扩容算法
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 ( int i = 0; i < _size; i++ )_elem[i] = oldElem[i]; //复制原向量内容(T为基本类型,或已重载赋值操作符'=') delete [] oldElem; //释放原空间 }
4、容量扩充策略
分摊复杂度
考查对可扩充向量的足够多次连续操作,并将其间所消耗的时间,分摊至所有的操作。如此分摊平均至单次操作的时间成本,称作分摊运行时间(amortized running time)。
容量递增策略
- _capacity += increment; 追加固定容量
- 最坏情况:在初始容量为0的空向量中,连续插入 n = m*I >> 2个元素,而无删除操作,总体耗时O(n²),每次(insert/remove)操作的分摊成本为O(n)。
容量加倍策略
- _capacity <<= 1; 容量加倍
- 最坏情况:在初始容量为1的满向量中,连续插入 n = 2^m >> 2个元素,而无删除操作,总体耗时O(n),每次(insert/remove)操作的分摊成本为O(1)。
三、有序向量
1、二分查找(版本A)
- 统一接口
template <typename T> //查找算法统一接口,0 <= lo < hi <= _sizeRank Vector<T>::search(T const &e, Rank lo, Rank hi) const{return (rand() % 2) ? //按各50%的概率随机选用binSearch(_elem, e, lo, hi) //二分查找算法, 或者:fibSearch(_elm, e, lo, hi) //Fibonacci查找算法}
- 实现
template <typename T>static Rank binSearch(T *S, T const &e, Rank lo, Rank hi){while(lo < hi){ //每步迭代可能要做两次比较判断,有三个分支Rank mi = (lo + hi) >> 1; //轴点居中(区间宽度折半,等效于其数值右移一位if(e < S[mi]) hi = mi; //深入前半段[lo, mi)else if (S[mi] < e) lo = mi + 1; //深入后半段(mi, hi)else return mi; //命中}return -1; //查找失败}/*1、判断语句if-else,一般把概率小的写在后面(本例命中的概率比其他两个小)2、判断条件一般写小于号,这是编程习惯3、前半段的数值只需要比较一次,而后半段需要比较两次(两次if)
*/
2、Fibonacci查找(二分查找改进)
思路及原理
版本A:转向左、右分支前的关键码比较次数不等,而递归深度却相同
通过递归深度的不均衡对转向成本的不均衡做补偿,平均查找长度应能进一步缩短!
比如,若有n = fib(k) - 1,则可取 mi = fib(k - 1) -1
于是,前、后字向量的长度分别为fib(k - 1) - 1 、fib(k - 2) -1
实现
template <typename T> // 0 <= lo <= hi <= _sizestatic Rank fibSearch(T *s, T const &e, Rank lo, Rank hi){for(Fib fib(hi - lo); lo < hi; ){while(hi - lo < fib.get()) fib.prev(); //Fib数列制表备查Rank mi = lo + fib.get() - 1; //自后向前顺序查找轴点(分摊0(1))if(e < S[mi]) hi = mi; //确定形如Fib(k) - 1的轴点else if(S[mi] < e) lo = mi + 1; //深入前半段[lo, mi)else return mi; //深入后半段(mi, hi)}return -1; //查找失败}
3、通用策略
在任何区间[0, n)内,总是选取[λ · n]作为轴点,0 <= λ < 1
比如:二分查找对应于λ = 0.5,Fibonacci查找对应于λ = φ = 0.6180339…
这类查找算法的渐进复杂度为α(λ) · log₂n = O(log n)
(在常系数意义上的)性能最优,即意味着α(λ)达到最小
4、二分查找(版本B)
只判断一次,用三元运算符,具体略
5、二分查找(版本C)(实用版本)
- 实现
template <typename T>static Rank binSearch(T *S,T const &e, Rank lo, Rank hi){while(lo < hi){ //不变性:A[0, lo) <= e < A[hi, n)Rank mi = (lo + hi) >> 1;e < S[mi] ? hi = mi : lo = mi + 1; //[lo, mi)或(mi, hi)} //出口时,必有S[lo = hi] = Mreturn lo - 1; //故,S[lo-1] = m}/*1、待查找区间宽度缩短至0而非1时,算法才结束2、转入右侧字向量时,左边界取作mi+1而非mi
*/
6、插值查找
假设:已知有序向量中各元素随机分布的规律
比如:独立且均匀的随机分布
于是:[lo, hi]内各元素应大致呈线性趋势增长
因此:通过猜测轴点mi,可以极大地提高收敛速度
以英文词典为例:binary大致位于2/26处、search大致位于19/26处
四、向量排序
1、起泡排序
依次比较每一对相邻元素;如有必要,交换之。若整趟扫描都没有进行交换,则排序完成;否则,再做一趟扫描交换。
2、归并排序(分而治之、二路归并)
分治策略:序列一分为二,子序列递归排序,合并有序子序列
合并策略:有序序列,合二为一,保持有序(每次比较两个子序列最低位,小的归位)
五、位图(Bitmap)
1、数据结构
位图是个很简单的东西,它通过利用一个bit位来表示一些数据状态简单的情况,比如一万个人的性别,或者表示某些东西是否存在,在某些情况可以节省大量的空间。
//实现
bool test(int k) {return M[k >> 3] & (0x80 >> (k & 0x07)); }
void set(int k) {expand(k); M[k >> 3] |= (0x80 >> (k & 0x07));}
void clear(int k) {expand(k); M[k >> 3] &= ~(0x80 >> (k & 0x07));}/*最好用前面的写法,计算机专业性强一些:1、k >> 3表示二进制k右移三位,即k除以8(k/8)2、k & 0x07表示二进制k与八进制07做与运算,即保留后三位,前面全部置零,也即k模8(k%8)
*/
2、典型应用
小集合 + 大数据:
剔除重复元素
数据结构1 - 向量相关推荐
- vector 赋值_从零开始学习R语言(一)——数据结构之“向量”(Vector)
本文首发于知乎专栏:https://zhuanlan.zhihu.com/p/59688569 也同步更新于我的个人博客:https://www.cnblogs.com/nickwu/p/125370 ...
- R语言数据结构之向量
R总共是6中数据结构:向量.因子.矩阵.数组.数据框.列表.向量用于存储数值型.字符型或逻辑型数据的一维数组,是R中的最小单元.向量构成的基本元素为:数值(numeric).字符(character) ...
- 邓俊辉《数据结构》-向量学习笔记
目录 2021.12.7 星期二 向量 数组与向量 简单理解什么是泛化? 理解什么是接口? 向量的ADT操作接口 有序向量 唯一化-去重 有序向量的二分查找 有序向量的fibonacci查找 有序向量 ...
- 数据结构 笔记--向量 C++ 语言版 邓俊辉老师
邓俊辉老师的书. 1 有数组为什么还需要向量? 几乎所有程序设计语言中都会有数组,程序设计语言的开发者将数组作为一种内置的数据类型. 数组在刚开始初始化的时候就已经固定了长度,也可以依照下标查找,但还 ...
- Matlab与数据结构 -- 搜索向量或矩阵中非零元素的位置
本图文介绍了Matlab中搜索向量或矩阵中非零元素位置的方法.
- Matlab与数据结构 -- 求向量或矩阵的最大值
本图文介绍了Matlab中求向量或矩阵最大值的方法.
- Matlab与数据结构 -- 对向量的排序
本图文介绍了Matlab怎样实现对向量的排序.
- 数据结构与算法之-----向量(Vector)
[ 写在前面的话:本专栏的主要内容:数据结构与算法. 1.对于初识数据结构的小伙伴们,鉴于后面的数据结构的构建会使用到专栏前面的内容,包括具体数据结构的应用,所使用到的数据结构,也是自己 ...
- R语言与数据分析(11)R语言的数据结构
数据结构 数据结构是计算机存储.组织数据的方式,数据结构是指相互之间存在一种或多种特定关系的数据元素的集合 R中的数据类型 1.数值型 数值可以用于直接结算,加减乘除 2.字符串型 可以进行连接.转换 ...
最新文章
- java连接mysql执行ddl_Mysql 执行DDL导致Waiting for table metadata lock
- 10、Ktor学习-运行程序和基础架构;
- 程序员如何优雅地使用 Mac? - OS X - 知乎
- 100m和1000m网线的常见制作方法
- ad采样频率_使用AD5933分析复阻抗的时钟频率设置
- SpringCloud(笔记)
- python 文件服务器
- 突然!华为P30 Pro真机上手视频曝光:屏幕指纹解锁秒开
- ZOJ 3635 Cinema in Akiba[ 大规模阵列 ]
- 【渝粤教育】国家开放大学2018年春季 4990T电子商务概论(农) 参考试题
- 福建师范网络教育应用计算机,福建师范大学网络教育计算机应用基础课程期末考核答案.docx...
- C++学习之 delete 构造器
- icon好看的图标-素材库
- 九大百度竞价操作技巧
- JS对象(对象的创建、属性的增删改查、属性的检测和枚举)
- 字节跳动移动架构师学习笔记,Android篇
- [讨论]什么是网络安全?
- Oracle:UGA PGA
- 火狐浏览器代理服务器拒绝连接的解决方案
- [附源码]计算机毕业设计JAVA全国人口普查管理系统论文