**VJ水题堆-sort函数的用法**

本文详细介绍了C++标准库中的sort函数用法,包括如何通过指定比较函数实现自定义排序方式,例如升序和降序排列。同时也讲解了sort函数的基本调用方法。
主播姐姐说,sort函数是根据需要排序的内容自动选择调用的,时间复杂度固定为logn,它内部包含了快速排序等等一系列排序方法。因此直接调用就显得尤为简单。
调用sort函数的方法是需要include头文件algorithm。同时还要使用命名空间std。即`using namespace std;`或std::sort
sort函数有三个参数,最后一个为默认参数。我把它抽象为:
sort(First, Last, compare);
也就是在[First, last)里利用compare的方法进行排序;其中First和Last为地址值。
那么,compare方法又是什么呢?
在sort函数原型中,compare是一个默认函参。即可以直接调用sort(First, Last);从得到的结果我们可以看到它是以升序排列的。倘若我们需要对排序的方式进行修改,就需要更改sort函数的第三个参数,同时也是一个新的函数,(随便给它起个名字),compare;
bool compare(int a, int b)
{
    return a<b;//升序排列。如果改为a>b的话就变味降序排列。
}

而接下来调用sort函数进行自动排序就只需要

sort(a,a+20,compare);

这太让人费解了,看了很久我也没懂这是在干嘛。那么接下来的方法更令我困惑。
sort函数完整用法
不过没关系,反正,我也不需要掌握很多方法,学会这一个就已经很令我开心了

