zoukankan      html  css  js  c++  java
  • 单链表-Python实现-jupyter->markdown 格式测试

    单链表引入

    • 顺序表
    • 理解Python变量的本质: 变量存储的不是值,是值的地址
    • 理解Python的 "="表示的是指向关系
    • 案例: 交换a,b的值, a=10, b=20
      • a, b = 20, 10
      • t0: a这块内存(也有id), 存储的是10这个值的地址(可能是0x111), b存储的是20这个值(整型4个字节)的地址(可能是0x222)
      • t1: a现在指向b的值的地址(a存储0x222), b指向(存储)10的地址(0x111)
    • Pyhton变量的本质: 指针. 所以Pyhton在定义变量时不必声明变量类型, 因为Pyhton变量根本就不直接存储值, 存储的是值的地址, 通过地址去取值.
    • 真正理解: Pyhton 一切皆对象(存地址嘛, 变量, 容器, 函数, 类...都只是一块地址而已), so 常看到把一个类, 一个函数=给一个变量,就不足为奇了.
    a, b = 10, 20 
    print('交换前',a,b)
    # 交换: 从等号右边开始看, 即把b存储20的地址,现在用a变量存储; 
    # 将a变量存储10的地址,现在用b去指向, 从而实现了a,b互相交换
    # 本质上, 10,20这两个值的地址并未改变, 只是其被引用的变量改变了而已, 改变的是引用
    a, b = b, a
    print('交换后',a, b)
    
    交换前 10 20
    交换后 20 10
    
    # 函数也是一块内存地址而已
    
    def add(x, y):
        return x + y
    
    print(add(3,4))
    
    7
    
    f = add  # 将函数赋值给一个变量f, 即用f来指向这块函数的地址
    print(f(3,4))
    
    7
    

    构造节点类

    • 为什么要用类: 节点 = 数据取 + 指针区(指向下一个节点的地址)
    • 类: 属性 + 操作的封装

    插入: Python3定义类用不用继承object的区别

    # Python3 编写类的是在, object 有无的区别
    
    class A:
        name = "youge"
    
        
    class B(object):
        name = 'youge'
        
        
    if __name__ == '__main__':
        
        a, b = A(), B()
        
        print('无object的类拥有:', dir(a))
        print('有object的类拥有:', dir(b))
    
    无object的类拥有: ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']
    有object的类拥有: ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']
    
    class Node(object):
        """"节点类""""
        def __init__(self, data=None):
            self.data = data
            self.next = None  # Pyhton 的 "=" 就直接想象成 ----> 指向即可(指向下一个节点对象)
    
    node1 = Node(123)  # 实例化一个节点对象
    
    print('这是一个节点对象, 包含属性和操作', node1)
    
    print(f'该节点的数据是:{node1.data}, 指向的节点对象是:{node1.next}')
    
    这是一个节点对象, 包含属性和操作 <__main__.Node object at 0x0000021B939406A0>
    该节点的数据是:123, 指向的节点对象是:None
    

    单链表类ADT

    • is_empty() 判断链表是否为空
    • lenghth() 链表的长度(元素个数)
    • travel 遍历整个链表
    • add(item) 从链表头部增加元素(值)
    • append(item) 从链表尾部增加元素
    • insert(pos, item) 从指定位置(下标)增加元素
    • remove(item) 删除节点
    • search(item)
    • 都是对象方法, 非类方法, 实现时先结构化写出来pass慢慢去实现
    class Node(object):
        """节点类""""
        def __init__(self, data=None):
            self.data = data
            self.next = None  
    
    class SingleLinkList(object):
        """单链表"""
        def is_empty(self):
            pass
        
        def length(self):
            pass
        
        def travel(self):
            pass
        
        def add(self, item):
            pass
        
        def append(self, item):
            pass
        
        def insert(self, pos, item):
            pass 
        
        def remove(self, item):
            pass 
        
        def search(item):
            pass
        
    
        
    # 调用  
    s_lst = SingleLinkList()
    s_lst.is_empty()
    s_lst.length()
    s_lst.travel()
    s_lst.add(123)
    ....
    

    头节点: 将一个节点挂在到单链表中来

    • 链表必须要有一个对象属性来作为头节点
    class Node(object):
        """节点类"""
        def __init__(self, data=None):
            self.data = data
            self.next = None  
    
    
    class SingleLinkList(object):
        """单链表"""
        
        # 头节点可能为空
        # 用户可能是先创建一个节点, 作为链表的头节点
        def __init__(self, node=None):
            self.head = node  # 内部使用维护的,不用给外部访问, 应该设为私有变量
            self.next = None
            
            
    # call
    node1 = Node(111)
    sl_obj = SingleLinkList(node1)  # 将head节点作为链表的头节点
    
    print('将节点对象传给链表的head属性:', sl_obj.head)
    print('属性是一个对象, 访问值用对象.属性来访问:', sl_obj.head.data)
    
    将节点对象传给链表的head属性: <__main__.Node object at 0x0000021B93710828>
    属性是一个对象, 访问值用对象.属性来访问: 111
    

    为什么需要两个类

    • 理解Node类和SingleListLink类 的运作过程
      • 节点类创建节点, 链表类"串联"上节点
    # 分析:
    
    link = SigleLinkList()  # 包含一个 __head -> None
    node = Node(111)  # 包含 (111,None) 
    # 目的: 让链表的 __head属性去指向(111, None)这个节点
    # 让 __head -> None 变为 __head -> (111,None), 正好Python的 --> 指向关系, 其实就是 "="
    
    

    is_empyt 实现

    class Node(object):
        """节点类"""
        def __init__(self, data=None):
            self.data = data
            self.next = None  
    
    class SingleLinkList(object):
        """单链表"""
        def __init__(self, node=None):
            self.__head = node 
            self.next = None
        
        def is_empty(self):
            """链表是否为空"""
            # 只要 __head指向的节点是None即链表为空
            return self.__head == None
        
        def length(self):
            """链表的长度"""
            pass
    

    length实现

    # 分析
    
    # (__head)-> (111, None)->(222,None)->(333,None)->(444,None)
    
    # 需要一个游标(指针)cur 从头数到尾, 并对节点计数
    # cur->__head, 计数, cur->111, 计数,判断111的next是否存在, 存在则cur->nex....循环
    
    
    class Node(object):
        """节点类"""
        def __init__(self, data=None):
            self.data = data
            self.next = None  
    
    class SingleLinkList(object):
        """单链表"""
        def __init__(self, node=None):
            self.__head = node 
            self.next = None
        
        def is_empty(self):
            """链表是否为空"""
            # 只要 __head指向的节点是None即链表为空
            return self.__head == None
        
        def length(self):
            """链表的长度"""
            # 让指针(游标cur)有首先指向头节点对象 cur -> __head 
            # 即 cur, __head 都指向了头节点对象
            cur = self.__head
            # 开始计数, 让指针一边移动, 则一边计数
            count = 0 
            # while 循环,让游标移动, 停止条件是当指针指向当前节点的next值为None时
            # 关于count取值, 0:cur=None, 1:cur.next == None (指针指向哪为位置)
            while cur != None:
                count += 1 
                # 实现指针的"移动": Python中其实就是"="表示 "->" , 注意'='要从右往左看
                cur = cur.next  # 右到左: 将当前节点的next, 让cur去指向
            return count
                
    

    travel 实现

    • 也是变量每个节点, 打印出该节点的数据而已
    # 分析
    
    # 也是游标移动, while的终止条件是当 cur==None时即可
    
    class Node(object):
        """节点类"""
        def __init__(self, data=None):
            self.data = data
            self.next = None  
    
    class SingleLinkList(object):
        """单链表"""
        def __init__(self, node=None):
            self.__head = node 
            self.next = None
        
        def is_empty(self):
            """链表是否为空"""
            # 只要 __head指向的节点是None即链表为空
            return self.__head == None
        
        def length(self):
            """链表的长度"""
            # 让指针(游标cur)有首先指向头节点对象 cur -> __head 
            # 即 cur, __head 都指向了头节点对象
            cur = self.__head
            # 开始计数, 让指针一边移动, 则一边计数
            count = 0 
            # while 循环,让游标移动, 停止条件是当指针指向当前节点的next值为None时
            # 关于count取值, 0:cur=None, 1:cur.next == None (指针指向哪为位置)
            while cur != None:
                count += 1 
                # 实现指针的"移动": Python中其实就是"="表示 "->" , 注意'='要从右往左看
                cur = cur.next  # 右到左: 将当前节点的next, 让cur去指向
            return count
                
            
        def travel(self):
            """元素遍历"""
            # cur->__head
            cur = self.__head
            # 移动, 然后print节点的元素, 当cur==None时终止
            while cur != None:
                print(cur.data)
                cur = cur.next
            
    

    append 实现(尾插法)

    • 尾部插入元素: 即遍历到最后一节点, 将其next指向插入的元素节点即可
    • 首先要将用户给定的元素(值), 作为一个节点对象(data,next)
    • __ head -> 111 ->222 ->None -> (333, None)
    class Node(object):
        """节点类"""
        def __init__(self, data=None):
            self.data = data
            self.next = None  
    
    class SingleLinkList(object):
        """单链表"""
        def __init__(self, node=None):
            self.__head = node 
            self.next = None
        
        def is_empty(self):
            """链表是否为空"""
            # 只要 __head指向的节点是None即链表为空
            return self.__head == None
        
        def length(self):
            """链表的长度"""
            # 让指针(游标cur)有首先指向头节点对象 cur -> __head 
            # 即 cur, __head 都指向了头节点对象
            cur = self.__head
            # 开始计数, 让指针一边移动, 则一边计数
            count = 0 
            # while 循环,让游标移动, 停止条件是当指针指向当前节点的next值为None时
            # 关于count取值, 0:cur=None, 1:cur.next == None (指针指向哪为位置)
            while cur != None:
                count += 1 
                # 实现指针的"移动": Python中其实就是"="表示 "->" , 注意'='要从右往左看
                cur = cur.next  # 右到左: 将当前节点的next, 让cur去指向
            return count
                
            
        def travel(self):
            """元素遍历"""
            # cur->__head
            cur = self.__head
            # 移动, 然后print节点的元素, 当cur==None时终止
            while cur != None:
                print(cur.data, end=' ' )
                cur = cur.next
            
        def append(self, item):
            """尾部添加元素"""
            node = Node(item)  # 用户只关心值, 不关心指针
            # 从头往后遍历
            cur = self.__head
            # 考虑空链表情况 if cur is None:
            if self.is_empty():
                # 直接将 __head -> node即可
                self.__head = node
            else:
                while cur.next != None:
                    cur = cur.next
                # 将尾节点的next -> node
                cur.next = node
    
    

    is_empty, length, travel 测试

    # 测试
    l = SingleLinkList()
    
    print(l.is_empty())
    print(l.length())
    
    l.append(0)
    print(l.is_empty())
    print(l.length())
    
    for i in range(8):
        l.append(i)
    
    l.travel()
    
    True
    0
    False
    1
    0 0 1 2 3 4 5 6 7 
    

    add 实现(头插法)

    • 构建要插入的节点对象
    • 头插的顺序是先让新元素的next->其余节点, 然后链表的__ head -> node
    # 分析
    # link:  head->(111, None)->(222,None)
    
    # 目标: head->(000, None)->(111, None)->(222,None)
    # 1. (000, Next)->(111, None)->(222,None)
    # 2. __head -> (000, Next)->.....
    
    class Node(object):
        """节点类"""
        def __init__(self, data=None):
            self.data = data
            self.next = None  
    
    class SingleLinkList(object):
        """单链表"""
        def __init__(self, node=None):
            self.__head = node 
            self.next = None
        
        def is_empty(self):
            """链表是否为空"""
            # 只要 __head指向的节点是None即链表为空
            return self.__head == None
        
        def length(self):
            """链表的长度"""
            # 让指针(游标cur)有首先指向头节点对象 cur -> __head 
            # 即 cur, __head 都指向了头节点对象
            cur = self.__head
            # 开始计数, 让指针一边移动, 则一边计数
            count = 0 
            # while 循环,让游标移动, 停止条件是当指针指向当前节点的next值为None时
            # 关于count取值, 0:cur=None, 1:cur.next == None (指针指向哪为位置)
            while cur != None:
                count += 1 
                # 实现指针的"移动": Python中其实就是"="表示 "->" , 注意'='要从右往左看
                cur = cur.next  # 右到左: 将当前节点的next, 让cur去指向
            return count
                
            
        def travel(self):
            """元素遍历"""
            # cur->__head
            cur = self.__head
            # 移动, 然后print节点的元素, 当cur==None时终止
            while cur != None:
                print(cur.data, end=' ' )
                cur = cur.next
            
        def append(self, item):
            """尾部添加元素"""
            node = Node(item)  # 用户只关心值, 不关心指针
            # 从头往后遍历
            cur = self.__head
            # 考虑空链表情况 if cur is None:
            if self.is_empty():
                # 直接将 __head -> node即可
                self.__head = node
            else:
                while cur.next != None:
                    cur = cur.next
                # 将尾节点的next -> node
                cur.next = node
    
        def add(self, item):
            """从头部插入元素"""
            node = Node(item)
            # 顺序很关键, 先node的next指向原先 __head所指向的节点, 然后再更新__head->node
            node.next = self.__head.next
            self.__head = node
            
        
    
    # 测试
    l = SingleLinkList()
    
    print(l.is_empty())
    print(l.length())
    
    l.append(0)
    print(l.is_empty())
    print(l.length())
    
    for i in range(8):
        l.append(i)
    
    # 头插入一个 666 
    l.add(666)
    l.travel()
    
    True
    0
    False
    1
    666 0 1 2 3 4 5 6 7 
    

    insert 实现

    • 从任意位置插入元素: 如何定位pos(下标)
    • 找到要插入的位置下标: count计数
    • 用该位置的该node的next->当前位置节点, 前一个节点的Next指向该node, 注意顺序哦
    # 分析
    # link: (111, None)->(222,None)->(333,None)
    
    # 目标: (111, None)->(222,None)->(444,None)->(333,None)
    
    # 顺序: (444,None)->(333,None); ...(222,None)->(444,None)
    
    
    class Node(object):
        """节点类"""
        def __init__(self, data=None):
            self.data = data
            self.next = None  
    
    class SingleLinkList(object):
        """单链表"""
        def __init__(self, node=None):
            self.__head = node 
            self.next = None
        
        def is_empty(self):
            """链表是否为空"""
            # 只要 __head指向的节点是None即链表为空
            return self.__head == None
        
        def length(self):
            """链表的长度"""
            # 让指针(游标cur)有首先指向头节点对象 cur -> __head 
            # 即 cur, __head 都指向了头节点对象
            cur = self.__head
            # 开始计数, 让指针一边移动, 则一边计数
            count = 0 
            # while 循环,让游标移动, 停止条件是当指针指向当前节点的next值为None时
            # 关于count取值, 0:cur=None, 1:cur.next == None (指针指向哪为位置)
            while cur != None:
                count += 1 
                # 实现指针的"移动": Python中其实就是"="表示 "->" , 注意'='要从右往左看
                cur = cur.next  # 右到左: 将当前节点的next, 让cur去指向
            return count
                
            
        def travel(self):
            """元素遍历"""
            # cur->__head
            cur = self.__head
            # 移动, 然后print节点的元素, 当cur==None时终止
            while cur != None:
                print(cur.data, end=' ' )
                cur = cur.next
            
        def append(self, item):
            """尾部添加元素"""
            node = Node(item)  # 用户只关心值, 不关心指针
            # 从头往后遍历
            cur = self.__head
            # 考虑空链表情况 if cur is None:
            if self.is_empty():
                # 直接将 __head -> node即可
                self.__head = node
            else:
                while cur.next != None:
                    cur = cur.next
                # 将尾节点的next -> node
                cur.next = node
    
        def add(self, item):
            """从头部插入元素"""
            node = Node(item)
            # 顺序很关键, 先node的next指向原先 __head所指向的节点, 然后再更新__head->node
            node.next = self.__head.next
            self.__head = node
            
        def insert(self, pos, item):
            """从任意位置插入元素"""
            # 考虑pos特殊情况
            if pos <= 0:
                self.add(item)
            elif pos > (self.length()-1):  # 不能包含 ==, 因为insert是前插入哦
                self.append(item)
            else:
                node = Node(item)
                # 前一个节点, 引入一个游标 pre 表示前一个节点
                pre = self.__head
    
                count = 0
                while count < (pos-1):  # 到该位置的前一个节点时终止
                    count += 1
                    pre = pre.next  # 移动
                # 当循环结束后,pre指向(pos-1) 对该位置的前一个节点操作: 
                # 1. 先用node.next -> 原先节点指向的node
                # 2. pre的next -> node
                node.next = pre.next
                pre.next = node
    
    # 测试
    l = SingleLinkList()
    
    print(l.is_empty())
    print(l.length())
    
    l.append(0)
    print(l.is_empty())
    print(l.length())
    
    for i in range(8):
        l.append(i)
    
    # 头插入一个 666 
    l.add(666)
    
    # inset
    l.insert(-1, 999)
    l.insert(2, 6699)
    l.insert(888,999)
    l.insert(5,'cj')
    
    l.travel()
    
    True
    0
    False
    1
    999 0 6699 1 2 cj 3 4 5 6 7 999 
    
    

    search实现

    • 游标去遍历, 比对值
    class Node(object):
        """节点类"""
        def __init__(self, data=None):
            self.data = data
            self.next = None  
    
    class SingleLinkList(object):
        """单链表"""
        def __init__(self, node=None):
            self.__head = node 
            self.next = None
        
        def is_empty(self):
            """链表是否为空"""
            # 只要 __head指向的节点是None即链表为空
            return self.__head == None
        
        def length(self):
            """链表的长度"""
            # 让指针(游标cur)有首先指向头节点对象 cur -> __head 
            # 即 cur, __head 都指向了头节点对象
            cur = self.__head
            # 开始计数, 让指针一边移动, 则一边计数
            count = 0 
            # while 循环,让游标移动, 停止条件是当指针指向当前节点的next值为None时
            # 关于count取值, 0:cur=None, 1:cur.next == None (指针指向哪为位置)
            while cur != None:
                count += 1 
                # 实现指针的"移动": Python中其实就是"="表示 "->" , 注意'='要从右往左看
                cur = cur.next  # 右到左: 将当前节点的next, 让cur去指向
            return count
                
            
        def travel(self):
            """元素遍历"""
            # cur->__head
            cur = self.__head
            # 移动, 然后print节点的元素, 当cur==None时终止
            while cur != None:
                print(cur.data, end=' ' )
                cur = cur.next
            
        def append(self, item):
            """尾部添加元素"""
            node = Node(item)  # 用户只关心值, 不关心指针
            # 从头往后遍历
            cur = self.__head
            # 考虑空链表情况 if cur is None:
            if self.is_empty():
                # 直接将 __head -> node即可
                self.__head = node
            else:
                while cur.next != None:
                    cur = cur.next
                # 将尾节点的next -> node
                cur.next = node
    
        def add(self, item):
            """从头部插入元素"""
            node = Node(item)
            # 顺序很关键, 先node的next指向原先 __head所指向的节点, 然后再更新__head->node
            node.next = self.__head.next
            self.__head = node
            
        def insert(self, pos, item):
            """从任意位置插入元素"""
            # 考虑pos特殊情况
            if pos <= 0:
                self.add(item)
            elif pos > (self.length()-1):  # 不能包含 ==, 因为insert是前插入哦
                self.append(item)
            else:
                node = Node(item)
                # 前一个节点, 引入一个游标 pre 表示前一个节点
                pre = self.__head
    
                count = 0
                while count < (pos-1):  # 到该位置的前一个节点时终止
                    count += 1
                    pre = pre.next  # 移动
                # 当循环结束后,pre指向(pos-1) 对该位置的前一个节点操作: 
                # 1. 先用node.next -> 原先节点指向的node
                # 2. pre的next -> node
                node.next = pre.next
                pre.next = node
                
        def search(self, item):
            """查找元素"""
            cur = self.__head
            # 循环遍历比较值即可
            while cur != None:
                if cur.data == item:
                    return True
                else:
                    # 记得移动游标 ,不然就死循环了
                    cur = cur.next
            return False
        
    

    remove实现

    • 删除某个元素, 删掉第一次找到的那个元素哦
    • 原理: cur找到该节点后, 用pre.next -> cur.next 即可
    • 即需要两个游标: pre 和cur

    但其实, 只需要pre就能达到效果呢

    • pre.next -> node.next 即** pre.next -> pre.next.next**
    class Node(object):
        """节点类"""
        def __init__(self, data=None):
            self.data = data
            self.next = None  
    
    class SingleLinkList(object):
        """单链表"""
        def __init__(self, node=None):
            self.__head = node 
            self.next = None
        
        def is_empty(self):
            """链表是否为空"""
            # 只要 __head指向的节点是None即链表为空
            return self.__head == None
        
        def length(self):
            """链表的长度"""
            # 让指针(游标cur)有首先指向头节点对象 cur -> __head 
            # 即 cur, __head 都指向了头节点对象
            cur = self.__head
            # 开始计数, 让指针一边移动, 则一边计数
            count = 0 
            # while 循环,让游标移动, 停止条件是当指针指向当前节点的next值为None时
            # 关于count取值, 0:cur=None, 1:cur.next == None (指针指向哪为位置)
            while cur != None:
                count += 1 
                # 实现指针的"移动": Python中其实就是"="表示 "->" , 注意'='要从右往左看
                cur = cur.next  # 右到左: 将当前节点的next, 让cur去指向
            return count
                
            
        def travel(self):
            """元素遍历"""
            # cur->__head
            cur = self.__head
            # 移动, 然后print节点的元素, 当cur==None时终止
            while cur != None:
                print(cur.data, end=' ' )
                cur = cur.next
            
        def append(self, item):
            """尾部添加元素"""
            node = Node(item)  # 用户只关心值, 不关心指针
            # 从头往后遍历
            cur = self.__head
            # 考虑空链表情况 if cur is None:
            if self.is_empty():
                # 直接将 __head -> node即可
                self.__head = node
            else:
                while cur.next != None:
                    cur = cur.next
                # 将尾节点的next -> node
                cur.next = node
    
        def add(self, item):
            """从头部插入元素"""
            node = Node(item)
            # 顺序很关键, 先node的next指向原先 __head所指向的节点, 然后再更新__head->node
            node.next = self.__head.next
            self.__head = node
            
        def insert(self, pos, item):
            """从任意位置插入元素"""
            # 考虑pos特殊情况
            if pos <= 0:
                self.add(item)
            elif pos > (self.length()-1):  # 不能包含 ==, 因为insert是前插入哦
                self.append(item)
            else:
                node = Node(item)
                # 前一个节点, 引入一个游标 pre 表示前一个节点
                pre = self.__head
    
                count = 0
                while count < (pos-1):  # 到该位置的前一个节点时终止
                    count += 1
                    pre = pre.next  # 移动
                # 当循环结束后,pre指向(pos-1) 对该位置的前一个节点操作: 
                # 1. 先用node.next -> 原先节点指向的node
                # 2. pre的next -> node
                node.next = pre.next
                pre.next = node
                
        def search(self, item):
            """查找元素"""
            cur = self.__head
            # 循环遍历比较值即可
            while cur != None:
                if cur.data == item:
                    return True
            return False
        
        def remove(self, item):
            """删除首次找到的该元素-两个游标"""
            pre = None
            cur = self.__head
            while cur != None:
                if cur.data == item:
                    # 判断是否为 head
                    if cur == self.__head:
                        self.__head = cur.next
                    else:
                        # 删除: pre.next -> cur.next
                        pre.next = cur.next
                    break
                else:
                   # 移动: pre移动一次, cur也移动一次, 顺序: 必须先移动pre, 才能跟上cur的节奏哦
                    pre = cur
                    cur = cur.next
    
    
    # 测试
    l = SingleLinkList()
    
    print(l.is_empty())
    print(l.length())
    
    l.append(0)
    print(l.is_empty())
    print(l.length())
    
    for i in range(8):
        l.append(i)
    
    # 头插入一个 666 
    l.add(666)
    
    # inset
    l.insert(-1, 999)
    l.insert(2, 6699)
    l.insert(888,999)
    l.insert(5,'cj')
    # 遍历
    l.travel()
    
    l.remove(999)
    # l.remove('aaa')
    
    True
    0
    False
    1
    999 0 6699 1 2 cj 3 4 5 6 7 999 
    
    
    l.travel()
    
    0 6699 1 2 cj 3 4 5 6 7 999 
    
    
    l.remove(999)
    l.travel()
    
    0 6699 1 2 cj 3 4 5 6 7 
    
    

    单链表完整实现

    • object Python3是默认继承的
    • 理解指向在Python中就是"=", 从右往左看
    • 要在头脑中有画面感, 毕竟, "="就是'->'指针呀
    class Node:
        """节点类"""
        def __init__(self, data=None):
            self.data = data
            self.next = None
            
    class SingleLinkList:
        """单链表类"""
        def __init__(self, node=None):
            """构造链表的头节点"""
            self.__head = node
            
        @property    
        def is_empty(self):
            """链表是否为空"""
            return self.__head == None
        
        @property
        def length(self):
            """链表中元素的个数"""
            current = self.__head
            count = 0 
            while current is not None:
                count += 1 
                # 游标不断向后移动
                current = current.next
            return count
        
        def travel(self):
            """遍历列表元素"""
            current = self.__head
            while current != None:
                print(current.data)
                current = current.next
                
        def append(self, item):
            """尾部插入元素"""
            node = Node(item)
            current = self.__head
            if self.is_empty:
                self.__head = node
            else:
                while current.next is not None:
                    current = current.next
                current.next = node
        
        def add(self, item):
            """头部插入元素"""
            node = Node(item)
            if self.is_empty:
                self.__head = node
            else:
                # 插入顺序,脑海里要有画面感
                node.next = self.__head
                self.__head = node
    
        def insert(self, position, item):
            """从指定位置插入元素"""
            if position <= 0:
                self.add(item)
            elif position > (self.length-1):
                self.append(item)
            else:
                node = Node(item)
                prior = self.__head
                count = 0
                while count < (position-1):
                    count += 1
                    prior = prior.next
                # 此时prior已定位到当前位置前一个节点
                node.next = prior.next
                prior.next = node
        
        def search(self, item):
            """搜索元素并范围其位置-首次被找到"""
            position = 0 
            current = self.__head
            while current:
                position += 1 
                if current.data == item:
                    return position-1
                else:
                    # 记得移动游标,不然就死循环了
                    current = current.next
            return False
        
        def remove(self, item):
            """删除元素-首次被找到"""
            # 删除: prior.next -> prior.next.next 或者: prior.next = cur.next
    #         prior = self.__head
    #         position = self.search(item)
    #         if position:
    #             count = 0
    #             while prior:
    #                 count += 1
    #                 if count == position-1
    #                 prior = prior.next
                    
    #         return 
    
            # 这里采用: prior.next = cur.next
            prior = None
            current = self.__head
            while current:
                if current.data == item:
                    # 判断是否为头节点
                    if current == self.__head:
                        self.__head = current.next
                    else:
                        prior.next = current.next
                    break 
                else:
                    # prior先移动一次,到current的位置, 然后current再往后移动一次
                    prior = current
                    current = current.next
    
    
    l = SingleLinkList()
    l.is_empty
    
    True
    
    
    l.append(1)
    l.add(0)
    l.append('cj')
    l.insert(999,666)
    l.travel()
    l.search('cj')
    
    0
    1
    cj
    666
    
    
    2
    
    
    l.add(333)
    l.travel()
    
    333
    333
    333
    0
    1
    cj
    666
    
    
  • 相关阅读:
    Beans
    HDU2830
    HDU1176
    rtc关机闹钟7 jni层 com_android_server_AlarmManagerService
    rtc关机闹钟6 AlarmManagerService研究
    rtc关机闹钟5 AlarmManager研究
    数论学习_裴蜀定理
    hdu-5465-二维BIT+nim
    hdu-1892-二维BIT
    hdu-2227-dp+bit
  • 原文地址:https://www.cnblogs.com/chenjieyouge/p/11617475.html
Copyright © 2011-2022 走看看