实现代码:
#Definition for singly-linked list.
class ListNode:
def __init__(self, x): #结点的两个属性
self.data = x
self.next = None #next默认值一般为None
class Solution(object):
def __init__(self):
self.length = 0
self.head = None
def addTwoNumbers(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
#链表下一个元素是否需要加1,或者链表最后是否需要增加结点
carry = 0
res = pre = ListNode(0) #创建res和pre两个结点,具有共同的地址
#判断l1、l2、node是否有值
while l1 or l2 or carry:
if l1:
carry += l1.data
l1 = l1.next
if l2:
carry += l2.data
l2 = l2.next
carry,data = divmod(carry,10) #现在carry具有同结点的和,需要判断sum是否大于10
# pre.next = pre = ListNode(data)
pre.next = ListNode(data) #pre已经存在,创建pre.next;
pre = pre.next #进行迭代更新
return res.next
if __name__ == '__main__':
#定义l1
l1 = ListNode(2)
l1.next = l11 = ListNode(4) #先创建l11:l11 = ListNode(4) 和 #将l11的地址赋给l1.next:l1.next = l11
l11.next = l12 = ListNode(3)
#定义l2
l2 = ListNode(5)
l2.next = l21 = ListNode(6)
l21.next = l22 = ListNode(4)
#创建Solution的对象
addTwoNumbersExp = Solution()
res = addTwoNumbersExp.addTwoNumbers(l1,l2)
while res:
print(res.data)
res = res.next
补充知识:
计算机存储空间被划分为一个一个小块,称为存储结点。存储结点包括数据域和指针域。
线性表:也叫顺序表( linear list),一种基本数据结构。线性表中存储的每个数据称为一个元素,各个元素及其索引是一一对应的关系。线性表有两种存储方式:顺序存储方式和链式存储方式。
数组(array):数组就是线性表的顺序存储方式。数组的内存是连续分配的,并且是静态分配的,即在使用数组之前需要分配固定大小的空间。可以通过索引直接得到数组中的而元素,即获取数组中元素的时间复杂度为O(1)。插入和删除时需要移动元素。
链表(linked-list):链表就是线性表的链式存储方式。链表的内存是不连续的,前一个元素存储地址的下一个地址中存储的不一定是下一个元素。链表通过一个指向下一个元素地址的引用将链表中的元素串起来。
链表分为单向链表、双向链表和循环链表。
单向链表:链表中最基本的数据称为节点(node),每一个节点包含了数据块和指向下一个节点的指针。
结点:单向链表有时候也分为有头结点和无头结点。有头结点的链表实现比较方便(每次插入新元素的时候,不需要每次判断第一个节点是否为空),并且可以直接在头结点的数据块部分存储链表的长度,而不用每次都遍历整个链表。
插入:在链表中插入一个新的元素有两种方式:后插和前插。后插就是每次在链表的末尾插入新元素,前插就是在链表的头插入新元素。 后插法比较符合平常的思维方式,并且保证插入数据的先后顺序。但是由于只保存了头结点,所以每次插入新元素必须重新遍历到链表末尾。为了解决这个问题,考虑增加一个尾指针,指向链表的最后一个节点。由于前插法是在头部插入新元素,那么每次增加新元素可以直接通过头指针索引,但是得到的元素顺序与插入顺序相反。
删除:由于单向链表只存储了头指针,所以删除单向链表中的元素时,需要找到目标节点的前驱节点。
清空链表:由于链表里面的内存是手动分配的,当不再使用这些内存时需要手动删除。
链表翻转:
双向链表:
双向链表就是有两个方向的链表。同单向链表不同,在双向链表中每一个节点不仅存储指向下一个节点的指针,而且存储指向前一个节点的指针。通过这种方式,能够通过在O(1)时间内通过目的节点直接找到前驱节点,但是同时会增加大量的指针存储空间。
插入:在双向链表中插入新元素的操作跟在单向链表中插入新元素的操作类似。
删除:由于双向链表中每个节点记录了它的前驱结点,所以不需要像单向链表中一样索引目的节点的前驱节点,而是可以通过目标节点直接获得。
在双向链表中,第一个节点的前驱节点不是头结点,而是指向一个空指针。同样的,最后一个节点的后驱指向了一个空指针。
循环列表:
循环链表的插入和删除操作与双向链表的实现方式一样。
链表的部分方法:
class ListNode:
def __init__(self,data,next=None):#地址默认为None
self.data = data
self.next = next
class LinkedList:
#初始化信息length和head
def __init__(self):
self.length = 0
self.head = None #head为头结点指针,指向开始结点的指针(即第一个元素结点的存储位置)。
#计算数组的长度
def get_length(self,l_1):
self.head = l_1
while l_1:
self.length += 1
l_1 =l_1.next
return self.length
# 判断链表是否为空
def is_empty(self):
return self.length == 0 #返回bool值
# 在链表末尾添加新结点
def append(self, node):
# 需先判断是否为ListNode类型,若不是需要先转换类型
if isinstance(node, ListNode):
pass
else:
node = ListNode(node)
if self.is_empty():
self.head = node # 若链表为空,头结点指针指向首元素
else:
current_node = self.head # current_node先初始化为头指针,从头开始遍历
while current_node.next: # 会依次更改结点的指针域
current_node = current_node.next
current_node.next = node # 最后一个结点加上node的地址
self.length += 1 # append了一个结点,长度增加
return
# 结点插入操作
def insert(self, value, index): # value插入值,index插入位置
if index > self.length: # 保证插入到链表中
print ("Index value is out of range")
return
else:
insert_node = ListNode(value) # 创建插入的结点
current_node = self.head # current_node先初始化为头指针,从头开始遍历
if self.is_empty():
self.head = insert_node # 索引值为0,将放到第一个结点处,头结点直接指向插入结点
current_node.next = insert_node # 相当于把之前head 指向的地址,给了insert_node的next
return
elif index == 0:
self.head = insert_node # 索引值为0,将放到第一个结点处,头结点直接指向插入结点
while index - 1: # 只有index,无法直接找到第index结点,所以需要依次更新current_node
current_node = current_node.next
index -= 1
# 将当前结点与后一个结点拆开,node 指向后一个结点,前一个结点指向node
current_node.next = insert_node
current_node = insert_node.next
self.length += 1
return
# 结点删除操作
def delete(self, index):
if index > self.length:
print("The index value is out of range!")
return
else:
current_node = self.head # current_node先初始化为头指针,从头开始遍历
if index == 0:
# current_node = current_node.next #current_node.next表示要删除点的地址
# self.head = current_node.next
pass
while index - 1:
current_node = current_node.next
index -= 1
# 将前一结点的指针域指向后一结点的地址
current_node = current_node.next.next
self.length -= 1
return
# 修改结点
def update(self, index, data): # 将index位置上的值修改成data
if index > self.length:
print("The index value is out of range!")
return
else:
current_node = self.head # current_node先初始化为头指针,从头开始遍历
if index == 0:
current_node = current_node.next
while index - 1:
current_node = current_node.next
index -= 1
current_node.data = data
return
# 获取某个结点的值
def get_value(self, index):
if index > self.length:
print("The index value is out of range!")
return
else:
current_node = self.head # current_node先初始化为头指针,从头开始遍历
if index == 0:
current_node = current_node.next
while index - 1:
current_node = current_node.next
index -= 1
data = current_node.data
return data
#清除链表
def clear(self):
self.head = None
self.length = 0
# # 翻转链表
# def reverse(self):
# L = []
# for i in range(self.length):
# val = self.get_value(i)
# L.append(val)
# L.reverse
# for i in range(self.length):
# self.update(i, L[i])
# return
# 打印链表
def print_linkedList(self):
if self.is_empty():
print ("The linked list is empty")
else:
current_node = self.head # current_node先初始化为头指针,从头开始遍历
while current_node.next:
current_node = current_node.next
print(current_node.data, '->',end='')
l_1 = ListNode(2)
l_2 = ListNode(4)
l_1.next = l_2 #python中变量名就是指针
l_3 = ListNode(6)
l_2.next = l_3
node = ListNode(7)
list = LinkedList()
print(list.get_length(l_1))
list.print_linkedList()
list.append(node)
list.print_linkedList()
print(list.length)
list.insert(1, 3)
list.print_linkedList()
print(list.length)
list.delete(2)
list.print_linkedList()
print(list.length)
list.update(2, 10)
list.print_linkedList()
print(list.get_value(2))
list.print_linkedList()
list.reverse()
list.print_linkedList()
欢迎批评改正!!!