- 内存
- 顺序表
- 链表
就是说在A py文件中导入B这个模块的话,如果没有
的话,那么这个A py文件会自动执行
所以为了避免这个被执行,就需要加个if,这样的话就不会执行print
面向对象
内存是以字节为存储单位
一个字节=八位二进制
int 用四个字节存储
eg:假设a是int 型数据,那么在内存中的存储如图
一、顺序表的两种基本形式:
顺序表存储的就是一组类型相同的数据,将他们连续存储,方便计算机的寻找
第一种:
eg:存储Li=【200,390,78,12112】这一组数据,因为这组数据都是int型,所以可以采用顺序表的形式存储
Li就相当于0x23(第一个数据的内存地址),指向第一个数据。
Li[3]:从Li开始,即从0x23开始,跳过3个存储单元
Li[3]=0x23+3*4Bytes
下标代表的就是偏移量,下标为0的意义就是偏移量为0,也就是不偏移
第二种:元素外置
列表存储的元素不是同一类型
地址都是占4个字节,所以每一个地址的存储单元都一样
由于列表存储的不是同一类型的元素,所以采用元素外置的存储方式
先向操作系统申请一块内存空间存储第一个元素12,再向操作系统申请一块内存空间存储第二个元素ab,注意,这两个元素的存储空间不一定是连在一起的,是分开的,第三四元素同上
把这四个元素的存储地址用4个连续的存储空间存起来,也就是向操作系统申请16个连续的存储单元
li代表的就是0x324
li[2]:由li的0x324开始,向后偏移2,找到0x332,然后得到0x332里面存储的内容0x53,由0x53这个内存地址找到1.111
二、顺序表的结构与实现
一个顺序表的完整信息包括两部分,一部分是表中的元素集合,另一部分是为实现正确操作而需记录的信息,即有关表的整体情况的信息,这部分信息主要包括元素存储区的容量和当前表中已有的元素个数两项
顺序表的两种实现方式:
分离式的表头区要有一块内存存储数据区的起始地址
元素存储区替换
一体式结构由于顺序表信息区与数据区连续存储在一起,所以若想更换数据区,则只能整体搬迁,即整个顺序表对象(指存储顺序表的结构信息的区域)改变了。
分离式结构若想更换数据区,只需将表信息区中的数据区链接地址更新即可,而该顺序表对象不变。
元素存储区扩充
1.每次扩充增加固定数目的存储位置,如每次扩充增加10个元素位置,这种策略可称为线性增长。
特点:节省空间,但是扩充操作频繁,操作次数多。
2.每次扩充容量加倍,如每次扩充增加一倍存储空间。(空间换时间)
特点:减少了扩充操作的执行次数,但可能会浪费空间资源。以空间换时间,推荐的方式。
链表单向链表:
表元素域elem用来存放具体的数据。
链接域next用来存放下一个节点的位置(python中的标识)
变量p指向链表的头节点(首节点)的位置,从p出发能找到表中的任意节点。尾结点指向为空。
eg:
python变量标识的本质:
a保存的不是10,而是10所在的内存单元的地址
b代表的是一块空间,这个空间里存的是20的地址
python变量的本质就是地址,赋值只是改变了该变量的指向而已
头插法:
单链表的操作
is_empty() 链表是否为空
length() 链表长度
travel() 遍历整个链表
add(item) 链表头部添加元素
append(item) 链表尾部添加元素
insert(pos, item) 指定位置添加元素
remove(item) 删除节点
search(item) 查找节点是否存在
class Node(object):
"""节点"""
def __init__(self, elem):
self.elem = elem
self.next = None
class SinglelinkList(object):
"""单链表"""
def __init__(self, node=None):
self.__head = node#_head指向第一个节点
def is_empty(self):
"""链表是否为空"""
return self.__head == None#头节点是否指向为空
def length(self):
"""链表长度"""
# cur游标,用来移动遍历节点
cur = self._head#让cur和_head指向同一个节点
# count记录数量
count = 0#当此链表为空链表时也满足条件
while cur != None:
count += 1
cur = cur.next
return count
def travel(self):
"""遍历整个链表"""
cur = self._head
while cur != None:
print(cur.elem,end="")
cur = cur.next
def add(self, item):
"""链表头部添加元素,头插法"""
node = Node(item)
#要先让新节点的next指向原先的头节点
#如果head先指向新节点的话,那就找不到原来的头节点了
node.next = self.__head
self.__head = node
def append(self, item):
"""链表尾部添加元素"""
node = Node(item)
if self.is_empty():
self._head = node#让_head指向node
else:
cur = self._head
while cur.next != None:
cur = cur.next
cur.next = node
def insert(self, pos, item):
"""指定位置添加元素
:param pos 从0开始
"""
if pos <= 0:
self.add(item)
elif pos > (self.length()-1):
self.append(item)
else:
pre = self.__head
count = 0
while count < (pos-1):
count += 1
pre = pre.next
# 当循环退出后,pre指向pos-1位置
node = Node(item)
node.next = pre.next
pre.next = node
def remove(self, item):
"""删除节点"""
cur = self.__head
pre = None
while cur != None:
if cur.elem == item:
# 先判断此结点是否是头节点
# 头节点
if cur == self.__head:
self.__head = cur.next
else:
pre.next = cur.next
break
else:
pre = cur
cur = cur.next
def search(self, item):
"""查找节点是否存在"""
cur = self.__head
while cur != None:
if cur.elem == item:
return True
else:
cur = cur.next
return False
if __name__ == "__main__":
ll = SinglelinkList()#创建具体的对象代表具体的一个链表
print(ll.is_empty())
print(ll.length())
ll.append(1)
print(ll.is_empty())
print(ll.length())
ll.append(2)
ll.add(8)
ll.append(3)
ll.append(4)
ll.append(5)
ll.append(6)
# 8 1 2 3 4 5 6
ll.insert(-1, 9) # 9 8 1 23456
ll.travel()
ll.insert(3, 100) # 9 8 1 100 2 3456
ll.travel()
ll.insert(10, 200) # 9 8 1 100 23456 200
ll.travel()
ll.remove(100)
ll.travel()
ll.remove(9)
ll.travel()
ll.remove(200)
ll.travel()
ll.search(5)



