数据结构-vector

本文介绍了C++中的数据结构vector,作为不定长数组的替代,它提供了灵活的大小调整。文章通过一个ACM-ICPC题目来说明vector在处理动态数组问题时的优势,解释了vector的基本操作和如何在代码中应用。此外,还简要提及了链表作为对比,并预告了关于迭代器的内容,但未展开详细讨论。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

vector是不定长数组,也就是说它的长度是不固定的,简单地说就是“按需分配”。这听上去似乎有点麻烦,但在声明数组时如果我们并不清楚数组的长度,并且简单粗暴地使用#define MAXN 1000000会导致内存失去了梦想——就算不,仍有大量的内存成了咸鱼。这个时候,我们就需要vector数组。


先看一道例题:

从左到右有n个木块,编号为0~n-1,要求模拟以下四种操作:

  • move a onto b:把a和b上方的木块全部归位,然后把a摞在b上面。
  • move a over b:把a上方的木块全部归位,然后把a放在b所在木块堆的顶部。
  • pile a onto b:把b上方的木块全部归位,然后把a及上面的木块整体摞在b上面。
  • pile a over b:把a及上面的木块整体摞在b所在木块堆的顶部。

遇到quit时终止一组数据。a和b在同一堆的指令时非法指令,应当忽略。
所有操作结束后,输出每个位置的木块列表,按照从底部到顶部的顺序排列。
(出自UVa 101,小紫书p110)

由于每个木块堆的最大高度并没有限制,如果开一个a[n][n]的数组,显然浪费了很多空间,并且出题人很可能会故意卡MLE,于是我们需要一个“按需分配”数组。


链表

在介绍vector前,先提一下链表。
在c语言中,我们并没有c++丰富的STL,也就是说需要人工实现不定长数组:

    struct Node
    {
        int num;     //用于储存数据
        Node* next;
    };

这段代码声明了一个结构体Node,它包含了一个int型变量num和一个指针next,让我们有请灵魂画师来帮助我们理解。

链表块

我们的链表是由若干个这样的“小块”组成的,由于创建的“小块”之间没有任何联系,所以我们需要用一个指针next将它们连接到一起,也就是用next指向下一个“小块”,这样我们就能将它们“链”在一起。

链表

每一个next都指向下一个块的地址,我们只需要访问当前块的next储存的地址,就可以到达下一个块。

由于我们只用在需要的时候申请一个新的块,并把它和之前的链表连在一起,所以可以达到不定长数组的作用。

但显然,构造一个链表十分麻烦,并且鄙人已经基本忘了怎么写链表,所以我们需要一个C艹。(c语言的链表构建我会在之后补上(flag++))


vector

在C++中,我们可以用vector来代替链表,这需要

    #include <vector>

在vector中,我们(暂时)不需要再思考指针和它的小伙伴们,可以把vector看作一个正常的数组:

vector示意图

也就是说它的空间是“连续”的。

我们可以用

    vector <int> v;

声明一个vector数组,它的元素为int型。当然,你也可以换成double型或者string型甚至是结构体。

vector为我们提供了以下操作:

    v.push_back(n);  //将元素n加入到v的尾部
    v.pop_back();    //将v的末端的元素删除
    v.empty();       //判断数组是否为空,若为空则返回真,否则返回假
    v.size();        //返回v中元素的数量
    v.resize(n);     //将v的长度设为n

如果我们想访问v中的元素,只需要像数组一样访问下标即可:

    ans=v[i];
    num=v[i]+v[i+1];

这时候,我们可以解决前面的例题了。


代码示例

#include <iostream>
#include <string>
#include <vector>
using namespace std;

const int MAXN=10000;
vector <int> v[MAXN];
int n;

int find(int a,int& p,int& h)  //寻找木块a(或b)所在位置和高度
{
    p=v[a][0];
    for(h=1;h<v[p].size();h++)
    {
        if(v[p][h]==a) return 0;
    }
}

