首页 > 其他分享 >面相对象(三):模拟链表

面相对象(三):模拟链表

时间:2024-04-11 12:11:38浏览次数:24  
标签:结点 cur self next 链表 面相 节点 模拟

面向对象的基本原理是对对象建模,让抽象的逻辑封装成具象的行为,更方便人们理解和使用。在前面的文章中我写了关于继承的一些理解,一般来说这里应该讨论与继承同为面向对象三个主要特征的多态与封装了。但是我想多态与封装是一种伴随着类的定义自然而然形成的现象,只有先接触了一定数量的类对象,我们才能更好地理解多态;也只有对一个类有了切实的应用,才能更好体会封装的精妙。因此,这些内容不会直接出现在这里。今天我希望分享的是如何去运用类创建一个链表。

链表由一系列结点(链表中每一个元素称为结点)组成,每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域

以上是百度百科中关于链表的描述。需要说明的是,在本文中,我们只讨论最基础的单向无循环链表,实际业务中,链表可能会比基础形态更加复杂。链表的每个结点,都只有一个前驱结点和一个后继结点,因此会形成一个结点串。
链表的优点是,由于只需要更改结点的地址域就可以实现元素的插入和删除,不需要像列表一样对更改之后的全部元素索引进行整体调整,因此在进行这两个操作时较为高效。与普通列表相比,链表利用了内存中的零碎空间,将整个表格分成一个个的结点,分别存到内存空着的地方,因此在处理内存空间时比较灵活。但是缺点是由于链表不存储索引,当需要取出固定位置的元素值时,链表必须从头开始按图索骥,来找到目标,这意味着链表的查改效率相对不高。实践中,我们会根据业务需求进行使用。

现在让我们来建模一个最基础的单向无循环链表。

  1. 定义结点
    显然,链表中的结点可以被建模成一个类。这个类应该有两个属性,即数值域和地址域。单个结点在创建时应该输入数值域,而地址域则应该赋值为None,因为他还没有被加入到链表中。
点击查看代码
class SingleNode(object):
    def __init__(self, data):
        self.item = data
        self.next = None
  1. 定义整条链表
    有了结点,我们就有了形成链表的基本单位。链表对象应该拥有一些行为可以让我们来操作这些结点。但是首先,我们必须要有结点。所在在创建链表对象时,先应该传入第一个结点对象,并将其设置为我们的头结点(即链表开始的地方)。头结点会在每次链表被访问时第一个被访问到,在单向无循环链表中,没有结点的地址域会指向头结点。
点击查看代码
class SingleLinkedList(object):
    def __init__(self,node=None):
        self.head = node  # 将传入的节点作为头节点
  1. 为链表添加功能-头插法与尾插法
    头插法是指在链表头部添加结点,而尾插法恰恰相反。注意我们每次插入一个值,都是要将其先实例化为一个结点,之后才可以进行操作。
点击查看代码
    def add(self,item):              # 头插法
        new_node = SingleNode(item)  # 创建新节点
        new_node.next = self.head    # 将新节点的next指针指向原本的头节点
        self.head = new_node         # 并将新节点作为头节点
    def append(self,item):           # 尾插法
        new_node = SingleNode(item)
        cur = self.head              # 将当前结点定位到头结点
        while cur:                   # 遍历链表,找到最后一个节点
            if cur.next ==None:
                cur.next = new_node  # 将新节点添加到链表尾部
                break
            else:
                cur = cur.next
        else:
            self.head = new_node    # 如果没有进入while循环,说明头结点为空,则直接将新节点作为头节点
  1. 为链表添加功能-遍历与查看链表长度
    遍历链表只需要按顺序输出每个结点的数值域,并顺着地址域找到下一个结点即可。
    查看长度在此基础上进行统计即可。
点击查看代码
    def length(self):      # 计算链表长度
        cur =self.head
        count = 0
        while cur:         # 由于初始条件为count=0,每次拿到一个非空结点之后count+1,并将cur指向下一个结点即可 
            count += 1    
            cur = cur.next
        return count
    def travel(self):        # 遍历链表
        cur = self.head
        while cur:
            print(cur.item)
            cur = cur.next
  1. 为链表添加功能-在指定位置插入值
    正常情况下在指定位置插入值只需要将原本位于此处的结点地址域打开,并将新的结点接入即可。
