内存
1. 计算机的作用:对数据进行存储和运算。首先我们需要知道我们目前使用的计算机都是二进制的计算机,就以为着计算机只可以存储和运算二进制的数据。例如下载好的一部电影,该电影可以存储到计算机中,计算机中存储的是基于二进制的电影数据,然后我们可以通过相关的视频播放软件结合相关的硬件对电影的二进制数据进行相关的运算操作,所产生的结果就是我们可以看到电影的画面和听到音频的声音。
- 问题:阐述计算机如何计算1+2的结果?
- 阐述:简单理解为,首先可以将1和2输入到计算机中,然后计算机会将1和2转换成二进制的数据进行数据存储,然后通过加法器进行两个二进制数值的计算并返回结果。
- 分析:上述的阐述中提到,计算机首先需要存储1和2这两个数值,那么计算机如何进行数据的存储呢?那么毫无疑问,计算机可以将数据直接存储到内存中。
- 变量:我们在编程世界中,可以将某个数值直接赋值给一个变量,但是最终数值会被存储到计算机的内存中,因此我们可以理解为,变量表示的就是计算机中进行数据存储的某一块内存。
- 如何形象化的理解计算机的内存?
- 举例:将计算机的内存空间映射到我们现实生活中的话,内存就好比是我们在现实生活中三维立体的空间。生活在北京的北漂们,几乎都居住的是一个独立的公寓或者合租在一个几居室的某一个房间中,那么北漂甲就好比是数据,而他所居住的房间则就是存储数据的一块内存空间。
- 分析:从上述案例中,我们可以得知北漂甲居住的房间会有两个基本的属性,其一就是房间空间的大小,其二就是房间的一个位置标识(门牌号)。那么计算机中存储数据的内存空间也会有这两个最基本的属性:内存空间大小和内存空间的地址。内存空间的大小可以表示该空间可以存储数据值的大小范围,内存空间的地址(用十六进制数值表示)可以用来通过寻址定位、查找到该内存空间中所存储的数据值。
- 如何理解 a = 10 这条赋值语句对应的内存图呢?
- 引用:当一个变量中存储的是某一块内存空间的地址,则该变量即可成为那块内存空间的引用。a=10,a就是10所在内存空间的一个引用。
- 指向:当一个变量中存储了一块内存空间的地址,则称该变量(引用)指向了那块内存。
- 不同类型数据占用内存空间的大小:整形(4字节),浮点型(8字节),字符型(1字节)
顺序表
顺序表: 集合中存储的元素是有顺序的。顺序表的结构可以分为两种形式:单数据类型和多数据类型。
- 单数据类型:在内存中如何存储 int a = 10,20,30,如何取得每一个数据值呢?
- 多数据类型:在内存中如何存储 li = 10,'a',96.5,如何获取每一个数据值呢?
- 顺序表的弊端:顺序表的结构需要预先知道数据大小来申请连续的存储空间,而在进行扩充时又需要进行数据的搬迁。
- Python中的 list 和 tuple 两种类型采用了顺序表的实现技术。
链表
链表: 相对于顺序表,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。
- 链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是不像顺序表一样连续存储数据,而是每一个结点(数据存储单元)里存放下一个结点的信息(即地址):
1、单向链表
单向链表也叫单链表,是表中最简单的一种形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域。这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值。
- 表中元素elem用来存放具体的数据。
- 链接域next用来存放下一个节点的位置。
- 变量p指向链表的头节点(首节点)的位置,从p出发能找到表中的任意节点。
Python实现单链表
- 单向链表的抽象数据类型定义:
- is_empty() # 链表是否为空
- length() # 链表长度
- travel() # 遍历整个链表
- add(item) # 链表头部添加元素
- append(item) # 链表尾部添加元素
- insert(pos, item) # 指定位置添加元素
- remove(item) # 删除节点
- search(item) # 查找节点是否存在
## 封装节点数据结构
class Node():
def __init__(self, item):
self.item = item
# 存储下一个节点的地址
self.next = None
def __str__(self):
return self.item
## 封装链表数据结构
class Link():
# 初始化一个空链表
def __init__(self):
# 永远指向第一个节点的地址
self._head = None
def isEmpty(self):
return self._head == None
def add(self, item):
# 创建一个新的节点对象
node = Node(item)
# 将节点的插入到链表的头部
node.next = self._head
self._head = node
def travel(self):
# cur = self._head = node
cur = self._head
while cur:
print(cur.item)
# 将下一个地址赋值给cur
cur = cur.next
def length(self):
count = 0
cur = self._head
while cur:
count += 1
cur = cur.next
return count
def append(self, item):
cur = self._head
pre = None # cur前面节点的地址
node = Node(item)
# 如果链表为空则新节点作为链表中的第一个节点
if self._head is None: # 当链表为空时赋值给_head
self._head = node
# 链表为非空时对应的插入情况
while cur:
pre = cur
cur = cur.next
per.next = node
def insert(self, pos, item):
cur = self._head
pre = None
node = Node(item)
length = self.length()
# 索引超出范围时插入最后
if pos > length:
self.append(item)
# 索引插入头部时
if pos <= 0:
self.add(item)
# 按照索引正常插入
for i in range(pos):
pre = cur
cur = cur.next
pre.next = node
node.next = cur
def remove(self, item):
cur = self._head
pre = None
# 删除第一个节点时
if item == cur.item:
self._head = cur.next
# 正常删除流程
while cur:
if cur.item == item:
pre.next = cur.next
return
else:
pre = cur
cur = cur.next
def search(self, item):
find = False
cur = self._head
while cur:
if cur.item == item:
return True
break
cur = cur.next
return find
link = Link()
link.add('a')
link.append('b')
link.insert(2, '哈哈')
link.append('c')
link.remove(10)
link.travel()
link.length()
link.search('bb')