Array 数组

Array 数组

数组(Array)是一种线性表数据结构.它用一组连续的内存空间,来存储一组具有相同类型的数据.

  1. 线性表数据结构:素之间是简单的线性关系, 每个元素至多有一个前继元素, 至多有一个后继元素(首位和末位只是单向的).像线段一样, 可以从入口或出口无限增减元素的数据结构.
    包括: 数组,链表、队列、栈等
  2. 连续的内存空间, 保证数组的数据都连续的分布在物理介质上
  3. 存储的数据具有相同类型, 保证了每个数据元素占用的物理空间大小都是相等的

特性

  1. 内存连续和类型相同的限制使得数组拥有特性: 随机访问, 按下标随机访问数组元素:
    一维数组: a[i]_address = base_address + i * data_type_size
    二维m * n数组: a[i][j] = base_address + (i * n + j) * data_type_size
  2. 假设要访问第3个元素, 通过公式可以直接得到内存地址:base_address+3*data_type_size
  3. 为了保持数组随机访问的特性, 插入和删除要付出很大的代价维护数组.
    插入: 在末位插入,不需要移动数据, 是O(1), 但首位需要将所有元素都后移一位, 就是O(n).
    因为在每个位置插入的概率是一样的: 1/n + 2/n + 3/n+ … n/n = (n+1)/2, 平均时间复杂度是O(n)
    针对元素乱序的数组, 可以通过将指定位置元素复制到末位, 然后将插入元素放到指定位置, 数组本身是乱序的, 不会受太大影响, 操作的时间复杂度降到O(1)
    删除: 掉首位元素后, 剩余的元素都要依次前进一个位置, 同插入一样也是O(n)
    优化的方法: 记录每次要删除元素,标记为删除状态,达到数组存储上限执行真正的删除
  4. 数组简单易用,在实现上使用的是连续的内存空间,可以借助 CPU 的缓存机制,预读数组中的数据,所以访问效率更高.
    而链表在内存中并不是连续存储,所以对 CPU 缓存不友好,没办法有效预读
  5. 缺点是大小固定,一经声明就要占用整块连续内存空间.如果声明的数组过大,系统可能没有足够的连续内存空间分配给它,导致“内存不足(out of memory)”.如果声明的数组过小,则可能出现不够用的情况.这时只能再申请一个更大的内存空间,把原数组拷贝进去,非常费时

Note

  1. 数组自身没有查找, 其实是按下标访问数组元素, 查找的时间复杂度指的是基于数组结构的查找算法的复杂度, 比如二分查找算法的时间复杂度是O(logn)
  2. c语言里下面代码会一直打印: 函数体内的局部变量会连续压栈, 像数组一样连续的存在内存空间上,
    比如…|i|arr[2]|arr[1]|arr[0]|…, 执行arr[3]=0时发生了数组溢出, arr[3]实际是i所在的位置, 相当于执行i=0.
int main(int argc, char* argv[]){
    int i = 0;
    int arr[3] = {0};
    for(; i<=3; i++){
        arr[i] = 0;
        printf("hello world\n");
    }
    return 0;
}
  1. 为什么数组的索引从0开始
    可能有历史原因, 但个人倾向于是因为便于计算物理位置.
    索引从0开始: a[i]_address = base_address + i * data_type_size
    索引从1开始: a[i]_address = base_address + (i - 1) * data_type_size
    寻址公式是基础中的基础, 执行的频率肯定也很高. 多出的一步计算消耗, 完全可以通过程序猿的条件设置抵消掉.
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值