你提出的问非常关键: 在代码中这一行: ```matlab denom_term = sigma2 + vj' * SigmaS * vj; ``` 报错 **“矩阵乘法的维度不对”**,说明 `vj` 和 `SigmaS` 的维度不匹配。我们来 **深入分析原因并修复它**--- ## 🔍 问根源:维度错误 ### ✅ 变量定义回顾: - `VK` 是 $ N \times K $ 矩阵(N个节点,K个低频特征向量) - `vj = VK(j, :)'` → 是第 j 行的列向量,尺寸为 $ K \times 1 $ - `SigmaS` 是 $ K \times K $ 协方差矩阵(作用于图频域系数空间) 所以: - `vj` 是 $ K \times 1 $ - `SigmaS` 是 $ K \times K $ - 所以 `vj' * SigmaS * vj` 应该是: - $ (1\times K) \cdot (K\times K) \cdot (K\times 1) = 1\times1 $ ✅ 标量 👉 **理论上没问!那为什么出错?** --- ## ❌ 常见出错场景与解决方案 ### 🚫 错误可能 1:`SigmaS` 初始化错误导致维度不是 $K \times K$ 原始代码中这句有问: ```matlab SigmaS = inv(VK * VK'); % 这是 N×N 矩阵!!! ``` ⚠️ 大问来了! - `VK` 是 $ N \times K $,所以 `VK * VK'` 是 $ N \times N $ - 那么 `inv(VK * VK')` 也是 $ N \times N $ 但后续你却用它和 $ K \times 1 $ 的 `vj` 相乘 → 维度不匹配! --- ## ✅ 正确建模:ΣS 的定义是什么? 根据你的描述: > $\Sigma_S = \left(W^{-1} + \sum_{j\in S} \frac{1}{\sigma_j^2} v_j v_j^T \right)^{-1}$ 其中: - $ W = \mathbb{E}[\tilde{x} \tilde{x}^T] $,$\tilde{x}$ 是信号在图频域上的表示(即前 K 个系数) - 所以 $W$ 是 $K \times K$ 的协方差矩阵 - $v_j$ 是指 VK 的第 j 行 → 是一个 $1 \times K$ 向量(对应节点 j 在 K 个基下的坐标) 因此,每一项 $\frac{1}{\sigma_j^2} v_j v_j^T$ 是 $K \times K$,所有运算应在 **图频率域(K维)** 中进行! --- ## ✅ 修正方案:将 ΣS 定义在 K 维空间 我们需要重新初始化 `SigmaS` 为 $K \times K$ 矩阵。 通常假设先验: $$ \tilde{x} \sim \mathcal{N}(0, I_K) \quad \Rightarrow \quad W = I_K \quad \Rightarrow \quad W^{-1} = I_K $$ 所以初始: $$ \Sigma_S^{(0)} = (I_K)^{-1} = I_K $$ 当加入观测时更新: $$ \Sigma_S^{-1} \leftarrow \Sigma_S^{-1} + \frac{1}{\sigma^2} v_j v_j^T \quad \text{(注意:这里 } v_j \text{ 是 } 1\times K \text{ 行向量)} $$ 然后最后再求逆得到新的 $\Sigma_S$ --- ## ✅ 修改后的正确代码段(修复维度问) 替换原来的 `SigmaS` 初始化和更新部分如下: ```matlab %% 初始化采样集 S 和 ΣS(现在是 K×K) S = []; % 当前采样节点集合 Lambda_prior = eye(K); % 先验精度矩阵:W^{-1} = I_K SigmaS_inv = Lambda_prior; % 初始为 W^{-1} % 注意:此时还没有任何观测,所以后验精度 = 先验精度 %% 贪心选取 r 个采样节点 for m = 1:r max_val = -inf; j_star = -1; for j = 1:N if ismember(j, S) continue; end % 提取 VK 的第 j 行:这是一个 1×K 的行向量(非常重要!) vj_row = VK(j, :); % size: 1×K % 计算项:vj * SigmaS * vj' (标量) % 注意:我们现在有 SigmaS_inv,需要临时计算 SigmaS? % 更聪明的做法:使用矩阵引理或直接计算信息增益 % 我们的目标函数是: % value = [vj * SigmaS^2 * vj'] / (σ² + vj * SigmaS * vj') % 所以需要当前的 SigmaS = inv(SigmaS_inv) try SigmaS = inv(SigmaS_inv); catch warning('Singular matrix, using pseudo-inverse'); SigmaS = pinv(SigmaS_inv); end term1 = vj_row * SigmaS * SigmaS * vj_row'; % 分子: vj Σ² vj' term2 = vj_row * SigmaS * vj_row'; % 分母中的二次项 value = term1 / (sigma2 + term2); if value > max_val max_val = value; j_star = j; end end % 更新:选中 j_star S = [S, j_star]; vj_row = VK(j_star, :); % 1×K % 更新精度矩阵:Σ^{-1} ← Σ^{-1} + (1/σ²) * vj'*vj SigmaS_inv = SigmaS_inv + (1/sigma2) * (vj_row' * vj_row); % outer product: K×K end % 最终得到 ΣS SigmaS = inv(SigmaS_inv); ``` --- ## ✅ 重构阶段也需修改 同样,在重构公式中: ```matlab H = C * VK; % r×K ``` 这是正确的。 MMSE 估计器为: $$ \hat{\tilde{x}} = \Sigma_S H^T (H \Sigma_S H^T + Q)^{-1} y_S \quad \Rightarrow \quad \hat{x} = V_K \hat{\tilde{x}} $$ MATLAB 实现: ```matlab H = C * VK; % r×K R_yy = H * SigmaS * H' + Q; % r×r,观测协方差 R_yy = R_yy + 1e-8 * eye(r); % 数值稳定 % 求解 x_hat_freq = SigmaS * H' * (R_yy \ yS); % K×1 x_hat = VK * x_hat_freq; % N×1 ``` --- ## ✅ 总结:修复重点 | 问 | 原因 | 解决方法 | |------|------|---------| | `vj' * SigmaS * vj` 维度错 | `SigmaS` 是 $N\times N$ | 改成 $K\times K$,定义在频域 | | `vj` 应该是行向量 | 使用了列特征向量 | 取 `VK(j,:)` 作为 $1\times K$ 向量 | | 不应使用 `inv(VK*VK')` | 得到的是空域投影 | 改为 $W^{-1}=I_K$ | --- ## ✅ 推荐最终初始化方式 ```matlab % 正确初始化 ΣS^{-1} SigmaS_inv = eye(K); % 假设先验协方差为单位阵 ``` 如果你有先验知识(如低频更强),也可以设为 `diag(1 ./ (1:K))` 等衰减形式。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值