数据结构和算法:复杂度分析

算法效率评估

时间效率:算法运行速度的快慢。
空间效率:算法占用内存空间的大小。

效率评估方法主要分为两种:实际测试、理论估算

实际测试问题:
1.难以排除测试环境的干扰因素。
硬件配置会影响算法的性能。需要在各种机器上进行测试,统计平均效率,而这是不现实的。
2.展开完整测试非常耗费资源。
随着输入数据量的变化,算法会表现出不同的效率。因此,为了得到有说服力的结论,需要测试各种规模的输入数据,而这需要耗费大量的计算资源。

由于实际测试具有较大的局限性,因此我们可以考虑仅通过一些计算来评估算法的效率。这种估算方法被称为渐近复杂度分析 (asymptotic complexity analysis),简称复杂度分析

复杂度分析能够体现算法运行所需的时间和空间资源与输入数据大小之间的关系。它描述了随着输入数据大小的增加,算法执行所需时间和空间的增长趋势。
1.“时间和空间资源”分别对应时间复杂度(time complexity)和空间复杂度(space complexity)。
2.“随着输入数据大小的增加”意味着复杂度反映了算法运行效率与输入数据体量之间的关系。
3.“时间和空间的增长趋势”表示复杂度分析关注的 不是运行时间或占用空间的具体值,而是时间或空间增长的“快慢”。

复杂度分析克服了实际测试方法的弊端:
1.独立于测试环境,分析结果适用于所有运行平台;
2.可以体现不同数据量下的算法效率,尤其是在大数据量下的算法性能。

迭代与递归

迭代(iteration) 是一种重复执行某个任务的控制结构。在迭代中,程序会在满足一定的条件下重复执行某段代码,直到这个条件不再满足。

/*** File: iteration.cpp* Created Time: 2023-08-24* Author: Krahets (krahets@163.com)*/#include "../utils/common.hpp"/* for 循环 */
int forLoop(int n) {int res = 0;// 循环求和 1, 2, ..., n-1, nfor (int i = 1; i <= n; ++i) {res += i;}return res;
}/* while 循环 */
int whileLoop(int n) {int res = 0;int i = 1; // 初始化条件变量// 循环求和 1, 2, ..., n-1, nwhile (i <= n) {res += i;i++; // 更新条件变量}return res;
}/* while 循环(两次更新) */
int whileLoopII(int n) {int res = 0;int i = 1; // 初始化条件变量// 循环求和 1, 4, 10, ...while (i <= n) {res += i;// 更新条件变量i++;i *= 2;}return res;
}/* 双层 for 循环 */
string nestedForLoop(int n) {ostringstream res;// 循环 i = 1, 2, ..., n-1, nfor (int i = 1; i <= n; ++i) {// 循环 j = 1, 2, ..., n-1, nfor (int j = 1; j <= n; ++j) {res << "(" << i << ", " << j << "), ";}}return res.str();
}/* Driver Code */
int main() {int n = 5;int res;res = forLoop(n);cout << "\nfor 循环的求和结果 res = " << res << endl;res = whileLoop(n);cout << "\nwhile 循环的求和结果 res = " << res << endl;res = whileLoopII(n);cout << "\nwhile 循环(两次更新)求和结果 res = " << res << endl;string resStr = nestedForLoop(n);cout << "\n双层 for 循环的遍历结果 " << resStr << endl;return 0;
}

在这里插入图片描述

递归 (recursion) 是一种算法策略,通过函数调用自身来解决问题。它主要包含两个阶段:
1.递:程序不断深入地调用自身,通常传入更小或更简化的参数,直到达到“终止条件”。
2.归:触发“终止条件”后,程序从最深层的递归函数开始逐层返回,汇聚每一层的结果。

