1.4python对链表进行重新排序

题目描述:

给定链表:L0->L1->L2…->Ln,把链表重新排序为L0->Ln->L1->L(n-1)…
要求:
(1) 在原来链表的基础上进行排序,即不能申请新的结点;
(2)只能修改结点的next域,不能修改数据域。

思路:

  1. 首先找到链表的中间结点;
  2. 对链表的后半部分子链表进行逆序;
  3. 把链表的前半部分子链表与逆序后的后半部分子链表进行合并,合并的思路为:分别从两个链表各取一个结点进行合并。

实现方法如下图:
在这里插入图片描述
算法性能分析:

查找链表中间结点的方法的时间复杂度为O(n),逆序子链表的时间复杂度为O(n),合并两个子链表的时间复杂度也为O(n),因此,整个方法的时间复杂度为O(n);
由于这种方法只用了常数个额外指针变量,所以空间复杂度为O(1)

代码实现:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time    : 2020/1/16 15:07
# @Author  : buu
# @Software: PyCharm
# @Blog    :https://blog.csdn.net/weixin_44321080
class LNode:
    def __init__(self, data=None, next=None):
        self.data = data
        self.next = next


def FindMiddleNode(head):
    """
    用快慢指针法找到链表Head的中间结点,把链表从中间断成两个子链表
    :param head: 链表头结点
    :return: 链表中间结点
    """
    if head is None or head.next is None:
        return head
    fast = head  # 快指针,遍历链表时每次走两步
    slow = head  # 满指针,遍历链表时每次走一步
    slowPre = head  # 当fast指针到达链表尾时,slow恰好指向链表的中间结点
    while fast is not None and fast.next is not None:
        slowPre = slow  # slowPre存在是为了把链表截断
        slow = slow.next
        fast = fast.next.next
    slowPre.next = None  # 把链表断开成两个独立的子链表
    return slow


def Reverse(head):
    """
    对不带头结点的但链表逆序
    :param head: 链表首结点
    :return: 逆序后的首结点
    """
    if head is None or head.next is None:
        return head
    pre = head  # 前驱结点,此时head为首结点,而非头结点
    cur = head.next  # 当前结点
    next = cur.next  # 后继结点
    pre.next = None  # 此时pre指向首结点,所以逆转后满足pre.next=None
    while cur is not None:
        next = cur.next
        cur.next = pre
        pre = cur
        cur = cur.next
        cur = next
    return pre


def Reorder(head):
    """
    对链表进行排序
    :param head: 链表头结点
    :return:
    """
    if head is None or head.next is None:
        return
    cur1 = head.next  # 前半部分链表第一个结点
    mid = FindMiddleNode(head.next)
    cur2 = Reverse(mid)  # 后半部分链表逆序后的第一个结点
    tmp = None
    while cur1.next is not None:  # 合并两个链表
        tmp = cur1.next  # tmp 用来做连接的中间结点
        cur1.next = cur2
        cur1 = tmp
        tmp = cur2.next
        cur2.next = cur1
        cur2 = tmp
    cur1.next = cur2


if __name__ == '__main__':
    i = 1
    head = LNode()
    tmp = None
    cur = head
    while i < 8:  # 构造第一个链表
        tmp = LNode()
        tmp.data = i
        cur.next = tmp
        cur = tmp
        i += 1
    print('before reorder:', end=' ')
    cur = head.next
    while cur is not None:
        print(cur.data, end=' ')
        cur = cur.next
    # middleNode=FindMiddleNode(head) # 测试中间结点及之后链表
    # print('\nafter: ',end=' ')
    # while middleNode is not None:
    #     print(middleNode.data,end=' ')
    #     middleNode=middleNode.next
    print('\nafter  reorder:', end=' ')
    Reorder(head)
    cur = head.next
    while cur is not None:
        print(cur.data, end=' ')
        cur = cur.next

结果
在这里插入图片描述
引申:

如何查找链表的中间结点

主要思路:

用两个指针从链表的第一个结点开始同时遍历结点,一个快指针每次走2步,另外一个慢指针每次走1步;当快指针先到链表尾部时,慢指针则恰好到达链表中部。(快指针到链表尾部时,当链表长度为奇数时,慢指针指向的即是链表中间指针;当链表长度为偶数时,慢指针指向的结点和慢指针指向的下一个结点都是链表的中间结点)

end

发布了76 篇原创文章 · 获赞 2 · 访问量 2579

猜你喜欢

转载自blog.csdn.net/weixin_44321080/article/details/104004624