物理机制
内存IC中有电源,地址信号,数据信号,控制信号等用于输入输出的大量引脚,通过为其指定地址(address),来进行数据的读写
将电源连接到VCC和GND后,就可以给其他引脚传递比如0或1这样的信号了,一般+5v直流电压表示1,0v表示0。
上图中,数据信号引脚有D0D8共8个,表示一次可以输入输出8位(1字节)的数据。地址信号引脚有A0A9共10个,表示可以指定0000000000~1111111111共2^10=1024个地址,地址是数据的存储场所,因此可以得到该内存IC可以存储1024个1字节的数据,也就是1024字节(1KB)。
逻辑模型
我们可以把内存模型假想成楼房,每层存储1个字节数据,楼层号就是一个内存地址。
在每次读写时,会发现每次只能读取1个字节数据太繁琐了,如果一次能读写几层数据该多好,这就产生了数据类型。
数据类型表示存储的是何种类型的数据。如char类型占用1个字节,short类型占用2个字节,long类型占用的4个字节。这样只要定义数据类型,就可以一次读写多层楼的数据了。
指针
指针也是一种变量,它所表示的不是数据的值,而是存储着数据的内存地址。通过使用指针可以对任意指定地址的数据进行读写。如32位的操作系统它的指针变量长度也是32位。
数组
数组是指多个同样数据类型的数据在内存中连续排列的形式,数组中的每个元素通过连续编号区分开来,这就是索引,指定索引后就可以对该索引对应地址的内存进行读写操作了,索引和内存地址的变换工作则由编译器自动实现。
数组定义中的数据类型,表示可以一次可读写的内存大小。如char类型数据一次可读写1字节,short和long类型一次可分别读写2字节和4字节。数组是使用内存的基本。
栈、队列
栈和队列都可以不通过指定地址和索引来对数组元素进行读写,栈和队列的区别在于数据出入顺序不同。栈用的是(LIFO,后入先出)方式,队列用的是(FIFO,先入先出)方式,如果在内存中预留好栈和队列所需的空间,并确定好读写顺序,就不用再指定地址和索引了
在程序中实现栈和队列,就要以适当元素来定义一个用来存储数据的数组,已经对该数组进行读写的函数对。如:往栈中写入数据的函数命名为Push,从栈中读取数据的函数命名为Pop;往队列中写入数据的函数命名为EnQueue,从队列中读取数据函数命名为DeQueue,通过使用这些函数,可以将数据临时保存(写入),需要时在读取出来。
队列一般以环状缓冲区的方式来实现,这样大大节省内存空间,因为每次写入数据就会新占用一个内存地址,而每次读出数据后该内存地址就空置在哪里,这是很浪费的,如果在取出数据后再写入的数据再存入该地址,就可以节省内存空间,整个队列看起来就像圆环状,故叫做环状缓冲区
链表
在数组的各个元素中,除了数据的值以外,通过为其附带下一个元素的索引,即可实现链表,如果附带上一个元素和下一个元素的索引,那就是双向链表。使用链表可以更加高效的对数组数据(元素)进行追加和删除操作。
从删除和添加元素的操作过程可以看到,当一个元素被删除(实际并没有物理删除,只是逻辑删除,也就是通过链表再也找不到这个元素了)后,内存地址闲置在哪里,当有元素加入时,刚才闲置的内存地址被重新利用(定义好相关元素索引值就可以找到元素了),这可以大大节省了内存空间及处理时间。如果是数组,中途加入元素或删除元素,后面的元素全部要跟着移动,这时非常浪费时间的。
二叉树
二叉查找树指在链表的基础上往数组追加元素时,考虑到数据大小关系,将其分成左右两个方向的表现形式。实际的内存并不会分两个方向,这只是在程序逻辑上实现的。
二叉查找树是在链表构造发展而来的表现形式,因此在追加和删除元素方面也同样有效。使用二叉树的便利之处在于它使数据搜索更高效。