zoukankan      html  css  js  c++  java
  • 算法漫游指北(第四篇):python中实现链表、单链表的实现、单向循环链表、双向链表

    一、python中实现链表(二)

    python中实现链表(一)见https://www.cnblogs.com/Nicholas0707/p/12730944.html

    单链表的实现

     

    0、定义节点

    class Node:
        """单链表的结点"""
        def __init__(self,item):
            # _item存放数据元素
            self.item = item
            # _next是下一个节点的标识
            self.next = None
    

      

     

    1、定义链表

    class SingleLinked(object):
        """定义单向链表"""
    ​
        # 初始化链表
        def __init__(self, node=None):
            self._head = node  # 默认头节点为空
    

      

    2、判断空:

     # 判断链表为空
         def is_empty(self):
             # 头节点为空则链表为空
             return self._head is None
    

      

    分析:如果链表的self._head为空,则说明链表的首节点就是空的,表示为空链表。

    3、尾部添加元素

        def append(self, item):
            """尾部添加元素"""
            node = SingleNode(item)
            # 先判断链表是否为空,若是空链表,则将_head指向新节点
            if self.is_empty():
                self._head = node
            # 若不为空,则找到尾部,将尾节点的next指向新节点
            else:
                cur = self._head
                while cur.next != None:
                    cur = cur.next
                cur.next = node
    

      

    示例

    class Node:
    ​
        def __init__(self,item):
            self.item = item
            self.next = None
    ​
    ​
    class SingleLink:
    ​
        def __init__(self,node=None):
            self._head = node
        
        def is_empty(self):
            # 头节点为空则链表为空
            return self._head is None
    ​
        def append(self, item):
            """尾部添加元素"""
            node = Node(item)
            # 先判断链表是否为空,若是空链表,则将_head指向新节点
            if self.is_empty():
                self._head = node
            # 若不为空,则找到尾部,将尾节点的next指向新节点
            else:
                cur = self._head
                while cur.next != None:
                    cur = cur.next
                cur.next = node
    ​
    ​
    sl1 = SingleLink()
    ​
    sl1.append('张三')
    sl1.append('李四')
    sl1.append('王五')
    

      

    添加节点过程分析:

    (1)如果是空链表的话:

    创建新的节点node对象

    node = Node('张三'),

    这里的node.item = '张三', node.next=None,

    并将self._head =node,此时 self._head 不再为空

     

    (2)再次添加新的节点:

    创建第二个节点node对象

    node = Node('李四'),

    cur为当前游标,将_head的值赋值给cur,

    此时是添加第二个节点,cur = self._head 即第一个节点的node.next=None,还是无法进入while循环

    直接执行 cur.next = node语句,

    cur.next = Node('李四')

    即SingleLink对象._head=Node('张三')

    SingleLink对象._head.next = Node('李四')

     

    (3)添加第三个节点

     

    创建第三个节点node对象

    node = Node('王五'),

    cur为当前游标,将_head的值赋值给cur,

    此时是添加第三个节点,cur = self._head 即第一个节点的node.next= Node('李四'),

    进入while循环

    执行 cur.next = node语句,

    cur = cur.next

    从头节点寻找下一个节点,直到cur.next==None,即一直找到尾节点,即next指向为空的节点,这里是第二个节点

    最后执行

    cur.next = node

    即cur.next = Node('王五')

    即SingleLink对象._head=Node('张三')

    SingleLink对象._head.next = Node('李四')

    SingleLink对象._head.next.next = Node('王五')

     

    4、返回链表长度

        def length(self):
            """链表长度"""
            if self.is_empty():
                return 0
            else:
                # cur初始时指向头节点
                cur = self._head
                count = 0
                # 尾节点指向None,当未到达尾部时
                while cur != None:
                    count += 1
                    print('执行了')
                    # 将cur后移一个节点
                    cur = cur.next
                return count
    

      

     

    分析:使用游标(cur)从链表的头节点找到尾部。

    执行过程动图

     

     

    5、头部添加元素:

        def add(self, item):
            """头部添加元素"""
            node = Node(item)
            if self.empty():
                # 空链表添加新节点
                self.__head = node
            else:
                # 注意这两句的顺序不能换
                # 将新节点的链接域next指向之前的头节点,即_head指向的位置
                node.next = self.__head
                # 将链表新的头_head指向刚刚添加的新节点
                self.__head = node
    

      

    示例

    class Node:
    ​
        def __init__(self,item):
            self.item = item
            self.next = None
    ​
    ​
    class SingleLink:
    ​
        def __init__(self,node=None):
            self._head = node
    ​
        def is_empty(self):
            # 头节点为空则链表为空
            return self._head is None
    ​
        def append(self, item):
            """尾部添加元素"""
            node = Node(item)
    ​
            # 先判断链表是否为空,若是空链表,则将_head指向新节点
            if self.is_empty():
                self._head = node
            # 若不为空,则找到尾部,将尾节点的next指向新节点
            else:
                cur = self._head
                print(cur)
                while cur.next != None:
                    cur = cur.next
                cur.next = node
    ​
        def length(self):
            """链表长度"""
            if self.is_empty():
                return 0
            else:
                # cur初始时指向头节点
                cur = self._head
                count = 0
                # 尾节点指向None,当未到达尾部时
                while cur != None:
                    count += 1
                    # 将cur后移一个节点
                    cur = cur.next
                return count
    ​
        # 头部添加元素
        def add(self, item):
            """头部添加元素"""
            node = Node(item)
            if self.empty():
                # 空链表添加新节点
                self.__head = node
            else:
                # 注意这两句的顺序不能换
                # 将新节点的链接域next指向之前的头节点,即_head指向的位置
                node.next = self.__head
                # 将链表新的头_head指向刚刚添加的新节点
                self.__head = node
    sl1 = SingleLink()
    ​
    sl1.add('张三')
    sl1.add('李四')
    

      

     

    分析执行过程动图

     

    6、指定位置添加元素

        def insert(self, pos, item):
            """指定位置添加元素"""
            # 若指定位置pos为第一个元素之前,则执行头部插入
            if pos <= 0:
                self.add(item)
            # 若指定位置超过链表尾部,则执行尾部插入
            elif pos > (self.length()-1):
                self.append(item)
            # 找到指定位置
            else:
                node = Node(item)
                count = 0
                # pre用来指向指定位置pos的前一个位置pos-1,初始从头节点开始移动到指定位置
                pre = self._head
                while count < (pos-1):
                    #通过循环找到要插入节点的前一个节点
                    count += 1
                    pre = pre.next
                # 先将新节点node的next指向插入位置的节点
                node.next = pre.next
                # 将插入位置的前一个节点的next指向新节点
                pre.next = node
         
    

      

     

    7、删除节点

        def remove(self, item):
            """删除节点"""
            if self.is_empty():
                return False
            cur = self._head  # 定义cur游标
            pre = None  # 定义pre游标,为cur的前一个位置
            while cur is not None:
                # 找到了指定元素
                if cur.item == item:
                    # # 如果第一个就是删除的节点
                    if cur == self._head:
                        # 将头节点的下一个节点赋给头节点
                        self._head = cur.next
                        return True
                    # 非头节点情况
                    else:
                        # 删除操作,将删除位置前一个节点的next指向删除位置的后一个节点
                        pre.next = cur.next
                        return True
                # 移动游标
                else:
                    # 这两句顺序不能反,继续按链表后移节点
                    pre = cur
                    cur = cur.next
            return False
    ​
    

      

    8、查找节点是否存在

        def search(self, item):
    ​
            """链表查找节点是否存在,并返回True或者False"""
            if self.is_empty():
                return False
            else:
                cur = self._head  # 定义游标
                while cur is not None:
                    if cur.item == item:
                        return True
                    else:
                        cur = cur.next  # 游标后移
                return False
    

      


    9、遍历链表:

        def travel(self):
            # 遍历链表
            if self.is_empty():
                return None
            else:
                item_list = []  # 元素列表
                cur = self._head
                # 如果游标不为空,则打印游标对应的元素,游标向后移动
                while cur is not None:
                    item_list.append(cur.item)
                    cur = cur.next  # 游标下移
                return item_list
    ​
    

      

    10、整体代码示例

    class Node:
        """单链表的结点"""
        def __init__(self,item):
            # _item存放数据元素
            self.item = item
            # _next是下一个节点的标识
            self.next = None
    ​
    ​
    class SingleLink:
    ​
        def __init__(self,node=None):
            self._head = node
    ​
        def is_empty(self):
            # 头节点为空则链表为空
            return self._head is None
    ​
        def append(self, item):
            """尾部添加元素"""
            node = Node(item)
    ​
            # 先判断链表是否为空,若是空链表,则将_head指向新节点
            if self.is_empty():
                self._head = node
            # 若不为空,则找到尾部,将尾节点的next指向新节点
            else:
                cur = self._head
                print(cur)
                while cur.next != None:
                    cur = cur.next
                cur.next = node
    ​
        def length(self):
            """链表长度"""
            if self.is_empty():
                return 0
            else:
                # cur初始时指向头节点
                cur = self._head
                count = 0
                # 尾节点指向None,当未到达尾部时
                while cur != None:
                    count += 1
                    # 将cur后移一个节点
                    cur = cur.next
                return count
    ​
        # 头部添加元素
        def add(self, item):
            """头部添加元素"""
            node = Node(item)
            if self.empty():
                # 空链表添加新节点
                self.__head = node
            else:
                # 注意这两句的顺序不能换
                # 将新节点的链接域next指向之前的头节点,即_head指向的位置
                node.next = self.__head
                # 将链表新的头_head指向刚刚添加的新节点
                self.__head = node
    ​
        def insert(self, pos, item):
    ​
            """指定位置添加元素"""
            # 若指定位置pos为第一个元素之前,则执行头部插入
            if pos <= 0:
                self.add(item)
            # 若指定位置超过链表尾部,则执行尾部插入
            elif pos > (self.length()-1):
                self.append(item)
            # 找到指定位置
            else:
                node = Node(item)
                count = 0
                # pre用来指向指定位置pos的前一个位置pos-1,初始从头节点开始移动到指定位置
                pre = self._head
                while count < (pos-1):
                    count += 1
                    pre = pre.next
                # 先将新节点node的next指向插入位置的节点
                node.next = pre.next
                # 将插入位置的前一个节点的next指向新节点
                pre.next = node
    ​
        def remove(self, item):
            """删除节点"""
            if self.is_empty():
                return False
            cur = self._head  # 定义cur游标
            pre = None  # 定义pre游标,为cur的前一个位置
            while cur is not None:
                # 找到了指定元素
                if cur.item == item:
                    # # 如果第一个就是删除的节点
                    if cur == self._head:
                        # 将头节点的下一个节点赋给头节点
                        self._head = cur.next
                        return True
                    # 非头节点情况
                    else:
                        # 删除操作,将删除位置前一个节点的next指向删除位置的后一个节点
                        pre.next = cur.next
                        return True
                # 移动游标
                else:
                    # 这两句顺序不能反,继续按链表后移节点
                    pre = cur
                    cur = cur.next
            return False
        # 查找节点是否存在
        def search(self, item):
    ​
            """链表查找节点是否存在,并返回True或者False"""
            if self.is_empty():
                return False
            else:
                cur = self._head  # 定义游标
                while cur is not None:
                    if cur.item == item:
                        return True
                    else:
                        cur = cur.next  # 游标后移
                return False
    ​
    ​
        def travel(self):
            # 遍历链表
            if self.is_empty():
                return None
            else:
                item_list = []  # 元素列表
                cur = self._head
                # 如果游标不为空,则打印游标对应的元素,游标向后移动
                while cur is not None:
                    item_list.append(cur.item)
                    cur = cur.next  # 游标下移
                return item_list
    ​
    sl1 = SingleLink()
    ​
    sl1.append('张三')
    sl1.append('李四')
    sl1.insert(1,'王五')
    ​
    print(sl1._head.item)
    print(sl1._head.next.item)
    print(sl1._head.next.next.item)
    ​
    ​
    sl1.remove('王五')
    ​
    print(sl1._head.item)
    print(sl1._head.next.item)
    print(sl1.search('张三'))
    ​
    print(sl1.travel())
    

      

    单向循环链表

    所谓单向循环链表,不过是在单向链表的基础上,如响尾蛇般将其首尾相连,也因此有诸多类似之处与务必留心之点。尤其是可能涉及到头尾节点的操作,不可疏忽。

    单链表的一个变形是单向循环链表,链表中最后一个节点的next域不再为None,而是指向链表的头节点。

    示例

    class Node(object):
        """节点"""
        def __init__(self, item):
            self.item = item
            self.next = None
    ​
    ​
    class SinCycLinkedlist(object):
        """单向循环链表"""
        def __init__(self):
            self._head = None
    ​
        def is_empty(self):
            """判断链表是否为空"""
            return self._head == None
    ​
        def length(self):
            """返回链表的长度"""
            # 如果链表为空,返回长度0
            if self.is_empty():
                return 0
            count = 1
            cur = self._head
            while cur.next != self._head:
                count += 1
                cur = cur.next
            return count
    ​
        def travel(self):
            """遍历链表"""
            if self.is_empty():
                return
            cur = self._head
            print cur.item,
            while cur.next != self._head:
                cur = cur.next
                print cur.item,
            print ""
    ​
    ​
        def add(self, item):
            """头部添加节点"""
            node = Node(item)
            if self.is_empty():
                self._head = node
                node.next = self._head
            else:
                #添加的节点指向_head
                node.next = self._head
                # 移到链表尾部,将尾部节点的next指向node
                cur = self._head
                while cur.next != self._head:
                    cur = cur.next
                cur.next = node
                #_head指向添加node的,这里是与单链表不同的地方
                self._head = node
    ​
        def append(self, item):
            """尾部添加节点"""
            node = Node(item)
            if self.is_empty():
                self._head = node
                node.next = self._head
            else:
                # 移到链表尾部
                cur = self._head
                while cur.next != self._head:
                    cur = cur.next
                # 将尾节点指向node
                cur.next = node
                # 将node指向头节点_head,这里是与单链表不同的地方
                node.next = self._head 
    ​
        def insert(self, pos, item):
            """在指定位置添加节点"""
            if pos <= 0:
                self.add(item)
            elif pos > (self.length()-1):
                self.append(item)
            else:
                node = Node(item)
                cur = self._head
                count = 0
                # 移动到指定位置的前一个位置
                while count < (pos-1):
                    count += 1
                    cur = cur.next
                node.next = cur.next
                cur.next = node
    ​
        def remove(self, item):
            """删除一个节点"""
            # 若链表为空,则直接返回
            if self.is_empty():
                return
            # 将cur指向头节点
            cur = self._head
            pre = None
            # 若头节点的元素就是要查找的元素item
            if cur.item == item:
                # 如果链表不止一个节点
                if cur.next != self._head:
                    # 先找到尾节点,将尾节点的next指向第二个节点
                    while cur.next != self._head:
                        cur = cur.next
                    # cur指向了尾节点
                    cur.next = self._head.next
                    self._head = self._head.next
                else:
                    # 链表只有一个节点
                    self._head = None
            else:
                pre = self._head
                # 第一个节点不是要删除的
                while cur.next != self._head:
                    # 找到了要删除的元素
                    if cur.item == item:
                        # 删除
                        pre.next = cur.next
                        return
                    else:
                        pre = cur
                        cur = cur.next
                # cur 指向尾节点
                if cur.item == item:
                    # 尾部删除
                    pre.next = cur.next
    ​
        def search(self, item):
            """查找节点是否存在"""
            if self.is_empty():
                return False
            cur = self._head
            if cur.item == item:
                return True
            while cur.next != self._head:
                cur = cur.next
                if cur.item == item:
                    return True
            return False
    ​
    if __name__ == "__main__":
        ll = SinCycLinkedlist()
        ll.add(1)
        ll.add(2)
        ll.append(3)
        ll.insert(2, 4)
        ll.insert(4, 5)
        ll.insert(0, 6)
        print "length:",ll.length()
        ll.travel()
        print ll.search(3)
        print ll.search(7)
        ll.remove(1)
        print "length:",ll.length()
        ll.travel()
    

      

    双向链表

    一种更复杂的链表是“双向链表”或“双面链表”。每个节点有两个链接:一个指向前一个节点,当此节点为第一个节点时,指向空值;而另一个指向下一个节点,当此节点为最后一个节点时,指向空值。

    链表实现

    class Node(object):
        """双向链表节点"""
        def __init__(self, item):
            self.item = item
            self.next = None
            self.prev = None
    ​
    ​
    class DLinkList(object):
        """双向链表"""
        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 travel(self):
            """遍历链表"""
            cur = self._head
            while cur != None:
                print cur.item,
                cur = cur.next
            print ""
    ​
        def add(self, item):
            """头部插入元素"""
            node = Node(item)
            if self.is_empty():
                # 如果是空链表,将_head指向node
                self._head = node
            else:
                # 将node的next指向_head的头节点
                node.next = self._head
                # 将_head的头节点的prev指向node
                self._head.prev = node
                # 将_head 指向node
                self._head = node
    ​
        def append(self, item):
            """尾部插入元素"""
            node = Node(item)
            if self.is_empty():
                # 如果是空链表,将_head指向node
                self._head = node
            else:
                # 移动到链表尾部
                cur = self._head
                while cur.next != None:
                    cur = cur.next
                # 将尾节点cur的next指向node
                cur.next = node
                # 将node的prev指向cur
                node.prev = cur
    ​
    ​
    ​
        def search(self, item):
            """查找元素是否存在"""
            cur = self._head
            while cur != None:
                if cur.item == item:
                    return True
                cur = cur.next
            return False
    

      

    指定位置插入节点

        def insert(self, pos, item):
            """在指定位置添加节点"""
            if pos <= 0:
                self.add(item)
            elif pos > (self.length()-1):
                self.append(item)
            else:
                node = Node(item)
                cur = self._head
                count = 0
                # 移动到指定位置的前一个位置
                while count < (pos-1):
                    count += 1
                    cur = cur.next
                # 将node的prev指向cur
                node.prev = cur
                # 将node的next指向cur的下一个节点
                node.next = cur.next
                # 将cur的下一个节点的prev指向node
                cur.next.prev = node
                # 将cur的next指向node
                cur.next = node
    

      

    删除元素

        def remove(self, item):
            """删除元素"""
            if self.is_empty():
                return
            else:
                cur = self._head
                if cur.item == item:
                    # 如果首节点的元素即是要删除的元素
                    if cur.next == None:
                        # 如果链表只有这一个节点
                        self._head = None
                    else:
                        # 将第二个节点的prev设置为None
                        cur.next.prev = None
                        # 将_head指向第二个节点
                        self._head = cur.next
                    return
                while cur != None:
                    if cur.item == item:
                        # 将cur的前一个节点的next指向cur的后一个节点
                        cur.prev.next = cur.next
                        # 将cur的后一个节点的prev指向cur的前一个节点
                        cur.next.prev = cur.prev
                        break
                    cur = cur.next
    

      

     

  • 相关阅读:
    Lua笔记4 语句
    Corps humain
    La Famille
    短语
    Lua笔记6 编译、执行与错误
    poser une question
    Photon——Exception Handling 异常处理
    Photon——Calling Operations 调用操作
    Photon——Licenses 许可证
    Photon——Firewall Settings 防火墙设置
  • 原文地址:https://www.cnblogs.com/Nicholas0707/p/12804303.html
Copyright © 2011-2022 走看看