python如何实现链表的逆序

“”“
给定一个带头结点的单链表,请将其逆序。即如果单链表原来为 head -> 1 -> 2 -> 3 ->4 -> 5 -> 6 -> 7,那么逆序后变为head -> 7 -> 6 -> 5 ->4 -> 3 -> 2 -> 1。
”“”

方法一:就地逆序

class LNode:
    def __init__(self,data):
        self.data = data
        self.next = None


def reverse(head):
    # 特殊情况:头节点为空或者为单节点,直接返回
    if head is None or head.next is None:
        return head
    pre = None
    cur = None
    next = None
    # 把链表首结点变为尾结点
    cur = head.next
    next = cur.next
    cur.next = None
    pre = cur
    cur = next
    # 使当前遍历到的结点 cur 指向其前驱结点
    while cur.next !=None:
        next = cur.next
        cur.next= pre
        pre= cur
        cur = cur.next
        cur= next
    # 链表中最后一个节点指到倒数第二个节点
    cur.next = pre
    # 将链表的头节点知道原链表的尾节点
    head.next = cur

if __name__ == "__main__":

    i = 1
    #链表的头结点
    head = LNode(0)
    cur = head
    #构造单链表
    while i<8:
        tmp = LNode(i)
        cur.next = tmp
        cur = tmp
        i += 1

    print("原链表:",end=" ")
    cur = head.next
    while cur != None:
        print(cur.data,end=" ")
        cur= cur.next
    print("\n逆序后:",end=" ")
    reverse(head)
    cur = head.next
    while cur != None:
        print(cur.data,end=" ")
        cur = cur.next
原链表: 1 2 3 4 5 6 7
逆序后: 7 6 5 4 3 2 1
以上这种方法只需要对链表进行一次遍历,因此,时间复杂度为 O(N) ,其中, N 为链表
的长度。但是需要常数个额外的变量来保存当前结点的前驱结点与后继结点,因此,空间复
杂度为 0(1 )。

方法二:递归法

“”"
假定原链表为1->2->3->4->5->6->7,递归法的主要思路为:先逆序除第一个结点以外
的子链表(将 1->2->3->4->5->6->7 变为 1 ->7->6 ->5 ->4 ->3 ->2 ),接着把结点 1 添加到逆序的子链表的后面( 1 ->7->6->5->4->3->2 变为 7->6->5->4->3->2->1) 。 同理,在逆序链表 2->3->4->5->6->7 时,也是先逆序子链表 3->4->5->6->7 (逆序为 2->7->6->5->4->3),接着实现链表的整体逆序( 2->7->6 ->5 ->4->3 转换为 7->6->5 ->4 ->3->2 ) 。
“”"

class LNode:
    def __init__(self, data):
        self.data = data
        self.next = None


def recursiveReverse(head):
    """
    方法功能:对不带头结点的单链表进行逆序
    输入参数: firstRef:链表头结点
    """

    # 如果链表为空或者链表中只有一个元素
    if head is None or head.next is None:
        return head
    else:
        # 反转后面的结点
        newhead = recursiveReverse(head.next)
        # 把当前遍历的结点加到后面结点逆序后链表的尾部
        head.next.next = head
        head.next = None
    return newhead


def reverse(head):
    """
    方法功能 : 对带头结点的单链表进行逆序
    输入参数 : head ·链表头结点
    """

    if head is None:
        return
    # 获取链表第一个结点
    firstNode = head.next
    # 对链表进行逆序
    newhead = recursiveReverse(firstNode)
    # 头结点指向逆序后链表的第一个结点
    head.next = newhead
    return newhead


if __name__ == "__main__":

    i = 1
    # 链表的头结点
    head = LNode(0)
    cur = head
    # 构造单链表
    while i < 8:
        tmp = LNode(i)
        cur.next = tmp
        cur = tmp
        i += 1

    print("原链表:", end=" ")
    cur = head.next
    while cur != None:
        print(cur.data, end=" ")
        cur = cur.next
    print("\n逆序后:", end=" ")
    reverse(head)
    cur = head.next
    while cur != None:
        print(cur.data, end=" ")
        cur = cur.next
原链表: 1 2 3 4 5 6 7 
逆序后: 7 6 5 4 3 2 1
由于递归法也只需要对链表进行一次遍历,因此,算法的时间复杂度也为 O(N),其中,
N 为链表的长度。递归法的主要优点是:思路比较直观,容易理解,而且也不需要保存前驱
结点的地址。缺点是:算法实现的难度较大,此外,由于递归法需要不断地调用自己,需要
额外的压技与弹枝操作,因此, 与方法一相比性能会有所下降。

方法三:插入法

“”"
插入法的主要思路为:从链表的第二个结点开始,把遍历到的结点插入到头结点的后面 ,直到遍历结束。假定原链表为 head -> l ->2 ->3 ->4->5 ->6 ->7 , 在遍历到 2 的时候,将其插入到头结点后,链表变为 head->2-> l ->3->4 ->5->6->7,同理将后序遍历到的所有结点都插入到头结点 head 后,就可以实现链表的逆序。
“”"

class LNode:
    def __init__(self, data):
        self.data = data
        self.next = None


def reverse(head):


    # 判断链表是否为空
    if head is None or head.next is None:
        return
    cur = None 
    next = None 
    cur = head.next.next
    # 设置链表第一个结点为尾结点
    head.next.next = None
    # 把遍历到结点插入到头结点的后面
    while cur is not None:
        next = cur.next
        cur.next = head.next
        head.next = cur
        cur = next


if __name__ == "__main__":

    i = 1
    # 链表的头结点
    head = LNode(0)
    cur = head
    # 构造单链表
    while i < 8:
        tmp = LNode(i)
        cur.next = tmp
        cur = tmp
        i += 1

    print("原链表:", end=" ")
    cur = head.next
    while cur != None:
        print(cur.data, end=" ")
        cur = cur.next
    print("\n逆序后:", end=" ")
    reverse(head)
    cur = head.next
    while cur != None:
        print(cur.data, end=" ")
        cur = cur.next

原链表: 1 2 3 4 5 6 7 
逆序后: 7 6 5 4 3 2 1
以上这种方法也只需要对单链表进行一次遍历,因此,时间复杂度为 O(N),其中, N 为
链表的长度。与方法一相比,这种方法不需要保存前驱结点的地址,与方法二相比, 这种方
法不需要递归地调用,效率更高 。

你可能感兴趣的:(python基础)