数据结构与算法:python语言描述学习笔记Part3_1

用python实现

  • 不带头结点的单链表
  • 改进的单链表——既有头指针也有尾指针
  • 循环单链表
# -*- coding:utf-8 -*-

from __future__ import print_function

# 异常
class LinkedListUnderflow(ValueError):
pass

# 单链表节点类
class LNode:
def __init__(self, elem, next_= None):
self.elem = elem
self.next = next_
'''
# 测试单链表节点类
llist1 = LNode(1)
p = llist1

for i in range(2, 11):
p.next = LNode(i)
p = p.next

p = llist1

while p is not None:
print(p.elem)
p = p.next
'''

# 单链表类
class LList:
def __init__(self):
self._head = None
self.length = 0
# 链表长度
def __len__(self):
return self.length

# 判空
def is_empty(self):
return self._head is None

# 前端插入
def prepend(self, elem):
self._head = LNode(elem, self._head)
self.length += 1
# 后端插入
def append(self, elem):
if self._head is None:
self._head = LNode(elem)
return
p = self._head
while p.next is not None:
p = p.next
p.next = LNode(elem)
self.length += 1

# 插入指定位置
def insert_data(self, elem, index):
if index > self.length:
raise LinkedListUnderflow( 'in insert_data')
p = self._head
if index == 1:
self.prepend(elem)
for i in range( 1, index- 1):
p = p.next
n = LNode(elem)
n.next = p.next
p.next = n
self.length += 1

# 弹出表头元素
def pop(self):
if self._head == None:
raise LinkedListUnderflow( 'in pop')
e = self._head.elem
self._head = self._head.next
self.length -= 1
return e

# 弹出表尾元素
def pop_last(self):
if self._head is None: # 空表
raise LinkedListUnderflow( 'in pop_last')
p = self._head
if p.next == None: # 表中只有一个元素
e = p.elem
self._head = None
self.length -= 1
return e
while p.next.next is not None: # 直到p.next是最后节点
p = p.next
e = p.next.elem
p.next = None
self.length -= 1
return e
# 删除指定位置的元素
def del_index(self, index):
if index > self.length:
raise LinkedListUnderflow( 'in del_index')
if index == 1:
self.pop()
p = self._head
for i in range( 1, index- 1):
p = p.next
e = p.next.elem
p.next = p.next.next
self.length -= 1
return e

# 查找指定位置的表元素
def find_data(self, index):
if index > self.length:
raise LinkedListUnderflow( 'in find_data')
p = self._head
for i in range( 1, index):
p = p.next
return p.elem
# 查找指定元素的位置
def find_index(self, data):
if self._head is None:
raise LinkedListUnderflow( 'in find_index')
p = self._head
count = 1
while p.next is not None:
if data == p.elem:
return count
else:
count += 1

# 打印所有表元素
def printall(self):
p = self._head
while p is not None:
print(p.elem, end= '')
if p.next is not None:
print( ', ', end= '')
p = p.next
print( '')


# 定义遍历函数
def for_each(self, func):
p = self._head
while p is not None:
p.elem = func(p.elem) # func的实参是可以作用于表元素的操作函数
p = p.next
# 定义迭代器
def elements(self):
p = self._head
while p is not None:
yield p.elem
p = p.next
# 筛选生成器
def filter(self, pred):
p = self._head
while p is not None:
if pred(p.elem):
yield p.elem
p = p.next
# 删除链表
def del_list(self):
self._head = None
self.length = 0
l = LList()
# 头插法生成链表
for i in range( 1, 11):
l.prepend(i)

# 测试插入表头
l.prepend( 3)

# 测试插入111到第一个位置,插入12到第3个位置
l.insert_data( 111, 1)
l.insert_data( 12, 3)

# 测试删除第三个位置的12,删除第一个位置的111
print(l.del_index( 3))
print(l.del_index( 1))

# 测试链表长度
print(len(l))

# 打印所有元素
l.printall()

# 查找第三个元素
print(l.find_data( 3))

# 查找元素7的位置
print(l.find_data( 7))

# 测试遍历函数
l.for_each( lambda x: x*x)
l.printall()

# 测试迭代器
for x in l.elements():
print(x)

# 测试筛选生成器,打印多个符合条件的元素
def pr(y):
if y == 9:
return y
for x in l.filter(pr):
print(x)

# 单链表的简单改进版本——带有尾结点引用的单链表,因为之前的单链表尾端加入元素操作效率低
class LList_improve(LList):
def __init__(self):
LList.__init__( self)
self._rear = None # 尾指针
# 头插法的重新定义
def prepend(self, elem):
if self._head is None: # 是空表
self._head = LNode(elem, self._head)
self._rear = self._head
else:
self._head = LNode(elem, self._head)
# 尾插法的重新定义
def append(self, elem):
if self._head is None:
self._head = LNode(elem, self._head)
self._rear = self._head
else:
self._rear.next = LNode(elem) # next为空,因为是最后一个结点
self._rear = self._rear.next

# pop无需重新定义,因为同一使用_head为None判断空表有关

# 弹出末元素的操作
def pop_last(self):
if self._head is None: # 是空表
raise LinkedListUnderflow( 'in pop_last')
p = self._head
if p.next is None: # 表中只有一个元素
e = p.elem
self._head = None
return e
while p.next.next is not None: # 直到p.next是最后结点
p = p.next
e = p.next.elem
p.next = None
self._rear = p
return e

# 测试带尾指针的单链表
print( '-------------')
mlist1 = LList_improve()
mlist1.prepend( 99)
for i in range( 11, 20):
mlist1.append(i)
mlist1.printall()

for x in mlist1.filter( lambda y: y % 2 == 0):
print(x)

# 循环单链表的类,最后一个结点指向不为空,而是指向头结点
# 选择尾指针而不是头指针,访问头尾会更方便
class LCList:
def __init__(self):
self._rear = None
def is_empty(self):
return self._rear is None

# 前端插入
def prepend(self, elem):
p = LNode(elem)
if self._rear is None:
p.next = p
self._rear = p
else:
p.next = self._rear.next
self._rear.next = p

# 尾端插入
def append(self, elem):
self.prepend(elem)
self._rear = self._rear.next # 相当于先头插了,然后再把尾指针移过去,反正是个循环,想怎么指都行咯
# 前端弹出
def pop(self):
if self._rear is None:
raise LinkedListUnderflow( 'in pop of LCList')
p = self._rear.next
if self._rear is p: # 只有一个结点
self._rear = None
else:
self._rear.next = p.next
return p.elem
# 输出表元素
def printall(self):
if self.is_empty():
return
p = self._rear.next
while True:
print(p.elem)
if p is self._rear:
break
p = p.next

# 测试循环单链表
print( '-------------')
mlist2 = LCList()
mlist2.prepend( 99)
for i in range( 11, 20):
mlist2.append(i)
mlist2.printall()

猜你喜欢

转载自blog.csdn.net/dmbjzhh/article/details/79463812