目录

  • 一、基本概念
  • 二、接口
    • 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 - 向量相关推荐

  1. vector 赋值_从零开始学习R语言(一)——数据结构之“向量”(Vector)

    本文首发于知乎专栏:https://zhuanlan.zhihu.com/p/59688569 也同步更新于我的个人博客:https://www.cnblogs.com/nickwu/p/125370 ...

  2. R语言数据结构之向量

    R总共是6中数据结构:向量.因子.矩阵.数组.数据框.列表.向量用于存储数值型.字符型或逻辑型数据的一维数组,是R中的最小单元.向量构成的基本元素为:数值(numeric).字符(character) ...

  3. 邓俊辉《数据结构》-向量学习笔记

    目录 2021.12.7 星期二 向量 数组与向量 简单理解什么是泛化? 理解什么是接口? 向量的ADT操作接口 有序向量 唯一化-去重 有序向量的二分查找 有序向量的fibonacci查找 有序向量 ...

  4. 数据结构 笔记--向量 C++ 语言版 邓俊辉老师

    邓俊辉老师的书. 1 有数组为什么还需要向量? 几乎所有程序设计语言中都会有数组,程序设计语言的开发者将数组作为一种内置的数据类型. 数组在刚开始初始化的时候就已经固定了长度,也可以依照下标查找,但还 ...

  5. Matlab与数据结构 -- 搜索向量或矩阵中非零元素的位置

    本图文介绍了Matlab中搜索向量或矩阵中非零元素位置的方法.

  6. Matlab与数据结构 -- 求向量或矩阵的最大值

    本图文介绍了Matlab中求向量或矩阵最大值的方法.

  7. Matlab与数据结构 -- 对向量的排序

    本图文介绍了Matlab怎样实现对向量的排序.

  8. 数据结构与算法之-----向量(Vector)

    [ 写在前面的话:本专栏的主要内容:数据结构与算法. 1.对于​​​​​​​初识数据结构的小伙伴们,鉴于后面的数据结构的构建会使用到专栏前面的内容,包括具体数据结构的应用,所使用到的数据结构,也是自己 ...

  9. R语言与数据分析(11)R语言的数据结构

    数据结构 数据结构是计算机存储.组织数据的方式,数据结构是指相互之间存在一种或多种特定关系的数据元素的集合 R中的数据类型 1.数值型 数值可以用于直接结算,加减乘除 2.字符串型 可以进行连接.转换 ...

最新文章

  1. java连接mysql执行ddl_Mysql 执行DDL导致Waiting for table metadata lock
  2. 10、Ktor学习-运行程序和基础架构;
  3. 程序员如何优雅地使用 Mac? - OS X - 知乎
  4. 100m和1000m网线的常见制作方法
  5. ad采样频率_使用AD5933分析复阻抗的时钟频率设置
  6. SpringCloud(笔记)
  7. python 文件服务器
  8. 突然!华为P30 Pro真机上手视频曝光:屏幕指纹解锁秒开
  9. ZOJ 3635 Cinema in Akiba[ 大规模阵列 ]
  10. 【渝粤教育】国家开放大学2018年春季 4990T电子商务概论(农) 参考试题
  11. 福建师范网络教育应用计算机,福建师范大学网络教育计算机应用基础课程期末考核答案.docx...
  12. C++学习之 delete 构造器
  13. icon好看的图标-素材库
  14. 九大百度竞价操作技巧
  15. JS对象(对象的创建、属性的增删改查、属性的检测和枚举)
  16. 字节跳动移动架构师学习笔记,Android篇
  17. [讨论]什么是网络安全?
  18. Oracle:UGA PGA
  19. 火狐浏览器代理服务器拒绝连接的解决方案
  20. [附源码]计算机毕业设计JAVA全国人口普查管理系统论文

热门文章

  1. 手机用户对手机游戏的偏好调查
  2. Android 模块 -- 基于XMPP协议的手机多方多端即时通讯方案
  3. python json库安装_python-安装simplejson后没有名为“ json”的模块
  4. android property实现路径
  5. 与或树的盲目搜索和启发式搜索
  6. Win10连接远程桌面失败
  7. 设置电脑wifi和网线同时访问网络
  8. 跳转到wps查看文件
  9. 写字机结构---coreXY结构
  10. mysql表分区数量限制_详解MySQL分区表的局限和限制的代码实例