由python实现的单向链表来看python的基础概念(赋值,垃圾回收)

之前只是对了解一些基础算法的概念,而并没有真正用代码取去实现过,所以准备在这段时间内把这些算法实现以下,第一个是单向链表,然而通过一个链表又让我想到了python的其它东西(相辅相成)。注:这里就不谈链表的概念了,只是说一说随着我脑洞大开而想到的其它东西。

好了先把我写的单链表给贴出来:

#单链表节点
class SingleNode:
    def __init__(self,item):
        #存放数据
        self.item = item
        #下个节点标识
        self.next = None

#单链表实现
class SingleLL:

    def __init__(self):
        self._head = None

    #判断链表是否为空
    def is_empty(self):
        return self._head == None

    #返回链表长度
    def length(self):
        cur = self._head
        count = 0
        while cur != None:
            count += 1
            #后移一个节点
            cur = cur.next
        return count

    # 打印链表内所有节点
    def print_all(self):
        cur = self._head
        while cur != None:
            print(cur.item)
            cur = cur.next

    #头部添加节点
    def add(self,item):
        #新的节点
        node = SingleNode(item)
        node.next = self._head
        self._head = node

    #尾部添加节点
    def append(self,item):
        #实例化一个节点
        node = SingleNode(item)
        #当为空时, _head直接指向新节点
        if self.is_empty():
            self._head = node
        else:
            #不为空,则找到最后一个节点并将其指向新节点
            cur = self._head
            while cur.next:
                cur = cur.next
            cur.next = node

    #指定位置添加节点(插入),此处设定: pos < 0 :将节点放置于链表头, pos > 0:将节点放置于链表尾
    def insert(self,pos,item):
        node = SingleNode(item)
        if self.is_empty():
            self._head = node
        elif pos <= 0:
            self.add(item)
        else:
            cur = self._head #游标
            cur_pos = 0  # 此时游标所指位置
            #找到链表中pos-1的位置,
            while True:
                if cur_pos == pos - 1:
                    #新节点指向此时位置后的节点
                    node.next = cur.next
                    cur.next = node
                    break
                cur = cur.next
                cur_pos+=1
                #游标指向最后一位时,说明指定插入位置超过链表长度
                if not cur.next:
                    cur.next = node
                    break

    #删除链表中的所有指定节点
    def remove(self,item):
        cur = self._head
        #当前cur的前一个节点
        pre = None
        while cur:
            if cur.item == item:
                #删除首个节点时
                if not pre:
                    self._head = cur.next
                else:
                    pre.next = cur.next
            else:
                pre = cur
            # 后移一个节点
            cur = cur.next

    #判断一个节点是否存在
    def search(self,item):
        sur = self._head
        while sur:
            if sur.item == item:
                return True
            sur = sur.next
        return False

if __name__ == '__main__':
    single_link_list = SingleLL()
    single_link_list.append('11')
    single_link_list.append('22')
    single_link_list.append('33')
    single_link_list.append('44')
    single_link_list.print_all()
    print('----------')
    single_link_list.insert(2,'21')
    single_link_list.print_all()
    print(single_link_list.search('21'))
    print('-------')
    single_link_list.remove('22')
    single_link_list.print_all()

在实现这个链表时我想到了 python的赋值,深浅拷贝,python的垃圾回收机制

python的赋值,在上面对链表的操作中,都是用一个把 self._head 付给一个游标变量然后再依次把下一个节点赋值给 游标,在这里为什么对游标指向的结点进行更改而整个链表就会发生改变呢,下面解释:

这里先将一下 python对象主要分为两大类容器类型对象(list,dict,class..)和非容器类型对象(int,str..)。而像 a =[1],b=a 其实两个变量只是指向了同一块内存,这个时候id(a)==id(b)。其中一个变量发生改变时 a.append(2), 这个时候 打印 b 就是 [1,2] ,id(a)==id(b),代码如下:

a = [1]
b = a
print(id(a)==id(b))
a.append(2)
print(b)
print(id(a)==id(b))


#结果
True
[1, 2]
True

如果是非容器类对象可以发生的改变只有重新赋值 ,而赋值的根本意义是变量指向了另一块内存,如 a=2,b=a,id(a)==id(b), a重新赋值 a=3,这时 id(a)!=id(b),代码如下:

a = 2
b = a
print(id(a)==id(b))
print(b)
a = 3
print(id(a)==id(b))

#结果
True
2
False

在上面实现的链表中,SingleNode类实例化出来的对象也是一个容器类型对象。因此 节点进行改变,整个链表也发生改变。

 

python的垃圾回收机制,在上面链表操作中,我们所做的删除节点操作只是把这个节点的父节点指向了这个节点的子节点,

那么这个节点已经无用,在内存中占用着空间,此时就轮到垃圾回收机制大展身手了。

python的垃圾回收机制以引用计数为主,标记清除、分代回收为辅,

引用计数:如果一个对象的引用数为0,Python虚拟机就会回收这个对象的内存,在上文中删除一个节点,是将此节点的父节点指向此节点的子节点,此时,此节点已经没有被引用,引用数为0,内存被回收。因为 引用计数 存在一些缺陷(像两个容器类型对象循环调用)所以有有了两个作为辅助的回收机制,这里只是简单阐述一下,网上关于垃圾回收机制的优秀文章太多。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值