python链表——链表重新排序

输入:1->2->3->4->5->6->7

输出:1->7->2->6->3->5->4

或者

输入:1->2->3->4->5->6

输出:1->6->2->5->3->4

思路:

1. 将1->2->3->4->5->6->7分成:1->2->3 与 4->5->6->7,将后半部分逆序7->6->5->4

2. 合并1->2->3与7->6->5->4 为1->7->2->6->3->5->4

3. 划分:就是找到中间节点mid,作为后半部分的头节点(注意后半部分的节点数量会比前半部分多0个或者1个节点),这里引入了slow与fast两个外部变量,fast一次走2步,slow一次走一步,这样fast走完时,slow正好走了一半,从而找到中间节点,同时,还需引入slow_pre外部变量,作为slow的前一个节点,目的是为了找到中间节点的slow时,通过slow_pre.next = None的方式,断开链表,分成2个链表

4. 逆序:输入后半段的头节点,也就是mid,实现对链表逆序操作,可参考之前的文章,此处采用插入法逆序(链表逆序

5. 合并:引入外部变量cur1, cur2用来操作两个链表,每个节点仍然是2次指针操作,但要注意,每节点指针操作结束后,需要将外部操作变量cur下移。最后当cur1遍历结束,即cur1.next为None时,跳出循环,将cur1.next指向cur2,cur2为最后一个节点。

代码:

def find_mid_node(head):
    # 头节点为空,或者链表为单节点,直接返回
    if head is None or head.next is None:
        return head
    fast = head
    slow = head
    slow_pre = head
    while fast is not None and fast.next is not None:
        slow_pre = slow
        slow = slow.next       # 每次移动1个节点,当fast结束时,slow走了一半
        fast = fast.next.next  # 每次隔一个赋值,一步走2个节点
    # 需要把指向slow的指针断了,这样才能变成两个链表,即slow前一个节点的next指针为空
    slow_pre.next = None
    return slow    # slow走了链表的一半,返回的值就是中间节点mid


def reverse(head):
    if head is None or head.next is None:
        return head
    cur = head
    pre = None
    while cur:
        nex = cur.next
        cur.next = pre
        pre = cur
        cur = nex
    head = pre
    return head


def reorder(head):
    if head is None or head.next is None:
        return head

    cur1 = head
    mid = find_mid_node(head)
    cur2 = reverse(mid)
    # 两个链表长度相等或者差1个,只需用cur1.next作为循环条件,遍历
    while cur1.next is not None:
        #对链表1的节点2次指针操作
        tmp = cur1.next
        cur1.next = cur2
        cur1 = tmp

        #对链表2的节点2次指针操作
        tmp = cur2.next
        cur2.next = cur1
        cur2 = tmp
    # cur1.next为空,跳出循环,指向最后一个cur2节点
    cur1.next = cur2
    return cur1
# 测试
if __name__ == "__main__":
    link = LinkedList()
    print("========== before ============")
    link.add(1)
    link.add(2)
    link.add(3)
    link.add(4)
    link.add(5)
    link.add(6)
    link.print_link()
    print("========== after ============")
    reorder(link.head)
    link.print_link()
#结果
========== before ============
1
2
3
4
5
6
========== after ============
1
6
2
5
3
4

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值