/*** File: recursion.cpp* Created Time: 2023-08-24* Author: Krahets (krahets@163.com)*/#include "../utils/common.hpp"/* 递归 */
int recur(int n) {// 终止条件if (n == 1)return 1;// 递:递归调用int res = recur(n - 1);// 归:返回结果return n + res;
}/* 使用迭代模拟递归 */
int forLoopRecur(int n) {// 使用一个显式的栈来模拟系统调用栈stack<int> stack;int res = 0;// 递:递归调用for (int i = n; i > 0; i--) {// 通过“入栈操作”模拟“递”stack.push(i);}// 归:返回结果while (!stack.empty()) {// 通过“出栈操作”模拟“归”res += stack.top();stack.pop();}// res = 1+2+3+...+nreturn res;
}/* 尾递归 */
int tailRecur(int n, int res) {// 终止条件if (n == 0)return res;// 尾递归调用return tailRecur(n - 1, res + n);
}/* 斐波那契数列:递归 */
int fib(int n) {// 终止条件 f(1) = 0, f(2) = 1if (n == 1 || n == 2)return n - 1;// 递归调用 f(n) = f(n-1) + f(n-2)int res = fib(n - 1) + fib(n - 2);// 返回结果 f(n)return res;
}/* Driver Code */
int main() {int n = 5;int res;res = recur(n);cout << "\n递归函数的求和结果 res = " << res << endl;res = forLoopRecur(n);cout << "\n使用迭代模拟递归求和结果 res = " << res << endl;res = tailRecur(n, 0);cout << "\n尾递归函数的求和结果 res = " << res << endl;res = fib(n);cout << "\n斐波那契数列的第 " << n << " 项为 " << res << endl;return 0;
}

在这里插入图片描述

递归:1+2+…+n

/* 递归 */
int recur(int n) {// 终止条件if (n == 1)return 1;// 递:递归调用int res = recur(n - 1);// 归:返回结果return n + res;
}

在这里插入图片描述

调用栈

递归函数每次调用自身时,系统都会为新开启的函数分配内存,以存储局部变量、调用地址和其他信息等。
这将导致两方面的结果:
1.函数的上下文数据都存储在称为“栈帧空间”的内存区域中,直至函数返回后才会被释放。因此,递归通常比迭代更加耗费内存空间。
2.递归调用函数会产生额外的开销。因此递归通常比循环的时间效率更低

栈顺序:先入后出

尾递归

如果函数在返回前的最后一步才进行递归调用,则该函数可以被编译器或解释器优化,使其在空间效率上与迭代相当。这种情况被称为尾递归 (tail recursion)。

许多编译器或解释器并不支持尾递归优化,如 Python,即使函数是尾递归形式,仍然可能会遇到栈溢出问题。

普通递归:当函数返回到上一层级的函数后,需要继续执行代码,因此系统需要保存上一层调用的上下文。
尾递归:递归调用是函数返回前的最后一个操作,这意味着函数返回到上一层级后,无须继续执行其他操作,因此系统无须保存上一层函数的上下文。

/* 尾递归 */
int tailRecur(int n, int res) {// 终止条件if (n == 0)return res;// 尾递归调用return tailRecur(n - 1, res + n);
}

普通递归:求和操作是在“归”的过程中执行的,每层返回后都要再执行一次求和操作。
尾递归:求和操作是在“递”的过程中执行的,“归”的过程只需层层返回。
在这里插入图片描述

递归树

给定一个斐波那契数列 0, 1, 1, 2, 3, 5, 8, 13, … ,求该数列的第 𝑛 个数字:

/* 斐波那契数列:递归 */
int fib(int n) {// 终止条件 f(1) = 0, f(2) = 1if (n == 1 || n == 2)return n - 1;// 递归调用 f(n) = f(n-1) + f(n-2)int res = fib(n - 1) + fib(n - 2);// 返回结果 f(n)return res;
}

在函数内递归调用了两个函数,这意味着从一个调用产生了两个调用分支。如图 所示,这样不断递归调用下去,最终将产生一棵层数为 𝑛 的递归树(recursion tree)。
在这里插入图片描述
从本质上看,递归体现了“将问题分解为更小子问题”的思维范式,这种分治策略至关重要。
从算法角度看,搜索、排序、回溯、分治、动态规划等许多重要算法策略直接或间接地应用了这种思维方式。
从数据结构角度看,递归天然适合处理链表、树和图的相关问题,因为它们非常适合用分治思想进行分析。

两者对比

