简单易懂的Python链表基础知识源代码版

# 在单向链表中,每一个节点都是一个对象
# 节点类

class LNode:
    def __init__(self, elem, next_=None):
        self.elem = elem
        self.next = next_


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

p = list1
while p is not None:  # 可以直接写为while p
    print(p.elem)
    p = p.next


# 基于节点类LNode定义一个单链表对象的类
class LList:
    def __init__(self, head):
        self._head = None  # _head是链表的头节点,因为_head域作为对象的内部表示,
        # 不希望外部使用,所以习惯上用单个下划线开头
        # _head作为判断表是否空的标志

    def is_empty(self):      # 判断是否为空
        return self._head is None

    def prepend(self, elem):  # 在表头插入数据
        self._head = LNode(elem, self._head)

    def pop(self):
        if self_head is None:  # 删除表头结点,如果没有就引发异常
            raise LinkedListUnderflow("in pop")
        e = self._head.elem
        self._head = self._head.next
        return e

    # 后端操作
    # 在链表的最后插入元素

    def append(self, elem):
        if self._head is None:
            self._head = LNode(elem)
            return
        p = self._head
        while p.next:
            p = p.next
        p.next = LNode(elem)

    # 删除链表最后的元素
    def pop_last(self):
        if self._head is Nono:  # 那就说明是空表
            raise LinkedListUnderflow("in pop_last")
        p = self._head
        if p.next == None:  # 链表只有一个元素
            e = self.elem
            self._head = None
            return e
        while p.next.next is not None:  # 直到p.next是最后的节点
            p = p.next
        e = p.next
        p.next = None
        return e

    # 找到满足给定条件的表元素
    def find(self, pred):
        p = self._head
        while p is not None:
            if pred(p.elem):
                return p.elem
            p = p.next

    # 查看被操作的表当时的情况
    def printall(self):
        p = self._head
        while p:
            print(p.elem, end=' ')
            if p.next is not None:
                print(',', end='')
            p = p.next
        print('')

    # 迭代器的使用
    # yield的使用非常关键,具体的用法可以百度
    # 可以把yield看成是一个逐个输出的过程
    def elements(self):
        p = self._head
        while p:
            yield p.elem
            p = p.next


# 调用迭代器
for i in list1.elements:
    print(i)

    # 筛选生成器:对所有满足条件的元素进行处理
    # 也是生成器的一种
    def filter(self, pred):
        p = self._head
        while p:
            if pred(self):
                yield p.elem
            p = p.next


# 链表的使用
mlist = LList(1)
for i in range(10):
    mlist.prepend(i)
for i in range(11, 20):
    mlist.append(i)
mlist.printall()
循环单链表类
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 CLList")
        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)
            if p is self._rear:
                break
            p = p.next
链表的两个特别的操作
反转
# 节点类
class LNode:
    def __init__(self, elem, next_=None):
        self.elem = elem
        self.next = next_
# 链表的操作
# 链表反转
# 把链表想象成一摞书就可以了


def rev(self):
    p = None
    while self._head is not None:
        q = self._head
        self._head = q.next  # 头节点往下移动
        q.next = p
        p = q  # p是新表中的第一个元素
    self._head = p  # 重置新的表头链接
链表排序,

采用插入排序的思想
先通过列表看看基本思想

def list_sort(lst):
    for i in range(1, len(lst)):  # 默认[0:1]相当于已经排好了序
        x = lst[i]
        j = i
        while j > 0 and lst[j-1] > x:
            lst[j] = lst[j-1]
            j -= 1
        lst[j] = x

对于单链表使用插入排序有两种思路,一种是通过更换元素的大小进行,另外一种是调整各个节点的链接关系

考虑第一种,更换元素
def sort1(self):
    if self._head is None:
        return
    crt = self._head.next
    while crt is not None:
        x = crt.elem
        p = self._head
        while p is not crt and p.elem <= x:  # 逐个比较,跳过小的
            p = p.next
        while p is not crt:
            y = p.elem
            p.elem = x
            x = y
            p = p.next
        crt.elem = x
        crt = crt.next
考虑第二种,通过改变元素之间的链接
def sort(self):
    p = self._head
    if p is Noen or p.next is None:
        return

    rem = p.next
    p.next = None
    while rem is not None:
        p = self._head
        q = None
        while p is not None and p.elem <= rem.elem:
            q = p
            p = p.next
        if q = None:
            self._head = rem
        else:
            q.next = rem
        q = rem
        rem = rem.next
        q.next = p
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值