题目描述:
假设给定链表1->2->3->4->5->6->7中指向第5个元素的指针,要求把结点5删除,删除后的链表变为1->2->3->4->6->7
分析与解答:
一般而言,要删掉单链表中的一个结点p,首先需要找到结点p的前驱结点pre,然后通过pre.next=p.next来实现对结点p的删除。但是对于本题而言,由于无法获取到结点p的前驱结点,所以不能采用这种传统的方法。
可以分如下两种情况来分析:
- 如果这个结点是链表的最后一个结点,那么无法删除这个结点;
- 如果这个结点不是链表中的最后一个结点,可以通过
把其后继结点的数据复制到当前结点中,然后删除其后继结点
的方法来实现。实现方法如下图所示:
在上图中,首先把结点p的后继结点的数据复制到结点p的数据域中,接着把后继结点删除。
算法性能分析:
由于这种方法不需要遍历链表,只需要完成一个数据复制与结点删除的操作,所以时间复杂度O(1);
由于这种方法只用了常数个额外的指针变量,所以空间复杂度也为O(1)
实现代码:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2020/1/18 10:18
# @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 printList(head):
"""
打印链表
:param head: 链表头结点
:return:
"""
cur = head.next
while cur is not None:
print(cur.data, end=' ')
cur = cur.next
def removeNode(p):
"""
给定单链表中的某个结点,删除该结点
:param p: 要删除的链表中某个结点
:return: True or False ,删除成功与否
"""
if p == None or p.next == None: # 如果结点为空或者结点为尾结点(即没有后继结点),则无法删除
return False
p.data = p.next.data
tmp = p.next
p.next = tmp.next
return True
if __name__ == '__main__':
i = 1
head = LNode()
tmp = None
cur = head
p = None
while i < 8:
tmp = LNode(i)
cur.next = tmp
cur = tmp
if i == 5:
p = tmp
i += 1
print('before remove ' + str(p.data), end=': ')
printList(head)
result = removeNode(p)
if result:
print('\nafter ', end=': ')
printList(head)
else:
print('failed!')
结果:
引申:
只给定单链表中某个结点p(非空结点),如何在p前面插入一个结点
思路:
首先分配一个新节点 q,把结点 q 插入到结点 p 后,然后把 p 的数据域复制到结点 q 中,最后把结点 p 的数据域设置为待插入的值。
end