在这里插入图片描述
事实上,“调用栈”和“栈帧空间”这类递归术语已经暗示了递归与栈之间的密切关系。
1.递:当函数被调用时,系统会在“调用栈”上为该函数分配新的栈帧,用于存储函数的局部变量、参数、返回地址等数据。
2.归:当函数完成执行并返回时,对应的栈帧会被从“调用栈”上移除,恢复之前函数的执行环境。
因此,可以使用一个显式的栈来模拟调用栈的行为,从而将递归转化为迭代形式:

/* 使用迭代模拟递归 */
int forLoopRecur(int n) {// 使用一个显式的栈来模拟系统调用栈stack<int> stack;int res = 0;// 递:递归调用for (int i = n; i > 0; i--) {// 通过“入栈操作”模拟“递”stack.push(i);}// 归:返回结果while (!stack.empty()) {// 通过“出栈操作”模拟“归”res += stack.top();stack.pop();}// res = 1+2+3+...+nreturn res;
}

尽管迭代和递归在很多情况下可以互相转化,但不一定值得这样做,有以下两点原因:
1.转化后的代码可能更加难以理解,可读性更差;
2.对于某些复杂问题,模拟系统调用栈的行为可能非常困难;
总之,选择迭代还是递归取决于特定问题的性质。

时间复杂度

运行时间可以直观且准确地反映算法的效率。
1.确定运行平台,包括硬件配置、编程语言、系统环境等,这些因素都会影响代码的运行效率;
2.评估各种计算操作所需的运行时间;
3.统计代码中所有的计算操作,并将所有操作的执行时间求和,从而得到运行时间。
实际上,统计算法的运行时间既不合理也不现实。首先,我们不希望将预估时间和运行平台绑定,因为算法需要在各种不同的平台上运行。其次,我们很难获知每种操作的运行时间,这给预估过程带来了极大的难度。

统计时间增长趋势

时间复杂度分析统计的不是算法运行时间,而是算法运行时间随着数据量变大时的增长趋势

/* 常数阶 */
//虽然运行时间很长,但它与输入数据大小 n 无关
int constant(int n) {int count = 0;int size = 100000;for (int i = 0; i < size; i++)count++;return count;
}/* 线性阶 */
int linear(int n) {int count = 0;for (int i = 0; i < n; i++)count++;return count;
}

相较于直接统计算法的运行时间,时间复杂度分析的特点:
1.时间复杂度能够有效评估算法效率;
2.时间复杂度的推算方法更简便;
3. 时间复杂度也存在一定的局限性。

函数渐近上界

将线性阶的时间复杂度记为 O ( n ) O(n) O(n) ,这个数学符号称为大 O 记号 big‑ Onotation,表示函数 𝑇(n)的渐近上界 (asymptotic upper bound).
在这里插入图片描述
在这里插入图片描述
计算渐近上界就是寻找一个函数 f ( n ) f(n) f(n) ,使得当 n n n 趋向于无穷大时, T ( n ) T(n) T(n) f ( n ) f(n) f(n) 处于相同的增长级别,仅相差一个常数项 c 的倍数。

推算方法

第一步:统计操作数量:
a.操作数量 𝑇(𝑛) 中的各种系数、常数项都可以忽略;
b.循环嵌套时使用乘法。总操作数量等于外层循环和内层循环操作数量之积。
第二步:判断渐近上界:
在 𝑛 趋于无穷大时,最高阶的项将发挥主导作用,其他项的影响都可以忽略。

常见类型

在这里插入图片描述
在这里插入图片描述
常数阶 𝑂(1): 常数阶的操作数量与输入数据大小 𝑛 无关,即不随着 𝑛 的变化而变化。

线性阶 𝑂(𝑛): 线性阶的操作数量相对于输入数据大小 𝑛 以线性级别增长。

遍历数组和遍历链表等操作的时间复杂度均为 𝑂(𝑛) ,其中 𝑛 为数组或链表的长度.

平方阶 𝑂(𝑛2): 平方阶的操作数量相对于输入数据大小 𝑛 以平方级别增长。平方阶通常出现在嵌套循环中。

