数据结构与算法01(python实现)__单链表的实现

以下代码以OOP(面向对象)的思想实现ADT(Abstract Data Type),基于python,其中python对定义变量实质是引用(类似C语言的指针)的思想贯彻全篇代码

复制代码
# 节点的实现
class Node(object):
    '''节点保存,数据+地址'''
    def __init__(self, item):
        self.item = item
        self.next = None

# 链表的实现
class SingleLinkList(object):
    '''链表,找到节点+实现操作'''
    def __init__(self):
        # 通过head指向头节点,即可找到其他节点
        self.__head = None

    # 实现链表的各种操作

    def is_empty(self):
        '''判断链表是否为空'''
        # 如果链表为空,self__head指向None; 不为空,则not None
        return self.__head is None  # 空 == True;非空 == False

    def add(self, item):
        '''头插法,链表头部增加节点'''
        node = Node(item)  # 实例化节点(数据+next)
        node.next = self.__head  # 1.新增节点指向原首节点
        self.__head = node  # 2.原head指向新增节点
        # 以上满足,原链表为空的特殊情况

    def length(self):
        '''得到链表的长度(节点数量)'''
        cur = self.__head  # 需要一个游标cursor指向节点,通过移动cursor,得到遍历节点的目的
        count = 0
        while cur != None:
            cur = cur.next  # 游标移动至下一节点
            count += 1
        return count
        # 以上满足,原链表为空的特殊情况

    def travle(self):
        '''遍历整个链表,不断输出每个节点的item(数据区)'''
        cur = self.__head
        while cur != None:
            # 如果是空链表,cur没有item属性,但是也进不来循环,所以满足空链表特殊情况
            print(cur.item, end=' ')   # input item, not address(next)
            cur = cur.next
        print()

    def append(self, item):
        '''尾插法, 链表尾部添加节点'''
        node = Node(item)
        cur = self.__head
        # 如果链表为空,需要单独考虑
        if self.is_empty():
            self.__head = node
        else:
            # 链表不为空的情况
            # 遍历到尾部再添加
            while cur.next != None:  # 这里不能让cursor移动到None,因为单链表没法回退,没法添加节点了
                cur = cur.next  # 移动cursor 这相当于循环终止条件,不写死循环!!!
            node.next = None
            cur.next = node

    def insert(self, pos, item):
        '''指定位置添加元素'''
        # assert 0 <= pos <= self.length(), '请输入正确的位置'
        # 可以采用断言抛异常的方式,但是为了程序的健壮性,我们采用以下方式
        node = Node(item)
        # 如果链表为空
        if self.is_empty():
            self.__head = node
        else:
        # 链表非空
            if pos <= 0:
                self.add(node)
            elif pos >= self.length():
                self.append(node)
            else:
                # 中间位置添加
                cur = self.__head
                for num in range(pos-1):  # cursor移动pos-1次,单链表不能回头
                    cur = cur.next
                # cur现在指向我们要添加节点的上一个节点
                node.next = cur.next
                cur.next = node

    def search(self, item):
        '''判断节点是否存在'''
        cur = self.__head
        if self.is_empty():
            return False  # 链表为空,直接F
        while cur != None:
        # while cur.next != None:  # 这么写的话,如果所判断的节点是最后一个,则无法判断了
            if cur.item == item:
                # 如果存在,返回T
                return True
            cur = cur.next
        return False

    def remove(self, item):
        '''删除指定节点'''
        if self.is_empty():
            return None
        # 这里需要两个游标 previous和cursor
        # 要删除一个节点,即使该节点前一个直接指向后一个而跳过它,需要两个游标(单链表不能回退)
        pre = None
        cur = self.__head
        while cur is not None:
           if cur.item == item:
               # 找到了要删除的节点
               if cur == self.__head:
                   # 要删除的是首节点
                   self.__head = cur.next
               else:
                   # 要删除的是中间+尾节点
                   pre.next = cur.next
           pre = cur
           cur = cur.next


if __name__ == '__main__':
    sll = SingleLinkList()
    # sll.append(1000)
    # sll.insert(0, 2000)
    print(sll.is_empty())  # True
    sll.add(100)
    sll.add(200)
    sll.add(300)
    print(sll.is_empty())  # False
    print(sll.length())  # 3
    sll.travle()   # 300 200 100

    sll.append(400)
    sll.travle()  # 300 200 100 400
    print(sll.length())  # 4

    sll.insert(2, 'insert_ele')
    sll.travle()  # 300 200 insert_ele 100 400

    print(sll.search('我在吗'))  # False
    print(sll.search(300))       # True
    print(sll.search(200))       # True
    print(sll.search(400))       # True

    # 300 200 insert_ele 100 400
    sll.remove(300)
    sll.travle()  # 200 insert_ele 100 400
复制代码

 

posted @   胖白白  阅读(290)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示