一个普通的单链表(一个指针域),对于其最重要的就是单链表的头指针,通过头指针可以确定单链表的一些属性,如:是不是空的,通过头指针进行遍历等。
我们用python做一个单链表的类实现,要求可以建立一个空的单链表,还要能够实现一些单链表的基本操作,如判断是不是空的,头部尾部插入,删除,遍历等
首先就是定于一个链表节点的类:
class LNode:
def __init(self, elem, next = None):
self.elem = elem
self.next_ = next
# 定义一个空的错误类,必须继承自基础的错误类
class LListValueError(ValueError):
pass
接下来建立链表的类:
class LList:
def __init__(self):
self._head = None
# 那么初始化链表类就是建立了一个空链表
# 首先是一个判断空的方法
def is_empty(self):
return self._head == None
# 接下来用于在头部插入一个节点
def prepend(self, elem):
self._head = LNode(elem, self._head)
# 这是最简单的实现方法
# 一个头部删除的方法
# 注意删除,我们不能删除一个空链表,那么就需要使用定义的错误类
def pop_first(self):
if not self._head:
raise LListValueError(“wrong”)
e = self._head.elem
self._head = self._head.next
return e
# 直接将头指针指向下一个节点,抛弃原头节点,python会自动回收
# 其储存空间的
# 接下来是尾部插入
def append(self, elem):
p = self._head
while p:
if not p.next_:
p.next_ = LNode(elem)
return
p = p.next
self._head = LNode(elem)
# 这里有两种情况,一种是空表,这是直接等于就可以了
# 其他的遍历到最后一个元素,然后将他的next指针指向这个新建的元素
# 这里有个变量p,我们称之为扫描指针。
# 对于尾部删除,有三种情况:空表,一个元素,两个及以上的元素
def pop_last(self):
if not self._head:
raise LListValueError("wrong")
if not self._head.next:
self._head = None
p = self._head
while p.next.next:
p = p.next
e = p.next.elem
p.next = None
return e
# 最后关于表的遍历问题,我们对于表的遍历问题
# 对于这种汇集对象来说,对其中的各个对象进行一些操作是很常见的,
# 我们除了可以从头指针顺着找下去之外,还有一些是对特定元素进行的操作
# 主要实现后者
def for_each(self, operate):
p = self._head
while p:
operate(p.elem)
p = p.next
# 其实还有一个就是关于python迭代器的,python的主要迭代工具就是迭代器
# 用yield关键字生成一个生成器函数是一个很好的选择
def elements(self):
p = self._head
while p:
yield p.elem
p = p.next
这就是一个链表类的实现。
如果深入理解链表的实现的话,可以看出self._head是头节点,但不是第一个节点,它本身是一个只包含指针域的链表对象,而这个指针就是指向链表的第一个节点。
对于更复杂的链表对象来说,我们还可以存储链表的长度,链表的尾指针等,这就需要为链表对象设计一个数据结构(一个类)
`
我在网上盗了一张图,用以说明单链表的结构
由图可以看出,first就是头指针,它不是一个节点,而是存在有第一个节点引用的“结构”吧!
所以我们叫first为链表对象,其实它不止可以保存第一个节点的引用,还以保存链表的长度,尾节点的引用或者都包含。如果我们需要有链表的长度的话,可以定义一个链表对象的类
class listObj:
def __init__(self):
self.node_num = 0
self.head = None
这样我们手动加入节点数目的代码就行了
完整代码
循环链表本质上只是列表对象的结构不一样,
class cirListObj:
def __init__(self):
self.head = None
self.nodeNum = 0
self.rear = Node
至于双向链表呢,只是节点的结构不一样:
class douLNode:
def __init__(self, elem, prev = None, next = None):
self.prev = prev
self.elem = elem
self.next = next
上面两种的具体实现,后面!
参考《数据结构与算法 python语言的实现》,强推这本书!!!