指数阶 𝑂(2𝑛): 指数阶增长非常迅速,在穷举法(暴力搜索、回溯等)中比较常见。对于数据规模较大的问题,指数阶是不可接受的,通常需要使用动态规划或贪心算法等来解决。

对数阶 𝑂(log 𝑛): 与指数阶相反,对数阶反映了“每轮缩减到一半”的情况。设输入数据大小为 𝑛 ,由于每轮缩减到一半,因此循环次数是 log ⁡ 2 n \log_2 n log2n ,即 2 n 2^n 2n 的反函数。简记为 𝑂(log 𝑛).

线性对数阶 𝑂(𝑛 log ): 线性对数阶常出现于嵌套循环中,两层循环的时间复杂度分别为 𝑂(log 𝑛) 和 𝑂(𝑛)。
主流排序算法的时间复杂度通常为 𝑂(𝑛 log 𝑛) ,例如快速排序、归并排序、堆排序等。

阶乘阶 𝑂(𝑛!): 阶乘阶对应数学上的“全排列”问题。给定 𝑛 个互不重复的元素,求其所有可能的排列方案。
因为当 𝑛 ≥ 4 时恒有 𝑛! > 2𝑛 ,所以阶乘阶比指数阶增长得更快,在 𝑛 较大时也是不可接受的。

最差、最佳、平均时间复杂度

算法的时间效率往往不是固定的,而是与输入数据的分布有关。

实际中很少使用最佳时间复杂度,因为通常只有在很小概率下才能达到,可能会带来一定的误导性。而最差时间复杂度更为实用,因为它给出了一个效率安全值;
最差时间复杂度和最佳时间复杂度只出现于“特殊的数据分布”,这些情况的出现概率可能很小,并不能真实地反映算法运行效率。相比之下,平均时间复杂度可以体现算法在随机输入数据下的运行效率,用 Θ 记号来表示。

空间复杂度

空间复杂度(space complexity)用于衡量算法占用内存空间随着数据量变大时的增长趋势。

算法相关空间

输入空间:用于存储算法的输入数据。
暂存空间:用于存储算法在运行过程中的变量、对象、函数上下文等数据。
输出空间:用于存储算法的输出数据。
一般情况下,空间复杂度的统计范围是“暂存空间”加上“输出空间”。

暂存空间可以进一步划分为三个部分:
1.暂存数据:用于保存算法运行过程中的各种常量、变量、对象等。
2.栈帧空间:用于保存调用函数的上下文数据。系统在每次调用函数时都会在栈顶部创建一个栈帧,函数返回后,栈帧空间会被释放。
3.指令空间:用于保存编译后的程序指令,在实际统计中通常忽略不计。

在这里插入图片描述

推算方法

空间复杂度的推算方法与时间复杂度大致相同,只需将统计对象从“操作数量”转为“使用空间大小”。
通常只关注最差空间复杂度。 因为内存空间是一项硬性要求,必须确保在所有输入数据下都有足够的内存空间预留。

最差空间复杂度中的“最差”有两层含义:
1.以最差输入数据为准;
2.以算法运行中的峰值内存为准。

在递归函数中,需要注意统计栈帧空间。

常见类型

在这里插入图片描述
常数阶 𝑂(1): 常数阶常见于数量与输入数据大小 𝑛 无关的常量、变量、对象。
需要注意的是,在循环中初始化变量或调用函数而占用的内存,在进入下一循环后就会被释放,因此不会累积占用空间,空间复杂度仍为 𝑂(1) ;

线性阶 𝑂(𝑛): 线性阶常见于元素数量与 𝑛 成正比的数组、链表、栈、队列等。

平方阶 𝑂(𝑛2): 平方阶常见于矩阵和图,元素数量与 𝑛 成平方关系。

指数阶 𝑂(2𝑛): 指数阶常见于二叉树。

层数为 𝑛 的“满二叉树”的节点数量为 2^𝑛 − 1 ,占用 𝑂(2𝑛) 空间

对数阶 𝑂(log 𝑛): 对数阶常见于分治算法。例如归并排序,输入长度为 𝑛 的数组,每轮递归将数组从中点处划分为两半,形成高度为 log 𝑛 的递归树,使用 𝑂(log 𝑛) 栈帧空间。

