一、单链表定义
单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。
链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。
二、python实现
用python实现单链表操作,包括创建、遍历、增添、删除,代码如下:
class Node(object):
"""节点"""
def __init__(self, elem):
self.elem = elem
self.next = None # 初始设置下一节点为空
'''
上面定义了一个节点的类,当然也可以直接使用python的一些结构。比如通过元组(elem, None)
'''
# 下面创建单链表,并实现其应有的功能
class SingleLinkList(object):
"""单链表"""
def __init__(self, node=None): # 使用一个默认参数,在传入头结点时则接收,在没有传入时,就默认头结点为空
self.__head = node
def is_empty(self):
'''链表是否为空'''
return self.__head == None
def length(self):
'''链表长度'''
# cur游标,用来移动遍历节点
cur = self.__head
# count记录数量
count = 0
while cur != None:
count += 1
cur = cur.next
return count
def travel(self):
'''遍历整个列表'''
cur = self.__head
while cur != None:
print(cur.elem, end=' ')
cur = cur.next
print("\n")
def add(self, item):
'''链表头部添加元素'''
node = Node(item)
node.next = self.__head
self.__head = node
def append(self, item):
'''链表尾部添加元素'''
node = Node(item)
# 由于特殊情况当链表为空时没有next,所以在前面要做个判断
if self.is_empty():
self.__head = node
else:
cur = self.__head
while cur.next != None:
cur = cur.next
cur.next = node
def insert(self, pos, item):
'''指定位置添加元素'''
if pos <= 0:
# 如果pos位置在0或者以前,那么都当做头插法来做
self.add(item)
elif pos > self.length() - 1:
# 如果pos位置比原链表长,那么都当做尾插法来做
self.append(item)
else:
per = self.__head
count = 0
while count < pos - 1:
count += 1
per = per.next
# 当循环退出后,pre指向pos-1位置
node = Node(item)
node.next = per.next
per.next = node
def remove(self, item):
'''删除节点'''
cur = self.__head
pre = None
while cur != None:
if cur.elem == item:
# 先判断该节点是否是头结点
if cur == self.__head:
self.__head = cur.next
else:
pre.next = cur.next
break
else:
pre = cur
cur = cur.next
def search(self, item):
'''查找节点是否存在'''
cur = self.__head
while not cur:
if cur.elem == item:
return True
else:
cur = cur.next
return False
#测试
if __name__ == "__main__":
# node = Node(100) # 先创建一个节点传进去
ll = SingleLinkList()
print(ll.is_empty())
print(ll.length())
ll.append(3)
ll.add(999)
ll.insert(-3, 110)
ll.insert(99, 111)
print(ll.is_empty())
print(ll.length())
ll.travel()
ll.remove(111)
ll.travel()
三、编程题
1、142 环形链表Ⅱ
-
题目
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
说明:不允许修改给定的链表。 -
示例 :
输入:head = [3,2,0,-4], pos = 1
输出:tail connects to node index 1
解释:链表中有一个环,其尾部连接到第二个节点。 -
思路一
创建两个节点,第一个慢节点单步走,第二个快节点两步走,如果没有环,则快节点会首先走到链表尾,退出循环,返回False。如果存在环,则快节点会再第二圈或者第三圈的地方追上慢节点,直到两者相等,则返回True。
可以发现,快节点是慢节点的多少倍,快节点就通过多少圈与慢节点相遇。
所以就根据相遇点距环入口的距离等于头节点距环入口的距离。 -
代码如下
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if head is None or head.next is None :
return None
slow = fast = head
while fast.next and fast.next.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
m = head
while slow != m:
m = m.next
slow = slow.next
return m
return None
-运行结果
- 思路二
采用哈希表的思想,创建一个空字典,若下一个能在字典里找到,则返回,并且重复的元素的值作为入环的第一个节点。 - 代码如下
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
node_dict = {}
temp = head
n = 0
while temp:
node_dict[temp]=n
temp = temp.next
if temp in node_dict:
return temp
n = n + 1
return None
-运行结果
2、206反转链表
-
题目
反转一个单链表。 -
示例
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL -
思路
迭代法,从前往后遍历链表,定义三个指针分别指向相邻的三个结点,反转前两个结点,即让第二个结点指向第一个结点。然后依次往后移动指针,直到第二个结点为空结束,再处理链表头尾即可。 -
代码如下
class Solution(object):
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if head is None:
return None
cur = head
pre = None
nxt = cur.next
while nxt:
cur.next = pre
pre = cur
cur = nxt
nxt = nxt.next
cur.next = pre
head = cur
return head
- 运行结果
部分内容参考:
https://www.cnblogs.com/yudanqu/