void clear(int p,int h)  //将位置p高度h的木块上方的所有木块归位
{
    for(int i=h+1;i<v[p].size();i++)
    {
        int j=v[p][i];
        v[j][0]=j;
    }
    v[p].resize(h+1);
}

void move(int p1,h1,p2) //将位置p1高度h1的木块及上方的所有木块移到位置p2的顶端
{
    for(int i=h1;i<v[p1].size();i++)
    {
        int j=v[p1][i];
        v[p2].push_back(j);
        v[j][0]=p2;
    }
    v[p1].resize(h1);
}

int main()
{
    int a,b;
    string s1,s2;
    while(cin>>n>>s1)
    {
        for(int i=0;i<n;i++)  //初始化v
        {
            v[i].clear();
            v[i].push_back(i); //v[i][0]保存木块i所在的位置
        }
        while(s1!="quit")
        {
            cin>>a>>s2>>b;
            int p1,h1,p2,h2;
            find(a,p1,h1);
            find(b,p2,h2);
            if(p1!=p2)
            {
                if(s2=="onto") clear(p2,h2);
                if(s1=="move") clear(p1,h1);
                move(p1,h1,p2);
            }
            cin>>s1;
        }
        for(int i=0;i<n;i++) //一组数据结束,打印木块列表
        {
            cout<<i<<":";
            for(int j=1;j<v[i].size();j++)
                cout<<v[i][j]<<" ";
            cout<<endl;
        }
    }
    return 0;
}

鄙人用v[i][0]来保存木块i所在的位置(初始为i),这样在每次find的时候可以减少一次for循环查找木块i的位置,避免最坏情况下find为O(n²)而导致超时。


迭代器

还记得之前说的“我们(暂时)不需要再思考指针和它的小伙伴们”么?
是的,我们只是暂时不需要,但事实上还有个叫做“迭代器”的设定。
由于不(wo)可(jiu)抗(shi)力(lan)的因素,此部分之后再更新……


PS:
写这篇的时候临近国庆,于是我咕了将近半个月,虽然打算国庆结束后就补完迭代器的部分,然而我很快就发烧在床上瘫了两天…就这么先扔上来吧(强颜欢笑)

…什么?还有链表?

### i-vector 和 X-vector 在说话人识别技术中的区别及应用 #### 定义与特征提取方法 i-vector 是一种用于表示语音信号的低维向量,在说话人识别领域广泛应用。该模型通过总变差(Total Variability Space)来捕捉不同说话者之间的差异,从而实现对个体身份的有效编码[^3]。 相比之下,X-vector 则采用了更深层次的学习框架来进行特征抽取。具体来说,X-vector 使用卷积神经网络(CNNs)以及时间延迟神经网络(TDNNs),这些结构能够自动学习到更加抽象且具有区分性的声学特性描述子。最终得到固定长度的嵌入向量作为输入样本的表现形式[^1]。 #### 训练过程对比 对于 i-vector 的训练而言,通常依赖于高斯混合模型-联合贝叶斯(GMM-UBM)体系下的统计建模方式;而 X-vector 更倾向于端到端的数据驱动型算法设计思路,即直接利用大规模标注数据集完成监督式学习任务,无需预先定义复杂的概率分布假设或手工设定参数初始化条件[^4]。 #### 应用场景分析 当涉及到实际部署环境时: - **资源受限设备**:由于计算复杂度较低,内存占用少的特点使得 i-vector 成为了移动终端、物联网节点等硬件配置相对简单的平台上的首选方案; - **高性能需求场合**:如果追求更高的辨识精度并可以接受较长处理时间和较大存储开销,则应考虑采用性能优越但成本较高的 X-vector 技术路线[^2]。 ```python import numpy as np def ivector_extraction(audio_signal): # 假设函数实现了基于 GMM-UBM 模型的 i-vector 提取流程 pass def xvector_extraction(audio_signal): # 假设此函数代表了一个完整的 CNN/TDNN 架构下 X-vector 获取的过程 pass ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值