权衡时间与空间

降低时间复杂度通常需要以提升空间复杂度为代价,反之亦然。我们将牺牲内存空间来提升算法运行速度的思路称为“以空间换时间”;反之,则称为“以时间换空间”。

学习地址

学习地址:https://github.com/krahets/hello-algo
重新复习数据结构,所有的内容都来自这里。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Web 常用的 扩展开发框架

当谈到提升浏览器功能和用户体验时&#xff0c;浏览器扩展成了一股强大的力量&#xff0c;备受用户青睐。在众多的Web扩展开发框架中&#xff0c;WXT和Plasmo凭借其丰富的工具和特性&#xff0c;以及简化的开发流程&#xff0c;成为开发者们的首选。在本文中&#xff0c;我们将…

数据分析-Pandas如何画自相关图

数据分析-Pandas如何画自相关图 数据分析和处理中&#xff0c;难免会遇到各种数据&#xff0c;那么数据呈现怎样的规律呢&#xff1f;不管金融数据&#xff0c;风控数据&#xff0c;营销数据等等&#xff0c;莫不如此。如何通过图示展示数据的规律&#xff1f; 数据表&#x…

C#,文字排版的折行问题(Word-wrap problem)的算法与源代码

1、英文的折行问题 给定一个单词序列&#xff0c;以及一行中可以输入的字符数限制&#xff08;线宽&#xff09;。 在给定的顺序中放置换行符&#xff0c;以便打印整齐。 假设每个单词的长度小于线宽。 像MS word这样的文字处理程序负责放置换行符。 这个想法是要有平衡的线条。…

专业140+总分430+西南交通大学924信号与系统考研经验电子信息与通信工程,真题,大纲,参考书

今年报考西南交通大学&#xff0c;考研分数专业课924信号与系统140&#xff0c;总分430&#xff0c;各门分数都还是比较均衡&#xff0c;经过一年的复习&#xff0c;有得有失&#xff0c;总结一下自己的复习经历&#xff0c;希望给大家有点帮助&#xff0c;在复习中做的更好&am…

钉钉平台“智”领宠物界,开启萌宠智能新时代!

在当前数字化转型的浪潮中&#xff0c;钉钉用便捷的数字化解决方案推动了宠物业界的智能升级。一家宠物用品公司采用无雀科技数字化管理系统&#xff0c;与钉钉平台结合&#xff0c;解决了小型企业普遍存在的财务管理不清晰、业务流程不规范、客户信息核对繁琐等痛点问题。 针对…

AHU 汇编 实验六

一、实验名称&#xff1a;实验6 输入一个16进制数&#xff0c;把它转换为10进制数输出 实验目的&#xff1a; 培养汇编中设计子程序的能力 实验过程&#xff1a; 源代码&#xff1a; data segmentbuff1 db Please input a number(H):$buff2 db 30,?,30 dup(?),13,10buff3 …

多维时序 | Matlab实现VMD-CNN-LSTM变分模态分解结合卷积神经网络结合长短期记忆神经网络多变量时间序列预测

多维时序 | Matlab实现VMD-CNN-LSTM变分模态分解结合卷积神经网络结合长短期记忆神经网络多变量时间序列预测 目录 多维时序 | Matlab实现VMD-CNN-LSTM变分模态分解结合卷积神经网络结合长短期记忆神经网络多变量时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:Stepper)

步骤导航器组件&#xff0c;适用于引导用户按照步骤完成任务的导航场景。 说明&#xff1a; 该组件从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 仅能包含子组件StepperItem。 接口 Stepper(value?: { index?…

微信小程序小白易入门基础教程1

微信小程序 基本结构 页面配置 页面配置 app.json 中的部分配置&#xff0c;也支持对单个页面进行配置&#xff0c;可以在页面对应的 .json 文件来对本页面的表现进行配置。 页面中配置项在当前页面会覆盖 app.json 中相同的配置项&#xff08;样式相关的配置项属于 app.js…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:RichText)

