python数据结构上机_python数据结构与算法学习笔记(一)

好久没有写了,今天来开个新坑。最近在看数据结构与算法,因为比较熟悉python语言,就选择了它的python语言版本来学习,现在就记录一下。

无序列表的实现

我们需要构造一个链表来实现无序列表。链表,顾名思义是前后两项之间有连接的数据结构,它不受限与连续的内存空间,而是通过每一个结点的指针域来找到它的下一个结点(后继),因此链表的增删十分方便,更改指针域指针的指向即可,而不用调整大量数据的存储位置。

构造结点类

首先需要构造链表中的基本元素:结点(Node)

class Node:

def __init__(self,initdata):

self.data = initdata

self.next = None

def getData(self):

return self.data

def getNext(self):

return self.next

def setData(self,newdata):

self.data = newdata

def setNext(self,newnext):

self.next = newnext

每个结点包括两个组成部分,数据(data)和指向它的后继的指针(next)。

构造无序列表类

接着就是无序列表(UnorderedList)本体的构造

class UnorderedList:

def __init__(self):

self.head = None

在构造链表时,头指针(head)是必须的,它指向链表中的第一个结点,如果是空链表就为None。有时,为了操作的统一,链表还会有头结点,头指针指向它,它的后继是链表的第一个结点,而它的数据域是无意义的,可以存放链表长度等公共信息。一个链表头指针必须有但头结点可以没有。

定义方法

接下来我们来定义无序列表的各种方法。

isEmpty

判断无序列表是否为空

add

向无序列表中增加元素

由于是无序列表,新增结点的位置无关紧要,并且链表本身维护了一个头指针,指向链表头部,所以直接在链表头部新增结点最简单。

注意这里必须先设定新增结点的后继为第一个结点,再更改头指针的指向,否则会导致链表其他结点丢失,无法访问。

size

返回无序列表的元素个数

最后一个结点的next是None,所以后继为None时表示已经到达列表尾部,循环结束。

search

查询无序列表中是否有指定元素

remove

移除无序列表中的指定元素

删除操作需要找到指定的元素,然后把它的前驱和它的后继连接起来,由于链表不能通过当前结点得到它的前驱,所以这里设置了一个previous变量,用来存储当前结点的前驱。

循环结束时如果previous仍然时None,说明我们要找的元素就在第一个位置,此时不能把它的前驱(previous)和后继(getNexTt)相连,因为此时previous是NoneType,并不是结点类。此时我们只要把链表头指针的指向设置为当前结点的后继即可。

这里我们假定指定的元素在无序列表中存在。

index

查询指定元素在无序列表中的索引

这里依然假定指定的元素在无序列表中存在。

insert

在无序列表的指定位置插入指定元素

这里通常的做法是和remove操作一样,设置一个previous,在找到指定位置后,把temp设为当前结点的前驱,previous的后继。也可以像我这样,做个小改动,把pos为0的情况单独处理,定位之后把temp设为当前结点的后继的前驱,当前结点的后继。注意这时需要向后多判断一个位置,即if i+1 == pos:

这里假定指定的位置不会超出无序列表的大小。

append

在无序列表尾部添加元素

通常的做法是以后继为None为终止条件循环找到链表尾,把新增结点设为尾部结点的后继。这样时间复杂度为O(n)

一种偷懒的做法是通过size()方法得到整个无序列表的长度,在通过insert()方法,以长度减1为参数在列表尾部插入新增元素,但这样更加耗时,因为有两个时间复杂度为O(n)的操作。

但是如果在无序列表类中多维护一个尾结点的属性,同时小改动一下add方法,就会简单很多。

这时append方法的时间复杂度仅为O(1)。

rear为None表示列表为空,此时add方法需要更新rear属性的值,并且append操作等价于add操作。

同时需要注意在append方法中设定rear的后继和更新rear的顺序,顺序相反会导致添加结点失败。

pop

从无序列表中删除并返回指定位置的元素,如果不指定位置,则删除并返回最后一个元素

和删除操作一样,这里需要新增一个previous变量来记录当前结点的前驱。定位后previous仍然为None时说明当前时链表头部,更改头指针的指向即可。

这里可以体现出python动态语言的方便之处,如果是其他静态语言,我们需要定义两个函数pop(self)和pop(self,pos)用来实现两个不同情况下的操作。这里我们只需要将pos参数设置默认为-1来表示不指定位置在尾部操作的情况,因为指定的位置不可能是-1。

注意不指定位置参数在尾部操作时需要更新尾结点rear属性。

这样我们就基本实现了无序列表的构造。但是python内置的list并不是这样的,从方法的时间复杂度上可以看出,我们的pop()方法是O(n),但python内置list的pop()方法是O(1)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值