数据结构+算法=程序
所以一个优秀的程序员应该是要懂一点数据机构和常见的算法的哈(所以目前正在向一个优秀的程序员努力)
关于数据结构及算法的博客整理会根据我的学习进度同步推进,希望和大家多多探讨交流
好了废话不多说,单项链表的python实现具体代码如下(注释感觉写的差不多了就不对里面的代码进行详细解释了,如果大家有什么见解或者是更好的方法或者是我的代码哪里有不准确的地方欢迎给我留言或者qq(1312625658)探讨)
# -*- coding:utf-8 -*-
"""
数据结构之单项链表(Python实现)
特点:动态数据结构,合理利用内存空间,没有大小限制,插入删除方便,但是查询较慢,需从链表头依次遍历
描述:链表中的每一个元素都可以看作一个节点对象,包含两部分:元素本身的值和指向下一个元素的指针
"""
# 定义一个节点对象,该对象由其本身的值value和指向下一个对象的指针next构成
class Node(object):
def __init__(self, value=None):
self.value = value
self.next = None
# 单项链表必须有一个头元素
class SingleLinkedList(object):
# 所以初始化时只需要定义一个头元素即可
def __init__(self, head):
self.head = head
#重写__str__方法,返回一个友好的显示(默认显示对象的内存地址)
def __str__(self):
return str(self.look())
# __str__方法是在程序中调用print()方法时调用,__repr__方法是在交互式环境中直接输出对象时使用
__repr__ = __str__
# 遍历链表
def look(self):
p = self.head
lst = []
while p:
lst.append(p.value)
p = p.next
return lst
# 获取链表长度方法
def length(self):
p = self.head
i = 1
while p.next:
i += 1
p = p.next
return i
# 添加元素方法
def add(self, value):
p = self.head
new_node = Node(value)
while p:
if not p.next:
p.next = new_node
break
p = p.next
# 删除元素方法(只删除匹配到的第一个元素)
def remove(self, value):
p = self.head
while p.next:
temp = p.next
if temp.value == value:
p.next = temp.next
del temp # 释放内存空间
break
else:
p = p.next
# 删除所有匹配的元素
def remove_all(self, value):
p = self.head
while p.next:
temp = p.next
if temp.value == value:
p.next = temp.next
del temp
else:
p = p.next
# 在指定位置插入元素(如果index大于等于链表长度则插入末尾)
def insert(self, index, value):
p = self.head
if index >= self.length():
while p.next:
p = p.next
p.next = Node(value)
i = 0
while p.next:
temp = p.next
i += 1
if i == index:
p.next = Node(value)
p.next.next = temp
p = p.next
# 查找指定位置的元素
def index(self, index):
p = self.head
if index >= self.length():
raise IndexError("查找范围超出链表长度")
i = 0
while p:
if i == index:
return p.value
p = p.next
i += 1
# 查找指定元素的位置(找不到返回-1)
def find(self, value):
p = self.head
i = 0
while p.next:
if p.value == value:
return i
p = p.next
i += 1
return -1
# 链表反转([None, 2, 3]--->[2, 3, None])
def reverse(self):
p = self.head
if p is None or p.next is None:
return p
q = p.next
p.next = None
while q:
r = q.next
q.next = p
p = q
q = r
return p # p是一个Node对象
if __name__ == '__main__':
s = SingleLinkedList(Node()) # 链表头一般不存放值,即value为None,用来表明这是链表的头部
print(s, '长度为: %i' % s.length())
s.add(1) # 添加几个value值相同的元素 用来查看remove和remove_all方法的区别
s.add(2)
s.add(1)
s.add(3)
s.add(1)
print(s, '长度为: %i' % s.length())
s.remove(1)
print(s, '长度为: %i' % s.length())
s.remove_all(1)
print(s, '长度为: %i' % s.length())
s.insert(2, 222)
print(s, '长度为: %i' % s.length())
s.insert(8, 222)
print(s, '长度为: %i' % s.length())
try:
print(s.index(5)) # 抛出IndexError异常,为了后续代码的正常运行在该处捕获异常并使程序继续执行
except IndexError as e:
print(e)
print('第一个value值为222的元素的位置是:\n%i' % s.find(222))
print('原链表为:\n%s' % s)
s = SingleLinkedList(s.reverse()) # 将返回的Node对象封装成一个链表对象即为反转后的链表
print('反转后的链表为:\n%s' % s)
只要理解了数据结构的原理,其实用代码很好实现的,该代码的主要难点在于链表的反转,其思想是:
1.从头元素开始,先取出头元素(p)和它的下一个元素(q),然后头元素指向None变为最后一个元素
2.从头元素(p)中的下一个元素(q)开始遍历,同样的,要想将第二个元素,也就是当前q元素放在倒数第二个位置上,那我们需要先取出它的下一个元素,也就是代码中的r元素,然后将q元素指针指向最后的一个元素(p),此时,再下一个元素就不是指向最后的p元素了,而是指向反转后的倒数第二个元素,也就是q元素,所以需要将q赋值给p,然后r元素赋值给正向链表的下一个元素q继续遍历,一直到结束。