点击查看代码
    def insert(self,pos,item):
        if pos <= 0:
            self.add(item)
        elif pos > self.length():
            self.append(item)
        else:
            count =0
            cur = self.head
            while count < pos-1:        # 通过循环找到插入位置的前一个节点
                count += 1
                cur = cur.next
            new_node = SingleNode(item)
            new_node.next = cur.next    # 将新节点的next指针指向原本的cur节点的下一个节点
            cur.next = new_node         # 将原本的cur节点的next指针指向新节点
  1. 为链表添加功能-删除指定值
    删除值的操作一般不需要指定位置,而是通过值来判断。最基础的情况下,我们只删除找到的第一个结点,并将他前一个结点的地址域直接指向它的下一个结点,以此来让这个结点处于无法被找到的状态(但他并未被从内存中删除)
点击查看代码
    def remove(self,item):
        cur = self.head
        if cur ==None:             # 如果链表为空,则直接返回
            print(f'链表为空,不存在{item}')
            return
        elif cur.item == item:     # 如果头节点就是要删除的节点,则直接将头节点指向下一个节点
            self.head = cur.next
            return
        count =0
        while cur:
            count +=1
            pre = cur              # 用pre记录前一个节点
            cur = cur.next
            if cur.item ==item:
                pre.next =cur.next  # 将pre节点的next指针指向cur节点的下一个节点
                return
        print(f'未找到{item}')       # 如果没有找到要删除的节点,则打印提示信息
  1. 为链表添加功能-搜寻某个值是否在链表中
    此功能较为简单,就不再补充代码。

以上,就是对于链表的建模,实现了链表的基本功能。

标签:结点,cur,self,next,链表,面相,节点,模拟
From: https://www.cnblogs.com/maninfirer/p/18128305

相关文章

  • 数据结构之链表(c语言版)
    链表是线性表,链表的特点就是可以动态增减元素。种类有单向链表、双向链表,循环链表。一、单链表单链表的储存思想使用指针表示节点之间的逻辑关系,它的储存单元可以连续也可以不连续,每个储存单元需要储存信息和储存与后继节点的地址信息,储存单元又称之为节点。单链表由头指针唯......
  • 链表(java语言版)
    链表(Linkedlist)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。使用链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域......
  • C语言简单的数据结构:单链表的有关算法题(1)
    算法题重点在于思路,代码其实并不难,这里的每一题都提供多种思路,大家可以动手写一下,并找到更好的解题方法这里先介绍前三道题目:1.单链表相关经典算法OJ题1:移除链表元素2.单链表相关经典算法OJ题2:反转链表3.单链表相关经典算法OJ题4:链表的中间结点1.单链表相关经典算......
  • C语言简单的数据结构:单链表
    目录:1.单链表的概念及结构2.单链表的实现2.1单链表的定义、创建和打印2.11单链表的定义2.12单链表的创建2.13单链表的打印2.2单链表的头插和尾插2.21尾插2.22头插2.3单链表的头删和尾删2.31尾删2.31头删2.4单链表的查找2.5单链表指定位置的插入和删除2.51指定位置前......
  • 模拟开关芯片 BL1551B中文资料 BL1551B引脚图及功能说明
     BL1551B是一款由贝岭(上海)微电子技术有限公司(ShanghaiBellingCo.,Ltd.)生产的模拟开关芯片。以下是关于BL1551B的功能和参数介绍:功能:BL1551B是一款高性能、低功耗的模拟开关芯片,适用于音频、视频和其他模拟信号的切换和控制。内置两个单刀双掷(SPDT)开关,可实现两路信......
  • 模拟机4.0
    这次新加了一个手机,有更多内容了对话也没有那么僵硬了还修复了星期0的bug星期改为汉字显示#include<iostream>#include<cstring>#include<cstdio>#include<cmath>#include<cstdlib>usingnamespacestd;inthuida;charmi[100],weekdays[7][7]={"一","二"......
  • C语言单链表代码实现
    声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。设计算法,实现线性结构上的单链表的产生以及元素的查找、插入与删除,求表长、有序表插入、元素逆置、2个有序表合并等。#include<stdio.h>#include<stdlib.h>//单链表的定义:typedefintDataType......
  • 数据结构:单链表
    一.链表的概念及结构概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。但是在逻辑结构上是顺序的。链表的结构其实就像的火车:车厢是独立存在的,且每节车厢都有车门。想象⼀下这样的场景,假设每节车厢的车门都是锁......
  • JZ24-反转链表
    /***structListNode{* intval;* structListNode*next;* ListNode(intx):val(x),next(nullptr){}*};*/#include<cstddef>classSolution{public:/***代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可*......
  • JZ06-从尾到头打印链表
    /***structListNode{*intval;*structListNode*next;*ListNode(intx):*val(x),next(NULL){*}*};*/#include<cstddef>classSolution{public://输入一个链表的头节点,按链表从头到尾的顺序返回每个......