链表查改增删及反转、合并

1. 定义

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

1.1 遍历链表

def bian_li(head):
    if not head:
        print("list is null")
        return
    p = head.next
    while p:
        print(p.val)
        p = p.next

1.2 求表长

def get_length(head):
    if not head:
        return -1
    cnt = 0
    p = head.next
    while p:
        cnt += 1
        p = p.next
    return cnt

1.3 删除一个结点

def delete_node(head, node):
    if not head:
        return None
    if not node:
        return head
    p = head
    while p.next != node:
        p = p.next
    p.next = node.next
    return head

1.4 求链表中间结点

链表中间结点即链表长度一半位置处的结点 (L//2+1)

使用快慢指针,当快指针遍历到链尾时,慢指针所指即为中间结点。

def get_mid(head):
    if not head:
        return None
    slow = fast = head
    while fast and fast.next:
        fast = fast.next.next
        slow = slow.next
    return slow

1.5 测试

# 定义结点
head = ListNode(-1)
n1 = ListNode(1)
n2 = ListNode(2)
n3 = ListNode(3)
n4 = ListNode(4)
# 构造链表
head.next = n1
n1.next = n2
n2.next = n3
n3.next = n4

# ---------求表长--------
print(get_length(head))
# 4
# ---------删除表结点--------
delete_node(head, n2)
bian_li(head)
# 1 3 4
# ---------求链表中间结点--------
print(get_mid(head).val)
# 2

2. 链表反转

时间复杂度o(n)

2.1 递归

2.2 头插法(使用三个指针)

def reverse(head):
    if not head:
        return None
    # 已反转新链表的首结点
    pre = None
    # 下一个待反转的结点
    next = None
    # 当前待反转的结点 
    head = head.next
    while head:
        # 保存下一个待反转的结点
        next = head.next
        # 采用头插法,每次插入pre之前
        head.next = pre
        # pre 再次移动到已反转新链表的首位
        pre = head
        # 当前待反转结点后移
        head = next
    # 给反转后的新链表加一个头结点
    temp = ListNode(-1)
    temp.next = pre
    return temp

2.3 借助栈

def reverse1(head):
    if not head:
        return head
    stack = []
    p = head.next
    while p:
        stack.append(p)
        p = p.next
    # 新链表头结点
    new_head = ListNode(-1)
    temp = new_head
    while stack:
        temp.next = stack.pop()
        temp = temp.next
    # 设置最后一个结点的next
    temp.next = None
    return new_head

2.4 测试

new_head = reverse(head)
bian_li(new_head)
# 4 3 2 1
new_head1 = reverse1(head)
bian_li(new_head1)
# 4 3 2 1

3. 链表合并

3.1 合并两个排序链表

def merge_sort_list(head1, head2):
    if not head1:
        return head2
    if not head2:
        return head1
    # 默认链表带头结点
    p1, p2 = head1.next, head2.next
    # 新链表的头结点
    head = ListNode(-1)
    p3 = head
    while p1 and p2:
        if p1.val <= p2.val:
            p3.next = p1
            p1 = p1.next
        else:
            p3.next = p2
            p2 = p2.next
        p3 = p3.next
    if p1:
        p3.next = p1
    if p2:
        p3.next = p2
    return head

3.2 测试

head1 = ListNode(-1)
head2 = ListNode(-1)
n1 = ListNode(1)
n2 = ListNode(2)
n3 = ListNode(3)
n4 = ListNode(4)
n5 = ListNode(5)

head1.next = n1
n1.next = n3
n3.next = n5

head2.next = n2
n2.next = n4

new_head = merge_sort_list(head1, head2)
bian_li(new_head)
# 1 2 3 4 5

4. 结点查找

4.1 链表倒数第K个结点

使用两个指针,first先走k-1步,然后last再走。

def lastK(head, k):
    if not head or k < 1:
        return None
    first = last = head
    while k != 0 and first:
        k -= 1
        first = first.next
    # k>链表长度
    if not first:
        return -1
    while first:
        first = first.next
        last = last.next
    return last.val

4.2 测试

head = ListNode(-1)
n1 = ListNode(1)
n2 = ListNode(2)
n3 = ListNode(3)
n4 = ListNode(4)
n5 = ListNode(5)
head.next = n1
n1.next = n3
n3.next = n5

print(lastK(head, 3))
# 1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值