富文本组件&#xff0c;解析并显示HTML格式文本。 说明&#xff1a; 该组件从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。该组件无法根据内容自适应设置宽高属性&#xff0c;需要开发者设置显示布局。 子组件 不包含子组…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的石头剪刀布手势识别系统详解(深度学习模型+UI界面代码+训练数据集)

摘要&#xff1a;本篇博客深入探讨了使用深度学习技术开发石头剪刀布手势识别系统的过程&#xff0c;并分享了完整代码。该系统利用先进的YOLOv8、YOLOv7、YOLOv6、YOLOv5算法&#xff0c;并对这几个版本进行性能对比&#xff0c;如mAP、F1 Score等关键指标。文章详细阐述了YOL…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的远距离停车位检测系统(深度学习代码+UI界面+训练数据集)

摘要&#xff1a;开发远距离停车位检测系统对于提高停车效率具有关键作用。本篇博客详细介绍了如何运用深度学习构建一个远距离停车位检测系统&#xff0c;并提供了完整的实现代码。该系统基于强大的YOLOv8算法&#xff0c;并对比了YOLOv7、YOLOv6、YOLOv5&#xff0c;展示了不…

TS271IDT运算放大器芯片中文资料PDF数据手册引脚图图片参数价格功能

产品描述&#xff1a; TS271 是一款低成本、低功耗的单通道运算放大器&#xff0c;设计用于采用单电源或双电源供电。该运算放大器采用意法半导体硅栅CMOS工艺&#xff0c;具有出色的消耗-速度比。该放大器非常适合低功耗应用。 电源可通过引脚 8 和 4 之间连接的电阻器进行外…

2024年【高压电工】考试及高压电工考试总结

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 高压电工考试考前必练&#xff01;安全生产模拟考试一点通每个月更新高压电工考试总结题目及答案&#xff01;多做几遍&#xff0c;其实通过高压电工模拟试题很简单。 1、【单选题】 为了保证频率偏差不超过规定值,必…

基于Springboot的预报名管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的预报名管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&a…

用miniconda建立PyTorch、Keras、TensorFlow三个环境

一、配置清华镜像conda源 由于网络问题&#xff0c;直接使用conda默认的源下载包可能会非常慢。为了解决这个问题&#xff0c;可以配置国内镜像源来加速包的下载。清华大学TUNA协会提供了一个常用的conda镜像源。下面是如何配置清华镜像源的步骤&#xff1a; 1. 配置清华conda…

发布DDD脚手架到Maven仓库,IntelliJ IDEA 配置一下即可使用

作者&#xff1a;小傅哥 博客&#xff1a;https://bugstack.cn 项目&#xff1a;https://gaga.plus 沉淀、分享、成长&#xff0c;让自己和他人都能有所收获&#xff01;&#x1f604; 大家好&#xff0c;我是技术UP主&#xff0c;小傅哥。 这篇文章将帮助粉丝伙伴们更高效地利…

使用 Jenkins 和 Spinnaker 构建 Kubernetes CI/CD

无论您是新手还是持续集成和持续交付以及容器化领域的经验丰富&#xff0c;本文都将为您提供设置 Spinnaker 以满足您的软件应用程序交付需求的基本知识。 了解 Jenkins、Spinnaker 和 Kubernetes Kubernetes 和 Jenkins 是两个强大的工具&#xff0c;它们相互配合&#xff0…

Head First Design Patterns - 命令模式

什么是命令模式 命令模式&#xff0c;把请求封装成对象&#xff0c;以便使用不同的请求、队列或者日志请求来参数化其他对象&#xff0c;并支持可撤回的操作。 为什么会有命令模式 假设要设置一个遥控器&#xff0c;遥控器需要控制多个设备&#xff0c;每个设备除了开关&#…

ARM64汇编06 - 基本整型运算指令

ADD (immediate) 将 Xn 与 imm 相加&#xff0c;结果赋值给 Xd&#xff0c;imm 是无符号数&#xff0c;范围为 0 - 4095。 shift 是对 imm 进行移位&#xff0c;shift 为 0 的时候&#xff0c;表示左移 0 位&#xff0c;即不变。shift 为 1 的时候&#xff0c;表示左移12 位&a…